17

I'm using AFNetworking as a network layer for my iPhone app which connects to a Rails server that uses Devise for authentication. If I sign in (with a POST call) providing username/password then after that any GET I perform is ok.

If I close the app (not just background) then all my GET requests fail because I guess they're not authenticated.

So I presume cookies are stored somewhere; is there a way to save them in NSUserDefaults or somewhere like that in order to avoid logging in all the time?

Marcus Leon
56.9k123 gold badges300 silver badges436 bronze badges
asked Dec 19, 2011 at 17:32

2 Answers 2

84

You do not need to bother with NSUserDefaults nor any keychain wrapper if you use NSURLCredential. Indeed NSURLCredential is much simpler to use, as it allows you to store both username and password in the keychain in two lines of code.

Your code would be something like that once the user is logged in:

NSURLCredential *credential;
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:self.loginProtectionSpace];

Then, each time the app is launched, you can check whether your user was already logged in by searching for any credential in order to automatically log back your user (if need be):

NSURLCredential *credential;
NSDictionary *credentials;
credentials = [[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:self.loginProtectionSpace];
credential = [credentials.objectEnumerator nextObject];
NSLog(@"User %@ already connected with password %@", credential.user, credential.password);

You also need to clean the credential when the user wants to log out:

NSURLCredential *credential;
NSDictionary *credentials;
credentials = [[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:self.loginProtectionSpace];
credential = [credentials.objectEnumerator nextObject];
[[NSURLCredentialStorage sharedCredentialStorage] removeCredential:credential forProtectionSpace:self.loginProtectionSpace];

loginProtectionSpace is created once for all. Please, note this sample code assumes there is only one credential in this space, which is usually the case unless you manage several accounts.

Here is an example of how you would create a NSURLProtectionSpace:

NSURL *url = [NSURL URLWithString:@"http://www.example.com"];
self.loginProtectionSpace = [[NSURLProtectionSpace alloc] initWithHost:url.host
 port:[url.port integerValue]
 protocol:url.scheme
 realm:nil
 authenticationMethod:NSURLAuthenticationMethodHTTPDigest];
answered Aug 1, 2013 at 15:13
3
  • Where is the code to create an NSURLProtectionSpace? I looked at the Apple docs but it's not really clear to me how to create one. I am referring to "self.loginProtectionSpace" Commented Sep 1, 2013 at 4:08
  • I guess what I mean is, do the port and hostname matter or are these namespaces? Commented Sep 1, 2013 at 4:36
  • 4
    I've updated my answer with an example of how to create a NSURLProtectionSpace. Please replace the URL with you own and update the authentication method parameter with the authentication method used by your server. Commented Sep 2, 2013 at 9:06
10

Cookies are indeed automatically stored for the lifetime of your application for any subsequent requests on a particular server. A good strategy would be to store the username and password in the keychain or in NSUserDefaults like this:

// Setting
[[NSUserDefaults standardDefaults] setObject:username forKey:@"username"];
[[NSUserDefaults standardDefaults] synchronize];
// Getting
NSString *username = [[NSUserDefaults standardDefaults] objectForKey:@"username"];

You may want to use this in combination with AFHTTPClient to send your credentials along with every request in an Authorization HTTP header.

answered Dec 24, 2011 at 21:41
2
  • 1
    Thanks for replying, yes this is what I do to keep old credentials. What I'd like to avoid is the initial POST for login at every app restart, I was just wondering if the lifetime of the cookie handled by AFNetworking can be extended. Commented Dec 28, 2011 at 20:02
  • 28
    Actually, please don't store usernames and passwords in NSUserDefaults. Use the keychain instead. Apple distributes a KeychainWrapper that does basically the same thing, but more securely. Commented Aug 12, 2012 at 4:15

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.