views:

1495

answers:

3

I am trying to call an https web service (RESTful) using basic authentication. It works fine if I put the credentials in the url itself but I would rather add it to the request so that the password does not appear, for instance in an exception.

I am using the following code:

    NSURLCredential *credential = [NSURLCredential credentialWithUser:@"myuser"
                                                             password:@"mypassword"
                                                          persistence:NSURLCredentialPersistenceForSession];

    NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
                                             initWithHost:@"example.com"
                                             port:443
                                             protocol:@"https"
                                             realm:nil
                                             authenticationMethod:NSURLAuthenticationMethodHTTPBasic];


    [[NSURLCredentialStorage sharedCredentialStorage]  setDefaultCredential:credential
                                                        forProtectionSpace:protectionSpace];

    NSURLConnection *theConnection = [NSURLConnection  connectionWithRequest:theRequest delegate:self];

but it does not work. The didReceiveAuthenticationChallenge delegate method gets called and I can add a credential there but ideally I would send it with the request.

Any ideas?

+3  A: 

Try this Wonderful Library :

http://allseeing-i.com/ASIHTTPRequest/

http://allseeing-i.com/ASIHTTPRequest/How-to-use

Using this you can set a username and password to use for the request,use the keychain,use session authentication,NTLM authentication etc. Hope this help.

Gaurav Verma
Nice looking library
Ian1971
btw I'd like to accept this as the answer (mainly because it is something I didn't know about and looks really handy) but for some reason I don't have a tic mark to click on.
Ian1971
+1  A: 

Try sending the credentials in the header if it is basic authentication. Works for me every time.

For sending the username and password in the header of the request

NSString *authString = [[NSString stringWithFormat:@"%@:%@", userName, password] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *finalAuth = base64 of authString;

In your request, add a header with the field name Authorization and value "Basic " + finalAuth

lostInTransit
I tried this before, but couldn't get it to work. I'll give it another go.
Ian1971
Does it give you an error? Are you sure the error is because of failing the authentication challenge?
lostInTransit
A: 

I missed that last line of code where you are using NSURLConnection. Make sure that your delegate is responding to
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
and is returning YES for your protectionSpace.
Also, make sure that your delegate is responding to
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
Here you can assign the credential that you created to the NSURLAuthenticationChallenge in the proposedCredential property, as well as your NSURLProtectionSpace instance into the protectionSpace property of the NSURLAuthenticationChallenge.

benasher44
It works fine when it get the challenge back, but I am trying to avoid that round trip by sending the credentials with the initial request.
Ian1971
I wouldn't consider that a round trip. Either way, the connection will be challenged and it will have to provide credentials.
benasher44