NSURLCredential not working for synchronuos request in iphone - iphone-sdk-3.0

I am using Synchronous request and passing the credentials but I am getting authentication error in response. Below is my code of request and response from server.
Request:-
NSURLCredential *userCredentials = [NSURLCredential credentialWithUser:#"username"
password:#"paswd"
persistence:NSURLCredentialPersistenceForSession];
NSURLProtectionSpace *space = [[NSURLProtectionSpace alloc] initWithHost:#"http://webaddress.inc.com"
port:80
protocol:#"http"
realm:#"webaddress.inc.com"
authenticationMethod:nil];
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:userCredentials
forProtectionSpace:space];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://webaddress.inc.com"]
cachePolicy:NSURLCacheStorageNotAllowed
timeoutInterval:30];
NSURLResponse *response;
NSError *error;
NSData *returnData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
/////////// Response
401 Authorization Required
Note: If I am sending the request with async request it is working fine as in that case
didReceiveAuthenticationChallenge is giving them the required credentials when asked for.
I am sure there might be something missing in my code.
Waiting for your valuable inputs.

Have you ever tried ASIHTTPRequest which makes easier http operations in IPhone enviroment. And It has really simple and good documentation. I used to use it inside of my projects, It was working awesome.

Related

Request NSURLSession with SSL .cert and .key files

