Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IdentityServer MVC Token Expiration

I am new to Identity server and a key concept is missing from my understanding. I am using the code from the MVC tutorial.

If I decorate my Home controller with the attribute [Authorize] and visit my website I get redirect to the IdentityServer. I then log in using my username and password. I then use some custom code and authenticate. I get back an AccessToken and I can then access the Home controller.

My client settings is as follows:

  new Client {
                ClientId = "mvc",
                ClientName = "MVC Client",
                AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
                ClientSecrets = new List<Secret>{new Secret("secret".Sha256())},
                RequireConsent = false,
                AccessTokenLifetime = 1,

                // where to redirect to after login
                RedirectUris = new List<string>{"http://localhost:5002/signin-oidc"},

                // where to redirect to after logout
                PostLogoutRedirectUris = new List<string>{"http://localhost:5002"},

                AllowedScopes = new List<string>
                {
                    StandardScopes.OpenId.Name,
                    StandardScopes.Profile.Name,
                    StandardScopes.OfflineAccess.Name,
                }
            }

My access token is

{
  "nbf": 1474697839,
  "exp": 1474697840,
  "iss": "http://localhost:5000",
  "aud": "http://localhost:5000/resources",
  "client_id": "mvc",
  "scope": [
    "openid",
    "profile"
  ],
  "sub": "26296",
  "auth_time": 1474697838,
  "idp": "local",
  "amr": [
    "pwd"
  ]
}

As I set my AccessTokenLifetime to 1 my token when sent to call an API etc will be invalided. I still however will be able to access the website.

What is the best way to get the MVC website to confirm that my token has not expired? This may be where the refresh tokens come in to play.

Note The AccessTokenLifetime set to 1 is for testing only so I can test things quickly.

like image 600
Liam Avatar asked Sep 24 '16 06:09

Liam


1 Answers

You will need to set the user authentication lifetime to match that of your access token. If using OpenIdConnect you can do that with the following code:

.AddOpenIdConnect(option =>
{
...

option.Events.OnTicketReceived = async context =>
{
    // Set the expiry time to match the token
    if (context?.Properties?.Items != null && context.Properties.Items.TryGetValue(".Token.expires_at", out var expiryDateTimeString))
    {
        if(DateTime.TryParse(expiryDateTimeString, out var expiryDateTime))
        {
            context.Properties.ExpiresUtc = expiryDateTime.ToUniversalTime();
        }
    }
};
});

I assume you are using cookie authentication? If so you may have to switch off Sliding Expiration. Sliding Expiration will automatically refresh the cookie any time it processes a request which was more than halfway through the expiration window. However the access token won't be refreshed as part of this. Therefore you should let the user authentication lifetime run until the end, at which point it will expire and a new access token will be automatically retrieved using the refresh token.

.AddCookie(options =>
            {
                // Do not re-issue a new cookie with a new expiration time.
                // We need to let it expire to ensure we get a fresh JWT within the token lifetime.
                options.SlidingExpiration = false;
            })
like image 52
Stacey Avatar answered Sep 26 '22 03:09

Stacey