1

I have an ASP.net MVC web application that uses Microsoft's Owin middleware (Microsoft.Owin.Security.OpenIdConnect) to configure OpenID Connect authentication. My identity provider (Okta) is configured to support refresh tokens and I have confirmed that it is working. When signing in, my application receives an Access, ID and Refresh Token as expected. These tokens are validated and returned to the client in a cookie called ".AspNet.Cookies" (the default). On each request, the cookie and these tokens are parsed into a set of claims. Great so far.

The Owin (Katana) middleware does not appear to do anything further with the Refresh Token, so I have implemented a token client to request a new Access Token from my IdP using the Refresh Token. This is working as expected.

Two questions:

  1. When and where should the application check to see if the Access Token is expired and request a new one?
  2. After receiving new a access, id, and refresh token, how and where should the application update the user identity, claims and cookie?
Mark Good
  • 4,271
  • 2
  • 31
  • 43

1 Answers1

2

OWIN COOKIE UPDATES

I believe the comment at the end of this post has the type of code you can write - I remember using similar code a few years back.

With OWIN you are using a server side stack secured by cookies so I'm not sure where access tokens are actually used, but maybe one of these is true?

  • The C# back end uses tokens to call an API
  • The Web UI downloads tokens from the web back end and makes Ajax calls to an API

PATTERN FOR HANDLING EXPIRED TOKENS

The only reliable pattern to handle expiry is to do this in the API client code:

  • When you get a 401 response from the API
  • Try to refresh the token and retry the API call with a new access token
  • If you can't refresh the token, redirect the user to sign in again

I always implement this with 2 classes, as in this SPA code of mine:

If the Web UI is getting tokens from the web back end and then calling an API, your web back end could provide MVC operations similar to those in my authenticator class:

  • getAccessToken - get the current access token, though it may fail with a 401
  • refreshAccessToken - use this if a 401 is received and you need a new token

TOKEN EXPIRY TIMES

It is also possible to check token expiry times in the background - to reduce the number of client 401s. This is not a full solution however, since 401s can occur for other reasons in addition to expiry.

Gary Archer
  • 22,534
  • 2
  • 12
  • 24
  • Hi @Gary, thank you for your answer! I implemented something very similar to this answer (https://stackoverflow.com/a/36992935/97276) that you referenced, and while it seems to work, it doesn't seem to update the cookie so on next refresh the token in the cookie is still expired. I was hoping that .GetOwinContext().Authentication.SignIn(newIdentity) would trigger the middleware to set a new cookie, but it does seem to be doing that. Not sure what I am missing? – Mark Good Jul 21 '20 at 15:55
  • 1
    You might be missing the AllowRefresh flag as discussed [here](https://stackoverflow.com/questions/55675689/how-do-i-update-my-cookie-having-got-a-new-access-token) – Gary Archer Jul 21 '20 at 18:23
  • I was really excited to see this comment and hopeful that this would work, but it didn't. I have opened an issue with Okta on GitHub here: https://github.com/okta/okta-aspnet/issues/130 – Mark Good Jul 22 '20 at 11:56
  • 1
    I think Laura's comment on ReplaceIdentity is the answer. I know I got this working at my last company - just don't have access to the source code any more and it's been a while since I used the tech stack. I knew calling 'SignIn' did not sound right ... – Gary Archer Jul 22 '20 at 17:22
  • Hi @Gary. Thanks for the follow up. Using ReplaceIdentity wasn't the answer because it occurs after the cookie is set, so subsequent requests contain the old cookie, claims and tokens. But, I did find a great solution that it similar to one that you provided a link to. Use the .SignIn() method, but instead of creating a new ClaimsIdentity, use the current identity and simply remove the old token claims and add the new ones. Then call SignIn() which triggers the cookie middleware method the fires BEFORE the cookie is created. Problem solved! I describe it in the GitHub thread. – Mark Good Jul 22 '20 at 18:35