add client certificate before posting to https server in C++ - http-post

I want to post some data to a https server before which I need to add a client certificate for trust validation. I have already done it in C# which is as follows:-
X509Certificate cert = X509Certificate.CreateFromCertFile("Path to my .cer file"); //****** name of cer file is "ServerTrial.cer" ******//
Uri authURL = new Uri("https://myServer/post");
HttpWebRequest authRequest = (HttpWebRequest)WebRequest.Create(authURL); //****** Here i add the server url ******//
authRequest.ClientCertificates.Add(cert); //****** Here i add the client certificate ******//
authRequest.Method = "POST"; //****** Here i specify the method which is "POST" ******//
byte[] postBytes = "Data to be posted";
authRequest.ContentLength = postBytes.Length;
Stream requestStream = authRequest.GetRequestStream();
// now send it
requestStream.Write(postBytes, 0, postBytes.Length); //****** Here I post the data to the Server ******//
requestStream.Close();
// grab the response
HttpWebResponse response = (HttpWebResponse)authRequest.GetResponse();
StreamReader responseStream = new StreamReader(response.GetResponseStream());
string responseStr = responseStream.ReadToEnd();
So ultimately what i want is to create a http object, add the server url to it, add the client certificate to it and then finally post the data to the server.
Now i want to achieve the above in C++. I am thinking of using openSSL for the above but I have very less idea of it. Can anyone please guide me regarding this?
-Thanking everyone,
sattu

Related

Login to web server with Google Sign-in

I'm connecting to a 3rd party web server from an HTTP client (Java or Dart - Android app) to download some resources (XML or IMG files) that belong to the current user on that server. This site requires login with Google Sing-In. I have everything set up in my Android app to login the user with Google, I obtained their authorization idToken. But how do actually use it in HTTP GET or POST methods to download the protected resources?
With BASIC authentication it's easy - just set HTTP 'Authorization' header correctly ("Basic " + user:password encoded as base64), call GET, and I download the desired resource. But I cannot find any information on how to do this with Google Sing-In. Do I send the idToken I received from Google in some headers? What other magic is needed?
Adding a Java code snippet, hope it helps:
// (Receive authCode via HTTPS POST)
if (request.getHeader('X-Requested-With') == null) {
// Without the `X-Requested-With` header, this request could be forged. Aborts.
}
// Set path to the Web application client_secret_*.json file you downloaded from the
// Google API Console: https://console.developers.google.com/apis/credentials
// You can also find your Web application client ID and client secret from the
// console and specify them directly when you create the GoogleAuthorizationCodeTokenRequest
// object.
String CLIENT_SECRET_FILE = "/path/to/client_secret.json";
// Exchange auth code for access token
GoogleClientSecrets clientSecrets =
GoogleClientSecrets.load(
JacksonFactory.getDefaultInstance(), new FileReader(CLIENT_SECRET_FILE));
GoogleTokenResponse tokenResponse =
new GoogleAuthorizationCodeTokenRequest(
new NetHttpTransport(),
JacksonFactory.getDefaultInstance(),
"https://www.googleapis.com/oauth2/v4/token",
clientSecrets.getDetails().getClientId(),
clientSecrets.getDetails().getClientSecret(),
authCode,
REDIRECT_URI) // Specify the same redirect URI that you use with your web
// app. If you don't have a web version of your app, you can
// specify an empty string.
.execute();
String accessToken = tokenResponse.getAccessToken();
// Use access token to call API
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
Drive drive =
new Drive.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential)
.setApplicationName("Auth Code Exchange Demo")
.build();
File file = drive.files().get("appfolder").execute();
// Get profile info from ID token
GoogleIdToken idToken = tokenResponse.parseIdToken();
GoogleIdToken.Payload payload = idToken.getPayload();
String userId = payload.getSubject(); // Use this value as a key to identify a user.
String email = payload.getEmail();
boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
String name = (String) payload.get("name");
String pictureUrl = (String) payload.get("picture");
String locale = (String) payload.get("locale");
String familyName = (String) payload.get("family_name");
String givenName = (String) payload.get("given_name");
For detailed info, find all the required steps and references at: https://developers.google.com/identity/sign-in/web/server-side-flow#step_1_create_a_client_id_and_client_secret

Sending Images to the client from tomcat server

