5

I am developing an iOS application (using AFNetworking 2, AFURLSessionManager) where I have to interact with an API that I don't control (which is using the Symfony PHP framework if that makes any difference).

The problem is this: The user has an account. On app's first launch, the user gets a form-based login screen. They log in, then get a session cookie. The cookie expires in 30 minutes. It will renew itself on every call that the client makes. HOWEVER, if the app is restarted the cookie is deleted and if the app is idle for more than 30 mins, the cookie will become invalid.

I have multiple difficulties here. First of all, I need to make the login call transparently, so the user doesn't have to re-login. So I get the error response and I make the login request and on success I remake the original request. Now the problem is that there could be several simultaneous requests happening, and couple that with the unreliable nature of mobile network connections. So what happens with this logic seems like a nightmare of multiple logins and retries and lots of extra code and error handling.

My solution so far is this: Make a request. If I get an unauthorized error response, add the request to a retry queue (that I manage myself), set a login flag, and make the login request. Any new requests that come in first check the login flag, to see if there is a login in progress. If so, they go directly to the retry queue. When the login request is complete, I go through the retry queue and make all the queued requests.

So far, this seems to be working pretty well. BUT, I have this nagging feeling that there has to a better way. Are there no built-in mechanisms to deal with this kind of situation? It seems like a common way to handle user authentication, but I can't find any documentation about how to deal with this in AFNetworking. They cover Basic and Digest auth but nothing about this form-based session cookie auth. This is the first time I have to deal with this and I just can't believe that no one else has had this exact same problem. Any ideas?

d370urn3ur
  • 1,736
  • 4
  • 17
  • 24

1 Answers1

0

your session ID should be sent automatically once user are logged in, as long as the cookie does not expire before the next request is sent . NSURLConnection, which AFNetworking uses, takes care of the this is a way to save and load cookies try like this

 - (void)saveCookies{

    NSData *savecookiesData = [NSKeyedArchiver archivedDataWithRootObject: [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject: savecookiesData forKey: @"sessionCookies"];
    [defaults synchronize];

}

- (void)loadCookies{

    NSArray *loadcookiesarray = [NSKeyedUnarchiver unarchiveObjectWithData: [[NSUserDefaults standardUserDefaults] objectForKey: @"sessionCookies"]];
    NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];

    for (NSHTTPCookie *cookies in loadcookiesarray){
        [cookieStorage setCookie: cookies];
    }

}
sarunw
  • 8,036
  • 11
  • 48
  • 84
Sport
  • 8,570
  • 6
  • 46
  • 65
  • This solves 50% of my problem, persisting cookies across app launches. However, the session expires after 30 mins of no calls. So if the user checks the app, leaves, comes back in an hour, I have to re-authenticate no matter what. This happens quite often. What I am looking for, and what would solve both problems simultaneously, is some kind of callback that notifies me when I get a 401 and suspends the request queue until I complete a re-login action. Pratik suggested AFNetworking-AutoRetry and it might be the least complicated solution. – d370urn3ur Oct 02 '14 at 07:45