Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OAuth Bearer Access Token sliding expiration

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?

like image 891
Eugene D. Gubenkov Avatar asked Nov 09 '22 16:11

Eugene D. Gubenkov


1 Answers

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)
        };
    }
}
like image 152
Eugene D. Gubenkov Avatar answered Nov 15 '22 12:11

Eugene D. Gubenkov