I am building a framework for e-commerce site. I have used jersey to create REST APIs. I need to send images to the clients as per the request.
How can I do so from my application server as Tomcat and jersey as REST API?
Since I am new to this, I have no clue how to send images to an Android client when they are shown as item.
Every resource is identified by the URI, client will ask for a particular image or a bunch of images by quering the URL, So you just need to expose a service, following service is an example to send single image to client.
#GET
#Path("/images/{imageId}")
#Produces("image/png")
public Response downloadImage(#PathParam("imageId") String imageId) {
MultiMediaDB imageDb = new MultiMediaDB();
String filePath = imageDb.getImage(imageId);
File file = new File(filePath);
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition",
"attachment; filename=\"fileName.png\"");
return response.build();
}
MultiMediaDB is my custom class to get the file location from the DB, you can hardcode it as of now for testing purpose like D:\server_image.png.
You need to mention Content-Disposition as an attachment so that file will not be downloaded, instead attached to the form. In android you just need to read inputstream from a HttpURLConnection object and send that to bitmap as shown below
URL url = new URL(BaseUrl + "/images/" + imageId);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
iStream = urlConnection.getInputStream();
bitmap = BitmapFactory.decodeStream(iStream);
The you can set that bitmap to imageview or what ever you have as a container.

SignalR .Net client fails to connect (upd: how to set auth. cookie?)

This thing is dragging me nuts.
I have a .net 4.0 console app and I have an MVC web app.
javascript clients can connect and talk to the server - no problems here...
but my .net client throws System.AggregateException with InnerException = "Unexpected character encountered while parsing value: <. Path...
so I created an empty MVC3 app, added SignalR libraries, and .net client surprisingly connects to that. But for some reason it doesn't to the other one. I've checked everything, both MVC3 apps, both use the same SignalR libs, the same NewtonsoftJson... I thought it must be something with the routing, I guess no - js client works.
var connection = new HubConnection("http://localhost:58746");
var hubProxy = connection.CreateProxy("myProxy");
connection.Start().Wait() // it fails here on Wait
What could it be?
UPD: I have figured... it's because FormsAuthentication on the server. Now is there any way to feed .ASPXAUTH cookie to SignalR so it can connect to the server?
The solution by Agzam was really helpful, but if anyone else uses the posted code it is critical that you close the HttpWebResponse before exiting GetAuthCookie. If you don't you will find that whenever you use SignalR to invoke a method on the server, the request (under most circumstances) will queue indefinitely on the client and will neither succeed nor fail.
Note. The original code worked in the test environment when everything was on my PC, but failed consistently when the website was hosted on a remote server.
here is the modified code I ended up using
private Cookie GetAuthCookie(string user, string pass)
{
var http = WebRequest.Create(_baseUrl+"Users/Login") as HttpWebRequest;
http.AllowAutoRedirect = false;
http.Method = "POST";
http.ContentType = "application/x-www-form-urlencoded";
http.CookieContainer = new CookieContainer();
var postData = "UserName=" + user + "&Password=" + pass + "&RememberMe=true&RememberMe=false&ReturnUrl=www.google.com";
byte[] dataBytes = System.Text.Encoding.UTF8.GetBytes(postData);
http.ContentLength = dataBytes.Length;
using (var postStream = http.GetRequestStream())
{
postStream.Write(dataBytes, 0, dataBytes.Length);
}
var httpResponse = http.GetResponse() as HttpWebResponse;
var cookie = httpResponse.Cookies[FormsAuthentication.FormsCookieName];
httpResponse.Close();
return cookie;
}
its a very minor change , but it will save you a lot of debugging time.
Ok... stupid me... SignalR failed to connect because it cannot breach server's Forms authentication. So what needed to be done is to get the auth cookie and stick it to the HubConnection.CookieContainer...
so I wrote this method method to login with a username and get the cookie:
private Cookie GetAuthCookie(string user, string pass)
{
var http = WebRequest.Create(_baseUrl+"Users/Login") as HttpWebRequest;
http.AllowAutoRedirect = false;
http.Method = "POST";
http.ContentType = "application/x-www-form-urlencoded";
http.CookieContainer = new CookieContainer();
var postData = "UserName=" + user + "&Password=" + pass + "&RememberMe=true&RememberMe=false&ReturnUrl=www.google.com";
byte[] dataBytes = System.Text.Encoding.UTF8.GetBytes(postData);
http.ContentLength = dataBytes.Length;
using (var postStream = http.GetRequestStream())
{
postStream.Write(dataBytes, 0, dataBytes.Length);
}
var httpResponse = http.GetResponse() as HttpWebResponse;
var cookie = httpResponse.Cookies[FormsAuthentication.FormsCookieName];
httpResponse.Close();
return cookie;
}
And used it like this:
var connection = new HubConnection(_baseUrl)
{
CookieContainer = new CookieContainer()
};
connection.CookieContainer.Add(GetAuthCookie(_user, _pass));
Works perfectly!
Just use this for reading cookies:
var cookie = response.Cookies[".AspNet.ApplicationCookie"];

