Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web API 2, OWIN Authentication, SignOut doesn't logout

I'm doing some research for work with a view to using Bearer tokens as an authentication mechanism (i.e. AngularJS UI, authenticates via OWIN in a Web API [2] project).

I have the login working fine, role information and all that is fine, but I cannot get the token to logout.

My startup configuration is this:

OAuthOptions = new OAuthAuthorizationServerOptions() {
    TokenEndpointPath = new PathString("/Token"),
    Provider = new ApplicationOAuthProvider(PublicClientId),
    AccessTokenExpireTimeSpan = SESSION_TIMEOUT,
    AllowInsecureHttp = true
};

And my logout action is simply this:

public HttpResponseMessage Logout() {
    var authentication = HttpContext.Current.GetOwinContext().Authentication;
    authentication.SignOut(DefaultAuthenticationTypes.ExternalBearer);

    return new HttpResponseMessage(HttpStatusCode.OK);
}

I've left all the authentication stuff out for brevity, but to confirm I am using ExternalBearer when setting up the token.

In my UI I'm storing the token in local storage (no cookies are involved here, which is a deliberate design decision). So I have a logout button on my UI, the Logout action is hit and the code runs fine.

However if I subsequently hit the an action on the API which requires authorisation, the request still goes through (i.e. the user is still authenticated even though they should have been signed out.

Either I'm missing something really obvious (wouldn't be the first time ;-) or there's something more fundamental going on here - finally I'm pinging @leastprivilege as I know this is their area.

Any help or insight would be gratefully received.


Only thing I can think of is that the token is stateless on the server/API side and hence can't be expired or signed out.

If that is the case I guess I could either:

a) Add a refresh token which creates a new token that expires in the past - would this even work? - actually cancel that, it would issue a new token ... the old one would still be valid

b) Store the bearer token in the database and check each time, removing the token on logout (naturally salted, hashed, etc). However this is just bringing us back to having a stateful server.

c) I can (and will) be removing the token from local storage when someone explicitly logs out, however the token is still technically valid if a baddy can intercept the token. Naturally all the above will be over SSL anyway, which should inhibit the bad guys/girls.

d) Perhaps this is why lots of people are storing the Bearer token in a cookie (as a storage mechanism) so once you logout as least the cookie will be removed on the next refresh.

Sorry the above is a bit of a brain dump, just wanting to pre-empt any questions

like image 743
toepoke.co.uk Avatar asked Jul 03 '14 11:07

toepoke.co.uk


3 Answers

Since OAuth is not an authentication protocol, there is no notion of signout. Delete the access token on the client - that's all you can do.

If you want to invalidate the token on the server side, add a unique id to it and keep track in your service - you would need to manually build something like that.

like image 118
leastprivilege Avatar answered Oct 16 '22 21:10

leastprivilege


I have a beautiful solution here: http://www.nakov.com/blog/2014/12/22/webapi-owin-identity-custom-login-service/. It is custom user session implementation for Web API OAuth bearer token authorization based on OWIN and the standard ASP.NET Identity (Microsoft.AspNet.Identity.EntityFramework). It works as most people may expect:

  • Web API sessions die after 30 minutes of inactivity.
  • Session’s life is extended at each authorized HTTP request with additional 30 minutes.
  • Logout works correctly: after logout the bearer access_token becomes invalid (its is revoked).

Full working source code is available at GitHub: https://github.com/SoftUni/SPA-with-AngularJS/tree/master/Ads-REST-Services

like image 16
Svetlin Nakov Avatar answered Oct 16 '22 19:10

Svetlin Nakov


This question has been here for ages (and answered too), but I only wanted to chime in my thoughts.

I would do similar to your (C) option, but use a shorter expiry on the bearer access token something like 10 or 20 minutes, so that when you have logged out and deleted the token on the client, although technically the token is still valid, the bad man will have only the remainder of the expiry time to play with your valid token.

In practice, I would use this together with a long-lived refresh token, so that I can get a new bearer token if it expires and want to continue interacting with the API resources, without having to authenticate again.

like image 2
jaeyow Avatar answered Oct 16 '22 19:10

jaeyow