Given an app that needs to exchange info such as ConsumerKey/ConsumerSecret for oAuth from
- server running "WebApi" over ServiceStack
- consumer is a desktop app
Looking to encrypt the messages using Public/Private keys which are already in place
Is there any support for encrypting/decrypting messages, hopefully transparently ? i.e. the encrypting/decryption is handled via say Filters on the server ?
OR
any workaround on how to do this ?
FYI - the server already requires SSL and requests are authenticated, however the registration is free/automated, hence the need for encryption
Update
The Encrypted Messaging Feature released in v4.0.42 now enables a secure channel for all Services offering protection to clients who can now easily send and receive encrypted messages over unsecured HTTP.
There's no published support for Message Level encryption built into the ServiceStack at the moment, although this is something we're thinking of adding in the future. Below is an example of an approach you could try with ServiceStack today for exploratory purposes (it will require more R&D on your part to come up with a good solid design), and as this is an area that may change in future, it's not a use-case we're supporting right now, but here's something that could work with ServiceStack as it is now:
class EncryptedRequest
{
//Name of the request type
public string Type { get; set; }
//Serialized Request DTO using something like JSON
public string EncryptedBody { get; set; }
//optional: let server the private key that was used (if multiple)
public string PrivateKeyMd5Hash { get; set; }
}
class EncryptedResponse
{
//Name of the response type
public string Type { get; set; }
//Serialized Response DTO
public string EncryptedBody { get; set; }
//optional
public string PublicKeyMd5Hash { get; set; }
}
Here is a convenient CryptUtils wrapper that makes it easy to create Public/Private keys as well as being able to Encrypt/Decrypt text using them.
Then you can have a single service, and do something like:
class EncryptedService : Service
{
const string PublicKey = ...;
const string PrivateKey = ...;
EncryptedResponse Any(EncryptedRequest request)
{
var requestType = Type.GetType("{0}.{1}"
.Fmt(typeof(EncryptedRequest).Namespace, request.Type));
var json = CryptUtils.Decrypt(PrivateKey, request.EncryptedBody);
var requestDto = JsonSerializer.DeserializeFromString(json,requestType);
var responseDto = GetAppHost().Config.ServiceController
.Execute(requestDto, base.RequestContext);
return new EncryptedResponse {
Type = responseDto.GetType().Name,
EncryptedBody = CryptUtils.Encrypt(PublicKey, responseDto.ToJson()),
};
}
}
The client would also need a copy of the Public/Private key pair which you would exchange out-of-band.
Related
I've managed to build a console application that successfully requests API data and converts it into a JSON object. However, I don't know how to put these DTO files (recently stored API objects) into my SQL server.
So far I have this for the console application.
class Program
{
static void Main(string[] args)
{
getRequestData();
}
public static void getRequestData()
{
var client = new RestClient(URL);
var request = new RestRequest();
var response = client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string rawResponse = response.Content;
AllRequests.Rootobject result = JsonConvert.DeserializeObject<AllRequests.Rootobject>(rawResponse);
}
}
}
As you can see, the console application program.cs file successfully obtains a get request then converts the API data into an object (A Json object I think). Here is the DTO file (AllRequests) that the data is being saved into.
class AllRequests
{
public class Rootobject
{
public Operation operation { get; set; }
}
public class Operation
{
public Result result { get; set; }
public Detail[] details { get; set; }
}
public class Result
{
public string message { get; set; }
public string status { get; set; }
}
public class Detail
{
public string requester { get; set; }
public string workorderid { get; set; }
public string accountname { get; set; }
}
}
When testing the application in debug mode, the objects are stored correctly and everything is fine. However, I don't know how to save these objects into an SQL database. I do already have an SQL server, however, I'm not sure how to push the already converted data and save it into a retrospective table. So for instance, saving this data into a Request table in my SQL database.
At the moment I only know how to make API calls in this console application. I can't find any data that will assist me with completing the second part of this task, which is storing the data into an SQL database.
Any help would be greatly appreciated, apologise if there is too much unnecessary information.
There are a few methods to make your application interact with a Database. You can setup your application to use Entity Framework (EF) to manage your DB. It is a powerfull and very popular ORM; there are a lot of resources in the web for help.
Personaly, I like to work with Dapper, that is very simple to use in comparison with EF. You just have to provide your connection-string to create your SqlConnection object.
You can find a simple tutorial in this link.
I avoid EF and other tools frankly. Just more hills to learn.
In .Net 6, I use RestSharp to do the API calls and conversion to JSON and Microsoft.Data.SqlClient to save the data into SQL Server.
Get your API call to respond
var client = new RestClient("your API url");;
Apply the API call
var req = new RestRequest();
req.AddHeader("x-api-key", "your API key");
Get a response object in JSON by default
RestResponse resp = client.Execute(req);
Make sure it worked
if (resp.IsSuccessful) {}
Deserialise your response, where RootObject is my name for my SQL Server table schema as a Class
RootObject ro = new RootObject();
ro = JsonConvert.DeserializeObject<RootObject>(resp.Content);
Build a List<>
//iterate through each device data and add it into a DataRow
List<DeviceClass> device = new List<DeviceClass>();
DataTable dt = GenericList2Datatable<DeviceClass>(device);
//only do anything if the API call worked!
if (!dt.HasErrors)
{
foreach (Device d in ro.Devices)
{
here do your mapping from "ro" object over to data objects like DataRow and DataTable and put them across to SQL server further down. Plenty on the web on how to do that.
The GenericList2Datatable() method I found on the web. Again google it.
public static DataTable GenericList2Datatable<T>(List<T> list)
{}
I might not have worded this question in the correct format as it's difficult to explain what the problem is. From the research I've gathered I think database hierarchy is something that I'm trying to utilize when using Entity Framework to create a database, I'll try to explain my problem in the best way possible.
Firstly, I'm running a Visual Studio 2019 project with a console application. This is my Program.cs file which is currently using a get request from an API URL with RESTSHARP then performing deserialization.
static void Main(string[] args)
{
getAPIData()
}
public static void getAPIData()
{
var client = new RestClient(URL);
var request = new RestRequest();
var response = client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string rawResponse = response.Content;
Requests.Rootobject result = JsonConvert.DeserializeObject<Requests.Rootobject>(rawResponse);
}
}
As you can see above, the raw data that's gathered from the URL (my API) is converted to a JSON format. And when I debug the code, it stores the code perfectly into the Requests DTO, as I'll show below.
public class Requests
{
public int Id { get; set; }
public class Rootobject
{
public Operation operation { get; set; }
}
public class Operation
{
public Result result { get; set; }
public Detail[] details { get; set; }
}
public class Result
{
public string message { get; set; }
public string status { get; set; }
}
public class Detail
{
public string requester { get; set; }
public string workorderid { get; set; }
public string accountname { get; set; }
}
}
The recently converted API data is now stored in this class in this correct format. Which is what's necessary for the API itself since it comes in numerous classes. This object now holds all the relevant data I need, now I can utilize the entity framework to generate an appropriate table that will hold this into an SQL server.
Here is the Entity Framework class.
public class TransitionContext : DbContext
{
private const string connectionString = #"(connection string here)";
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(connectionString);
}
public DbSet<Requests> Requesting { get; set; }
}
Currently, when I run the package manager console commands to build a migration and setup a connection to the server, it works fine (Obviously I've not included my real connection string for privacy reasons). However, when I use the "Update-Database" command from the DbSet which is my DTO for the API data. The only key that is displayed is an ID, nothing else.
SQL requests table
All that's generated here is an Id key from the Requests Dto. Now, on the API itself, there is no ID key, I added it in there because Entity Framework said I had to have an ID key and was displaying errors until I made one. But now that's all it's generating when I "Update-Database".
The reason why I showed as much data as I have done, is because the process is simply exporting the converted JSON data (a recently gathered API) into an SQL table. Or tables so that it supports a hierarchy, anything that will map correctly from the DTO to the database. But as of right now, my only issue with the project is that only an ID is being generated.
So I'm not sure where I'm going wrong here or how to get this working as I intend it to work. Apologies for the really long explanation, I tried to condense it as much as I could, any help would be appreciated and any questions I'm free to answer, thank you!
I'm using Angular js front end application and web API backend. I want to use google recaptcha in the front end application. I can get widget displayed by referring following URL. https://developers.google.com/recaptcha/docs/display. This document doesn't talk about server-side validation with the secret key. But I have noticed some asp.net developers use server side implementation to validate google recaptcha response with the secret key. Do I need to do server-side validation with the secret key and what is the best way to do that in relating to angular and web API?
Yes, you need to do server side validation otherwise your unauthenticated API endpoints aren't protected by direct calls that don't go through your website.
The solution is pretty straight-foward and is detailed here:
https://developers.google.com/recaptcha/docs/verify
But a very simple example of a method that would validated the g-recaptcha-response given by the website would look like this:
public bool Validate(string encodedResponse)
{
if (string.IsNullOrEmpty(encodedResponse)) return false;
var secret = **your secret**;
if (string.IsNullOrEmpty(secret)) return false;
var client = new System.Net.WebClient();
var googleReply = client.DownloadString(
$"https://www.google.com/recaptcha/api/siteverify?secret={secret}&response={encodedResponse}");
return JsonConvert.DeserializeObject<RecaptchaResponse>(googleReply).Success;
}
RecaptchaResponse is a simple class we have that looks like this:
public class RecaptchaResponse
{
[JsonProperty("success")]
public bool Success { get; set; }
[JsonProperty("error-codes")]
public IEnumerable<string> ErrorCodes { get; set; }
[JsonProperty("challenge_ts")]
public DateTime ChallengeTs { get; set; }
[JsonProperty("hostname")]
public string Hostname { get; set; }
}
I am looking for new wcf rest web service in asp.net 4.0 using vs2010.
here is my code for passing url:
"homewizard/Service1.svc/monthlytips/country_state=US_IL_N/tip_code=NoInformation/feature=ACC,FAHD,WHG,FP,WA,DY,DWSH,GD,REF,STV,OVN,MW,CPTR,ATT,ROOF,RG,BSMT,FDN,SPX,GAR,EGF,PLB,DOOR,WIND,WS,LWN,DKG,PF,BBQ,WSD,OWF,DWY,OLIT,HL,SPTC,CF,WF,CPTS,DVB,FURW,FURL,FURU,MAT,BATH,KITC,CLST,LITE,SD,COD,FE,EMS,PC,SS,MED,EAUD,ENR,GARR,INR,MGR,TAXR,TELR,CGD,DOOR,WIND,WS/dwelling_type=1/tip_priority=1/month=3/tip_knowledge_level=1/tipbr_ensav=0/tipbr_safe=0/tipbr_avoid=1/tipbr_comfort=1/tipbr_value=1/tipbr_appear=1/tipbr_green=0/tipbr_money=0/tipbr_space=1/tipbr_allergy=2/tipbr_elderly=2/tipbr_children=2/tip_location_temp=0/tip_location_humidity=0"
output:Bad Request - Invalid URL HTTP Error 400. The request URL is invalid.
my web config is: httpRuntime maxUrlLength="1024"
but it's working my local host not in server pc.
thanks in advance.
To be honest your issue is that that's not a restfull URL, the url should just be the location of the resource you are dealing with, the body of the request should contain the details of the request (as xml or json for example). It will both solve your problem and result in less code to manage the parameters via deserialization into a request object server side, not to mention clear up that url.
UPDATE
Are you sure thats a GET and not a PUT, what is the call meant to do?
If it is a GET I'd do something like the following...
Service Interface
[WebGet(UriTemplate = "monthlytips")]
AppropriateReturnType MonthlyTips(MonthlyTip monthlytip);
DTO Object
public class MonthlyTip
{
public string CountryState { get; set; }
public string TipCode { get; set; }
public List<string> Feature { get; set; }
public int DwellingType { get; set; }
public int TipPriority { get; set; }
...
...
}
Thats off the top of my head so it might need a little refining and you'll need to implement the interface, finish the DTO and so on but that's the approach you should take.
I'm having difficulty fully grasping a particular function of Windows Communication Foundation. I've read tutorial after tutorial, book after book. So the entire conceptual nature I feel confident on.
Except for one part; this is the part that is almost like magic. Which actually made the learning slightly difficult.
I'll use the most common example on the web.
I'll start with the DataContract:
[DataContract]
public class Customer
{
// Declerations:
private Guid id;
private string firstName;
private string lastName;
private string emailAddress;
[DataMembers]
public Guid Id
{
get { return id; }
set { id = value; }
}
[DataMember]
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
[DataMember]
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
[DataMember]
public string EmailAddress
{
get { return emailAddress; }
set { emailAddress = value; }
}
}
Now I've created an object; that I'd like to be exposed to my Client.
So I then create my ServiceContract.
[ServiceContract]
public interface ICustomer
{
[OperationContract]
Customer AddCustomer(Customer info);
}
So this where I keep confusing myself; lets say you have a Client-Side Application. You've consumed the service. You have three textboxes in a separate Assembly / Namespace. The Client puts in the criteria:
First Name
Last Name
Email Address
If you set those text boxes to the date; they will transfer over in Metadata. But on the server; how can I pull that information variable out? Do I just reference the private Guid and private string variables?
I saw a tutorial on how to add it to a database; but I don't fully comprehend what WCF is actually doing. Which is similar to what I'd like. I'd like to get the Client interface input and write it to a database and a separate log file.
I could just follow the tutorial; but I want to know how the Customer object data and it's variables are being assembled for use on the server.
Any assistance would be amazing, some clarification.
Sorry if my question is stupid; I'm not trying to start a debate. Just want to understand how to pull those variables and use them on the server.
Thanks in advance. If I didn't format the question correctly please let me know. I'd really like to understand what it is conceptually doing.
Update:
My true intention is to understand how the Client interface references that object; so when the call is made the server has a valid object that isn't null.
Client types in text box ---> Proxy Sends ---> De-serialized ---> Service ---> Serializes ---> Makes Property available for usage.
The actual types, such as your Customer class are not really transmitted across the wire. However, the public information within those types is sent across through a process called serialization. Serialization allows a type to be represented in a way that allows it to be transmitted over a network. This is often expressed using a format such as SOAP, JSON or XML. WCF even allows you to control exactly how objects are serialized, allowing you to write your own formatter if you want. Basically, when AddCustomer is called, WCF is constructing a Customer object on the server, serializing it, and sending those bits across the wire.
Now, on the client you would have a matching Customer object called a proxy. It might look something like:
public class Customer
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
}
Basically, a scaled down version with just the data members of the server version, with no code or logic. On the client, the serialized representation of Customer is deserialized back into an instance of this local proxy class, where it can be used for various client purposes, including being bound to local UI elements.
Web services can expose this type information using WSDL (which is an XML format for describing a web service contract). Visual Studio (using the wsdl.exe tool) can automatically write these proxy classes for you, which makes everything just work magically.
I am not sure but may be this is what you are looking for
Data Transfer and Serialization
In particular you can check DataContractSerializer
You can check this article too : Serialization in Windows Communication Foundation