I'm developing the authentication flow of a single page application (AngularJS + .Net MVC Json Rest API) using Owin Oauth2 (Authorization and Resource servers are the same).
I've chosen the Bearer Token route over the traditional cookie+session because I would like to stay stateless and also because the same Api will be used by a mobile app where token has less problem than the cookie.
This is the simplified flow:
AccessToken
with a claim containing
a generated GUID (that will represent something like a Session Id) and some other claims.RefreshToken
.RefreshToken
table with the following fields:GUID(PK)|RefreshToken|Ticket|DateIssued|DateExpire|DateEnd
Server gives both the AccessToken
and the
RefreshToken
to the client.
Client stores both the AccessToken
and RefreshToken
into the SessionStorage.
The client accesses the API with the AccessToken
.
When AngularJS detects that the AccessToken is near to expire, it buffers all the requests and issues a grant_type refresh_token request
;
the server uses the RefreshToken
provided by the client and:
DateExpire > GetTime() And DateEnd is Null
)RefreshToken
and the new Ticket (Note: the GUID remains the same)When the client hits the logout server-side, the GUID read from the identity claim of the logged user is used to invalidate the entry on the table (DateEnd = GetTime()
).
Client-side both tokens are removed from the SessionStorage
.
In this way, I can revoke the RefreshToken
denying any other requests to get a fresh AccessToken
.
The problem with this approach is that there is a window of time when the authorization is revoked (ie: RefreshToken
invalidated on DB) but the AccessToken
is still valid (although for a limited frame of time).
What I'm thinking to do is to check the validity of the AccessToken
on each request, taking the GUID from the user identity claims and hitting the db to check if the Refresh Token of that specific GUID is still valid.
Although it's quite trivial to make queries performing O(1), the single point of failure itself can have negative impact on the scalability and performance of the system.
Do you know another method to mitigate this problem and do you see any flaws in my approach?
There is nothing wrong with your approach and it is very identical to the approach I've blogged about earlier, but my recommendation is not to do any DB checks when you send the access token.
Why you do not issue short-lived access tokens i.e (30 mins) and you wait until the access token lifetime is expired after revoking the refresh token. And on the client, you can clear the refresh token and access token from your client's local storage.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With