I have to login via https in an Obj-C project. Everything is fine with all the url, the user, pass and the needed stuff. For identify, the server checks by ssl .cert and .key files. So far, so good, the files were uploaded to the server, and the connection made well by curl from terminal.
Here comes my problem.
Spend some days, read the available stuff here and there, but simply can't find any solution to send the ssl files with the request in Obj-C. (The server cannot accept p12)
Here's the curl:
curl -q -k --cert cert2048.crt --key key2048.key https://somesite.com/ -d "username=usrnm&password=psswrd"
Here's my Obj-C code so far:
-(void)connect {
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://somesite.com/"]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSDictionary* bodyParameters = #{
#"username": #"usrnm",
#"password": #"psswrd"
};
[request setHTTPBody:[self httpBodyForParameters:bodyParameters]];
[request setHTTPMethod:#"POST"];
[request setValue:#"gzip, deflate" forHTTPHeaderField:#"Accept-Encoding"];
[request setValue:#"keep-alive" forHTTPHeaderField:#"Connection"];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSError *jsonError;
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
NSLog(#"%#", jsonResponse);
}];
[postDataTask resume];
}
(httpBodyForParameters simply sets up the request body)
The connection establish, everything passes, the jsonResponse holds response as expected (well, the error message about authentication failure, in regular format). But I simply can't find a way to send the ssl files as in the curl line. Sadly, https authentication is far beyond my knowledge. I'm stucked. Every help appreciated.
Thank you,
Sz
That curl command is using the cert and key as a client certificate for authentication, not sending them as files. It's actually part of the authentication handshake.
The code for importing PKCS data and using it in response to a client certificate challenge is fairly involved, so rather than try to explain it all off the top of my head, I'm going to point you to another Stack Overflow question and answer that contain pretty extensive code snippets.
Creating a SecCertificateRef for NSURLConnection Authentication Challenge
However, be aware that some of the code in that link is not quite correct. For the protection spaces that are not handled, you should use default handling, not cancel the challenge.

AFNetworking upload task with credentials (HTTP Basic Auth)

I need to upload video files from my app to a server. I tried doing so via [AFHTTPRequestOperationManager post:parameters:success:failure] but unfortunately kept getting request timeouts. I'm now trying something similar to Creating an Upload Task from the AF Docs.
I read on SO and the AF Docs about setSessionDidReceiveAuthenticationChallengeBlock: and tried to implement the whole upload malarky as follows:
__block ApiManager *myself = self;
// Construct the URL
NSString *strUrl = [NSString stringWithFormat:#"%#/%#", defaultUrl, [self getPathForEndpoint:endpoint]];
NSURL *URL = [NSURL URLWithString:strUrl];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
[request setHTTPMethod:#"POST"];
// Build a session manager
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
// Set authentication handler
[manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing *credential) {
*credential = myself.credentials;
return NSURLSessionAuthChallengeUseCredential;
}];
// Create the upload task
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
[myself endpoint:endpoint returnedFailure:error];
} else {
[myself endpoint:endpoint returnedSuccess:responseObject];
}
}];
// and run with it
[uploadTask resume];
The myself.credentials object has been set previously to have the correct username and password. Whenever this request fires, I get 401 unauthorised as a response. I tried putting NSLog(#"CHALLENGE") inside the challenge block above, but it never seems to get called, so AFNetworking isn't giving me a way to supply credentials. I know that this works perfectly well on the server side because I've tested it with Postman.
How can I get AFNetworking to let me supply credentials for HTTP Basic Auth with this upload task?
I'm not sure about AFNetworking's setSessionDidReceiveAuthenticationChallengeBlock, but as long as you have an NSMutableURLRequest you may set the Authorization HTTP Header directly on the request object:
[request setValue:base64AuthorizationString forHTTPHeaderField:#"Authorization"];
Keep in mind that the value must be base64 representation of the username:password string.
Otherwise, for GET, POST, etc. requests on a session manager, you may set the credentials on the request serializer used by the session manager. See:
[AFHTTPRequestSerializer setAuthorizationHeaderFieldWithUsername:password:]
[AFHTTPRequestSerializer clearAuthorizationHeader]

How to get a new access token after expiration using OAuth 2.0 along with Youtube API in iOS application

I am using the Youtube Api in my iPad application. i managed to get authenticated and get the access token using the OAuth 2.0.
my problem is that the token expires after one hour and i don't know how to get a new one using the refresh-token without going through the authentication process again.
i am using XCode 4.5 and iOS 5.1 & 6
According do the documentation
If your application obtains a refresh token during the authorization process, then you will need to periodically use that token to obtain a new, valid access token. Server-side web applications, installed applications, and devices all obtain refresh tokens.
So if you already have your refresh token, you just need to perform a POST request configured as follows
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
client_id=21302922996.apps.googleusercontent.com&
client_secret=<YOUR CLIENT SECRET>
refresh_token=<YOUR REFRESH TOKEN>
grant_type=refresh_token
and you'll get back a response like
{
"access_token":<A NEW ACCESS TOKEN>,
"expires_in":<AN EXPIRING TIME>,
"token_type":"Bearer"
}
Here is the full code to refresh the accessToken using AFNetworking to make the request:
NSString *refreshToken = <YOUR_REFRESH_TOKEN>;
NSString *post = [NSString stringWithFormat:#"client_secret=%#&grant_type=refresh_token&refresh_token=%#&client_id=%#",kYouTubeClientSecret,refreshToken,kYouTubeClientID];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSURL *url = [NSURL URLWithString:#"https://accounts.google.com/o/oauth2/token"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
AFHTTPRequestOperation *httpRequest = [httpClient HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:responseObject options:kNilOptions error:nil];
NSString *newAccessToken = json[#"access_token"];
NSLog(#"received new accessToken = %#",newAccessToken);
// store accessToken here
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error refreshing token: %#",[error localizedDescription]);
}];
[httpClient enqueueHTTPRequestOperation:httpRequest];

NSMutableURLRequest with multiple headers

I'm trying to create a synchronous REST request to an API. The API uses HTTP Basic authentication, so in addition to sending an Accept: application/json header, I need to specify the Authorization header as well with my Base64-encoded username and password pair. When I use just one header the request executes just fine (either successfully authenticating me, or specifying my content format), but when I use both headers, it seems to ignore the Authorization line and returns "HTTP Basic access denied" (presumably a 401).
So I can't for the life of me figure out whats wrong. I'm 100% sure my credentials are valid, because executing the request via REST client works just fine. I'm pretty new to Objective-C so I think perhaps there could be some kind of design pattern I'm not following. Is it valid to call setValue:forKey on an NSMutableDictionary multiple times like that? I also tried using setValue:forHTTPHeader on the request object with the same results.
Here's the code:
NSURL *url = [NSURL URLWithString:#"http://foo.com/api/v1/bar"];
NSMutableURLRequest *request= [NSMutableURLRequest requestWithURL:url];
NSMutableDictionary *headers = [NSMutableDictionary dictionary];
NSURLResponse *urlResponse;
NSError *error;
[headers setValue:#"application/json" forKey:#"Accept"];
[headers setValue:#"Basic ..." forKey:#"Authorization"];
[request setAllHTTPHeaderFields:headers];
NSData *urlData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&urlResponse
error:&error];
NSString *responseString = [[NSString alloc] initWithData:urlData
encoding:NSUTF8StringEncoding];
NSLog(#"%#",responseString);
The answer is to use:
[request addValue:#"Basic ..." forHTTPHeaderField:#"Authorization"];
Which adds another header into the request instance.

Can't post to Twitter from my iPhone app

I'm using this small chunk of code to post in Twitter, with real credentials in place of 'mytwitterloginname' and 'mytwitterpassword' placeholders:
void _StartTwitter()
{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:
[NSURL URLWithString:#"http://mytwitterloginname:mytwitterpassword#twitter.com/statuses/update.xml"]
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
// The text to post
NSString *msg = #"testing";
// Set the HTTP request method
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[[NSString stringWithFormat:#"status=%#", msg]
dataUsingEncoding:NSASCIIStringEncoding]];
NSURLResponse *response;
NSError *error;
if ([NSURLConnection sendSynchronousRequest:request
returningResponse:&response error:&error] != nil)
NSLog(#"Posted to Twitter successfully.");
else
NSLog(#"Error posting to Twitter.");
}
But even my console says the post was succeful it still doesn't happen.
Can anyone help me to find what's wrong ?, thanks.
I though twitter had only O-AUTH authentication now, so you couldn't post information simply through their REST service anymore.
You may need to re-integrate with their new OAUTH service.
UPDATE:
Here is the link to the OAUTH Examples:
Twitter - OAUTH
The bummer part that I needed to do was create a WebUI view in order to go through the silly steps twitter now enforces. After doing a request to authenticate (which is bound to an app created in twitter), my session was created and from there I could do my posting of a message.
Not nearly as user friendly as the previous REST service :/