Search code examples
asp.net-web-apioauthoauth-2.0asp.net-coreaspnet-contrib

Refresh Tokens - Server Side Storage And Revoking For Multiple Clients


I'm getting started with token based authentication using the ASOS (AspNet.Security.OpenIdConnect.Server) framework.

I've got the access token generation and retrieval done and am now moving on to the refresh token bit.

My questions are:

  • How should I store the refresh token server side?
    • Should I just store the clientID and the hashed and salted refresh token in a database (Along with utility fields, such as an expiration date)?
  • What is the expected behaviour if a user of my API has a single clientID and secret, but performs many calls concurrently (Suppose they want to scale out the client on their end across multiple machines to get better throughput for example).
    • Specifically, I mean what if 1 of the client's access tokens expires, but their refresh token has also expired? Of course they can go to the token endpoint to get a new access token and refresh token at the same time, but then what about the other instances for that clientID? Assuming that their code is identical (i.e. they don't share knowledge of the refresh token), each instance will also go on to request a new access and refresh token.
    • If you store a single refresh token for a clientID, you'll end up excessively requesting refresh tokens, potentially every time the access token expires, which would be undesirable.
    • If you store multiple refresh tokens for a client, how many is a sensible number?

Also, what is the common process of revoking the refresh tokens? Is it as simple as just deleting it from wherever you're storing it?

Thanks.


Solution

  • Should I just store the clientID and the hashed and salted refresh token in a database (Along with utility fields, such as an expiration date)?

    The approach I recommend is to use the ticket identifier attached by ASOS to all the tokens it creates. You can retrieve the refresh token identifier and the expiration date from the SerializeRefreshToken event via context.Ticket.GetTokenId() and context.Ticket.ExpiresUtc.

    Note: the default identifier is a GUID but you can replace it using context.Ticket.SetTokenId("token identifier").

    Specifically, I mean what if 1 of the client's access tokens expires, but their refresh token has also expired? Of course they can go to the token endpoint to get a new access token and refresh token at the same time, but then what about the other instances for that clientID?

    It really depends on your application requirements and how you implement that. You're free to consider refresh tokens as completely independent or, conversely, interdependent. This logic would usually take place into HandleTokenRequest.

    Also, what is the common process of revoking the refresh tokens? Is it as simple as just deleting it from wherever you're storing it?

    If you use the default token format (more than recommended), refresh tokens will be considered valid until they expire. It's up to you to check whether the token has been revoked from HandleTokenRequest by making a DB lookup (you can get the refresh token identifier using context.Ticket.GetTokenId())