wp7 - twitter photo upload

We are trying to upload image to Twitter via silverlight code in WP7. We are able to post the message but not the image.
We tried all including download of their library but not getting the hint.
In following link,
https://dev.twitter.com/docs/api/1/post/statuses/update_with_media
there is one point which we are not able to set.
"Unlike POST statuses/update, this method expects raw multipart data. Your POST request's Content-Type should be set to multipart/form-data with the media[] parameter "
I am not getting it how to put it.
Can anyone please guide me or provide sample for image upload?
If your photo is called LoadedPhoto, you could create a memory stream from it
MemoryStream ms = new MemoryStream();
LoadedPhoto.SaveJpeg(ms, LoadedPhoto.PixelWidth, LoadedPhoto.PixelHeight, 0, 100);
Create OAuthCredentials object according to the authentication details you have acquired
var credentials = new OAuthCredentials
{
Type = OAuthType.ProtectedResource,
SignatureMethod = OAuthSignatureMethod.HmacSha1,
ParameterHandling = OAuthParameterHandling.HttpAuthorizationHeader,
ConsumerKey = Common.TwitterSettings.ConsumerKey,
ConsumerSecret = Common.TwitterSettings.ConsumerKeySecret,
Token = file.AccessToken,
TokenSecret = file.AccessTokenSecret,
Version = "1.0"
};
Create a RestClient and a RestRequest
var restClient = new RestClient
{
Authority = "https://upload.twitter.com"
};
var restRequest = new RestRequest
{
Credentials = credentials,
Path = "/1/statuses/update_with_media.xml",
Method = Hammock.Web.WebMethod.Post
};
Set the stream position to 0
ms.Position = 0;
Add fields to RestRequest
restRequest.AddField("status", message);
restRequest.AddFile("media[]", "ScreenShot.png", ms, "image/jpeg");
And then begin request
restClient.BeginRequest(restRequest, callback);
callback is a callback method for the request.
Taken from my blog post, see there for more details if you're interested.

WebClient NotFound error but working with HttpWebRequest/Response

In my WinPhone app I'm accessing a REST service.
At the beginnings I was using this code:
WebClient wc = new WebClient();
wc.Credentials = credentials;
wc.Headers["App-Key"] = appKey;
wc.DownloadStringCompleted +=
(o, args) => MessageBox.Show(args.Error == null ? "OK" : "Error");
wc.DownloadStringAsync(uri);
but it suddenly stopped working returning me a "The remote server returned an error: NotFound" error. After a google session and some clicks in the control panel, I didn't get it to work.
I decided to try this other way:
HttpWebRequest request = HttpWebRequest.CreateHttp(uri);
request.Credentials = credentials;
request.Headers["App-Key"] = appKey;
request.BeginGetResponse(asResult =>
{
var response = request.EndGetResponse(asResult) as HttpWebResponse;
StreamReader reader = new StreamReader(response.GetResponseStream());
string responseString = reader.ReadToEnd();
Dispatcher.BeginInvoke(
() => MessageBox.Show(response.StatusCode.ToString()));
}, null);
and it works.
I also tried to run the first snipped pointing the URI to google's home page and it works (I had to remove the credentials, of course).
Can anyone explain what's going on?
UPDATE
I managed to get it working by replacing the
wc.Credentials = new NetworkCredentials(username, password);
with
wc.Headers["Authorization"] = "Basic someBase64encodedString";
but i still wonder what happened and which are the differences between the first and the second line.
PS: the test URI is: https://api.pingdom.com/api/2.0/checks but you will need an app-key from them.
When using the Credentials property, the HttpWebRequest implementation will wait the challenge response from server before to send the 'Authorization' header value.
But this can be an issue in some cases, so you have to force Basic authentication by providing directly the Authorization header.
Example when using a REST Client library like Spring.Rest :
RestTemplate template = new RestTemplate("http://example.com");
template.RequestInterceptors.Add(new BasicSigningRequestInterceptor("login", "password"));
string result = template.GetForObject<string>(uri);

Resources