Question
· Sep 20, 2019

Is there an OAuth 2.0 "sliding expiration" for JWT access tokens to extend the expiry date?

In .NET Core you have an option to extend a session using a "sliding expiration". This means that if over half the time has passed and the user actively uses their session then the expiry timer gets reset and the user remains logged in. This can lead to the curious situation where you have an active authenticated user with an expired access token being used in data-access requests.

Consider the following Startup.cs config

            services.ConfigureApplicationCookie(options =>
            {
                // Cookie settings
                options.Cookie.HttpOnly = true;
                options.ExpireTimeSpan = TimeSpan.FromMinutes(3);
                options.LoginPath = "/Identity/Account/Login";
                options.LogoutPath = "/Identity/Account/Logout";
                options.AccessDeniedPath = "/Identity/Account/AccessDenied";
                options.SlidingExpiration = true;
});

I am using a PasswordGrant authentication mechanism to generate a JWT access token that expires after 3 minutes(180 seconds). The default setting is 1 hr (3600 seconds).  I save the access token to a session variable so that it can be used in subsequent requests. Since the session can extend beyond the 3 minutes when a user is active, you are left with the problem of a user logged in and an invalid/expired access token being utilized in data-access requests (web api calls).  

Is there a way to refresh the expiry timer on the access token without re-directing the user to the login screen or prompting the user for input?

An alternative approach might be to grant a more generous interval and disable SlidingExpiration but then users will be asked to login every [n] minutes no matter how active they are. 

Update #1 
Not seeing a lot in documentation but a find-in-files in %SYS gives more clues.
The answer appears to be in the use of RefreshTokens in %SYS ##class(OAuth2.Server.Token).Process() method. The refresh token is a random 32 length string and is used to generate the access token. It also has a interval length (default is 24 hrs). 
A password grant has a grant_type of 'password' and a refresh token has a grant_type of  'refresh_token'. 
I'm still unsure unsure how the two grant types work together and whether the resulting access token could be successfully decoded as a JWT.

Discussion (1)0
Log in or sign up to continue

Adding the scope 'offline_access' to the 'password' grant_type generates a refresh_token in the JSON response. 

endpoint: https://{{SERVER}}:{{SSLPORT}}/oauth2/token

{
"grant_type":"password",
"username":"test1",
"password":"P@ssw0rd",
"client_id":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"client_secret":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"response_type":"token",
"state":"myapp",
"scope":"myapp openid profile offline_access"    
}
 

Response JSON

{

"access_token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",

"token_type": "bearer",

"expires_in": 180,

"refresh_token": "7NJ7tQbFBLFcUftZr9j4n6o99Og03QeM6rx51L05eIU",

"scope": "myapp offline_access openid profile",

"account_enabled": 1,

"account_never_expires": 1,

"account_password_never_expires": 1,

"change_password": 0,

"comment": "Test User",

"full_name": "test1",

"roles": "%DB_CODE,createModify,publish"

}

So... if you detect that access_token is no longer valid, you could try using the refresh_token to generate a new one without prompting the user for input. It seems a good idea to have the refresh_token interval significantly larger value than your access_token value. I will need to do more experimentation to find the ideal intervals and review the impact on license usage.