views:

5340

answers:

1

Hello,

I'm trying to get a small twitter client running and I ran into a problem when testing API calls that require authentication.

My password has special characters in it, so when I try to use the following code it doesn't work.

NSString *post = [NSString stringWithFormat:@"status=%@", [status stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];

NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];

NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://%@:%@@%@/statuses/update.json", username, password, TwitterHostname]];
[request setURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];

NSURLResponse *response;
NSError *error;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

I started looking into base64 and putting the authentication into the headers. I found Dave Dribin's post on his base64 implementation, and it seemed to make sense. However when I tried to use it the compiler started complaining about how it couldn't find the openssl libraries. So I read that I needed to link in the libcrypto library, but it doesn't seem to exist for iphone.

I've also read people saying that apple won't allow apps that use crypto libraries, which doesn't make sense to me.

So now I'm kinda stuck and confused. What's the easiest way to get basic authentication into my app?

Cheers

+7  A: 

Two things. Firstly you have to use the async methods rather than the synchronous/class method.

NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:req]
                                                               cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                           timeoutInterval:30.0];

// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

The authentication is managed by implementing this method in your delegate:

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;

And you'll probably also need to implement these methods too:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;

Using the async method tends to give a better user experience anyway so despite the extra complexity is worth doing even without the ability to do authentication.

Stephen Darlington
I changed the sendSynchronous call to initWithRequest:request delegate:self and then setup up the didReceiveAuthenticationChallenge in the delegate, but nothing gets called. I tried other NSURLConnection delegate methods and they didn't work either. Any ideas?
Meroon
I figured out why the delegate methods weren't working. I was calling initWithRequest from a class method which won't work. Thanks for the help.
Meroon
Sorry, unnecessarily terse answer (but happy that you got there in the end). I've expanded it. Hopefully it's a bit more useful now.
Stephen Darlington