Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Session expire design pattern [closed]

I have often had to cope with sessions / access tokens expiring in an iOS app design and have never really quite found a design that I am 100% comfortable with, so I am asking this here to see if anyone can come up with a better design than I currently use.

The problem

You have an app that logs in with a username and password. The server returns an access token that should be used for future requests to authenticate that user. At some point in the future (unknown time) the server will expire that token and any request sent with that token will return an authentication failure.

After failure due to the session expiring, the app should re-login using the original credentials and get back a fresh access token. It can then retry the original request.

Example

So imagine you have an API to get a list of news articles that requires authentication. The flow might go like this:

  1. User logs in and app receives token.
  2. View controller refreshes list of news articles.
    1. API request is made with token attached.
    2. API request successful and view is updated with new articles.
  3. App is closed and some time passes.
  4. App is opened at which point the view controller wants to refresh the list of news articles.
    1. API request is made with token attached.
    2. API request is unsuccessful because token has expired.
    3. View controller requests a refresh of the token and waits patiently.
    4. Once token has been refreshed, API request is retried.

Now imagine that this is done from more than one place in the app.

How I currently solve it

What I usually do is store the credentials in NSUserDefaults (if I am not concerned with security of those credentials - obviously better to be using the keychain) and then have a method on a global manager object (singleton) which refreshes the login using these credentials when I notice that the session has expired. This global manager fires off notifications when the login state changes so that other parts of the app can know when they should retry a request after failure due to the session expiring.

What I don't feel is right

Well, I just never have liked the state machine handling of the manager object. Every place that performs a request needs to save some state to know that a login refresh is going on and to retry the request after the login has been refreshed. There's also the problem of what to do if the refresh fails because the password is wrong now (the user changed it maybe) - you probably don't want to log out completely and destroy all user state of the app, because you might just be able to ask for the new password and carry on as before. But the global manager doesn't really relate to UI so it's hard to it to handle the UI of asking for the new login.

What I want to know in answers

I understand that this question is particularly vague and conceptual (I still think it's OK to be on StackOverflow though?) but I'd really just like to know how other people solve this kind of problem. Just an explanation of how you go about handling the session expiration, retrying the failed requests from all over the app and asking the user for new credentials if refreshing didn't work.

I guess the crux of the whole thing is this question:

Where to put the retry logic of requests that failed due to session expiring. I see these places are options:

  1. At the view controller level (i.e. keep a flag to say we need to retry the last request once login refresh has finished).
  2. At the API request level (i.e. encapsulate the API request in an object that knows to retry after the login has been refreshed).
  3. At the global login manager level (i.e. perhaps take a block in when refreshLogin is called that is executed once the login has been refreshed).
like image 740
mattjgalloway Avatar asked Mar 28 '12 11:03

mattjgalloway


People also ask

What happens when a session expires?

When the session expires, or session timeout occurs, the Session_End event in global. asax is raised (except when session is handled by the DB) and the session collection is finally cleared. If any objects are NOT holding a reference to any of values in the session collection, then GC will collect it.

What causes a session to expire?

If your Internet connection is unstable, periodically disconnecting and reconnecting, it can cause a website session to expire. When the Internet connection is lost the website connection can be terminated, resulting in a session expired message if you try to access any page after the Internet reconnects.

Is session expire when browser close?

Browsers deletes the session cookies when the browser is closed, if you close it normally and not only kills the process, so the session is permanently lost on the client side when the browser is closed.

Do session ids expire?

Answer. Yes the Session cookie expires. In addition to the 30 minute default timeout (if the visitor is idle for 30 minutes) the 'Session ID' cookie will expire at the end of an internet browser session.


2 Answers

Not to raise this question from the dead, but since it hasn't been answered I'll give my input.

What I chose to do for this scenario was to store the creds in the keychain (or wherever, really), and then I subclassed an HTTPClient to check whether to refresh or not before every call. This way, I can identify a refresh is needed, perform it, and retry the call all in one step as well as being able to send an error block up the chain if necessary to handle any cases in which the user could NOT be refreshed accordingly.

This seems to be in line with what you are (or probably were) trying to accomplish. No need for notifications or any of that jazz, and you can write it once and reuse it throughout the entire app by sending your calls through that subclassed HTTPClient.

EDIT: Bear in mind, you should remember to allow any authentication calls to pass!

like image 182
Stakenborg Avatar answered Oct 14 '22 07:10

Stakenborg


What you've asked is how to deal with session expiration. The others have answered your question. But I think you're asking the wrong question. Let me explain.

What we want is a design pattern for user sessions on iOS. We need to look at it from the point of view of the iOS device:

  1. User installs the app
  2. User authenticates with details and a session token is returned
  3. The app then stores the (secret) session token on the device
  4. Any future requests include the session token

Conclusion: Any API designed for iOS shouldn't expire the session token. It's simply kept secret on the device.

So from my experience the answer to your question about a design pattern for session expiration is basically: Do not use session expiration when using an API for iOS.

One of the biggest iOS REST API's out there is doing it this way, and I would have to agree.

like image 31
Brian Avatar answered Oct 14 '22 09:10

Brian