OAuth Bearer Access Token sliding expiration

16,621

WARNING! Here is the solution that NO ONE SHOULD USE if you're not 100% sure that your application guarantees (which is impossible) that Access Token can not be compomised (for instance, XSS vulnerability allows to steal Access Token). In this solution once Access Token leaked it can be used to indefinitely prolong the access. OAuth Refresh Tokens solve exactly this problem, limiting access in case of compromising Access Token with very short amount of time, usually about 15 minutes.

[Authorize]
public class RefreshTokenController : ApiController
{
    [HttpGet]
    public HttpResponseMessage ReissueToken()
    {
        // just use old identity
        var identity = ((ClaimsPrincipal)User).Identity as ClaimsIdentity;

        var ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
        DateTimeOffset currentUtc = new SystemClock().UtcNow;

        ticket.Properties.IssuedUtc = currentUtc;
        ticket.Properties.ExpiresUtc = currentUtc.AddMinutes(30);

        string token = Startup.OAuthBearerAuthOptions.AccessTokenFormat.Protect(ticket);

        return new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new ObjectContent<object>(new
            {
                accessToken = token,
                expiresIn = (int)((ticket.Properties.ExpiresUtc.Value - ticket.Properties.IssuedUtc.Value).TotalSeconds),
            }, Configuration.Formatters.JsonFormatter)
        };
    }
}
Share:
16,621
Eugene D. Gubenkov
Author by

Eugene D. Gubenkov

Updated on June 04, 2022

Comments

  • Eugene D. Gubenkov
    Eugene D. Gubenkov almost 2 years

    Let's suppose that we're using OAuth Bearer tokens to secure our API. There is NuGet package with OWIN middleware that will do it for us: https://www.nuget.org/packages/Microsoft.Owin.Security.OAuth.

    Everethig looks great, until raises question about access token expiration - we don't want to force use to re-login over and over again. As far as I understand there are three basic ways:

    1. Make Access Token expiration time very big (1 month for instance)
    2. Use OAuth Refresh Tokens that adds much difficulties to both Authentication Server and the user application code (described in following article http://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/)

    I'm curious is it possible to create the endpoint that will require access token that is about to expire and just answer with new access token to simulate kind of sliding expiration for OAuth Access Tokens?

  • Taylor Buchanan
    Taylor Buchanan almost 9 years
    If an attacker got a hold of an access token, this would allow them to maintain access indefinitely by continually reissuing the compromised access token. This is the problem refresh tokens try to solve. If you choose this route, be sure to store the access tokens in the database and add the necessary code checks so they can be revoked when compromised.
  • Eugene D. Gubenkov
    Eugene D. Gubenkov almost 9 years
    @TaylorBuchanan, exactly, thank you! I'll update the answer to alert readers.
  • Beryl Wilson
    Beryl Wilson over 8 years
    Since refresh token is also stored at client side like the access token, if the refresh token is stolen, it can be used until the administrator revokes it. Finally we end up with the same situation as with access token? am I missing something here? Please help.
  • Eugene D. Gubenkov
    Eugene D. Gubenkov over 8 years
    @BerylWilson, this is why specification distinguishes between "public" and "confidential" clients (rfc6749, section 2.1). As per rfc6749 section 10.4, the refresh tokens should be only issued to "confidential" clients (web app or native app) that "capable of maintaining the confidentiality of their credentials (e.g., client implemented on a secure server with restricted access to the client credentials), or capable of secure client authentication using other means". E.g. web app + HTTP-only cookie makes Refresh Token hard to compromise (the Client itself has no access to it from JS).
  • Eugene D. Gubenkov
    Eugene D. Gubenkov over 8 years
    @BerylWilson, I mean if you Client is just JS application ("public Client") you're not allowed by OAuth specification to use Refresh Tokens at all.
  • Beryl Wilson
    Beryl Wilson about 8 years
    @EugeneD.Gubenkov Thanks for your response.