How to revoke older reference token when client request for new reference token in IdentityServer3? - identityserver3

I have a scenario where the client is invoking http://localhost/connect/token endpoint to get reference token (Note: this is grant_type = client_credentials), if client_id, client_secret & scope matches then IdentityServer will return valid reference token. Let's say this reference token is valid for 1 day.
Now after sometimes(say 30 minutes or so) client requesting again for new reference token and IdentityServer return new reference token.
Is there any way to revoke old reference token and client can only use new reference token?

Use method ITokenHandleStore.RemoveAsync(string) to revoke particular token.
You can override method ITokenHandleStore.StoreAsync(string, Token) to remove old token prior to storing new token. However you'll need to create your own implementation of ITokenHandleStore.
On the other hand, your users can call token revocation endpoint to revoke tokens on their own.

Related

Difference in types of token

I am hearing continously token name of different type. Can anybody explain me different type of token with some example.
Access token
Refresh token
Oauth Token
Bearer token
JWT token.
Please forgive me if my question is incorrect. I am highly consfused so looking for the answer.
Right, terminology can be very confusing. OAuth2 is the protocol to allow a client to get an access token to access the user's data on a resource server. The protocol is token agnostic (meaning it does not specify how the token looks). So OAuth token and access token are used interchangeably.
Often, the access token used in the protocol is a structured token in the JSON Web Token (JWT) format. It contains claims (name-value pairs) with info about the user and authentication that the resource server can use.
A bearer token is any token that can be used as the sole way of authenticating. If you have the token, you get access as the user for which it was issued. Nothing else required. OAuth2 typically uses bearer tokens, although some holder-of-key tokens (where you need to prove you acquired the token by signing something) are being added to the protocol. JWT tokens are usually bearer tokens.
Refresh tokens are used in some OAuth2 protocol flows to allow the client to get a new access token when the issued one expires without asking the user to log in again. They are typically just an identifier to some row in the data store of the authorization server.

Is it secure to store a refresh token in the database? (To issue new access tokens for login purposes). Or is there a method to do it easier?

Currently im trying to gather knowledge on how to implement an auth system (a login) . And during my research i've tried to implement a JWT based solution in my backend.
I have an express server which allows me to register an user , storing its password (encrypted) and its email.
After that on login, it generates an access token (short lived, 5min) , in order to access protected routes, and a refresh token (long lived, 7 days), in order to generate new access tokens once the previous expire.
In my current implementation, im storing the refresh token in my database, so I can use it every time I want to generate a new access token.
But is that secure? As far as I understand, storing an access token in my database is dangerous, so its better to create a short lived cookie stored one. But... the refresh token? As far as i understand it would be dangerous since it basically allows to generate new access tokens, so I dont see the point of why not simply storing a long lived access token in my database, an generating a new one in every login.
Whats is the refresh token for then?
Since im following some tutorials in order to achieve this, this is how my refresh_token route looks
//get a new access token with a refresh token
app.post('/refresh_token', (req, res) => {
const token = req.cookies.refreshtoken
//if no token in request
if(!token) return res.send({accesstoken : ''});
//if we have a token we verify it
let payload = null;
try{
payload = verify(token, process.env.REFRESH_TOKEN_SECRET);
}catch(err){
return res.send({accesstoken: ''});
}
//if token is valid check if user exist
const user = fakeDB.find(user => user.id === payload.userId)
if(!user) return res.send({ accesstoken: ''});
//if user exists check if refreshtoken exist on user
//Is this really necessary? <-------------------------------------------
if(user.refreshtoken !== token){
return res.send({accesstoken: ''})
}
//if token exist create a new Refresh and Accestoken
const accesstoken = createAccessToken(user.id);
const refreshtoken = createRefreshToken(user.id);
user.refreshtoken = refreshtoken;
//send new refreshtoken and accesstoken
sendRefreshToken(res, refreshtoken);
return res.send({accesstoken});
})
The arrow comment is where I have my doubts, ok its returning an empty access token if my database table user (its a mock database so an array so far) , doesnt have stored a refresh token. But why would you do that? Is that used to not let arbitrary users generate access tokens? As far as I understand thats the only reason of why would I do that.
But again then, isnt it dangerous to store in a database? WHy not simply store the access token then make it a long lived token, and generate a new one in every login?
Is there a method to do it simplier than with jwt?
Why access tokens should be short-lived: if you want a decentralised auth flow (authentication service signs a token, other services can verify if it's valid using an asymmetric public key), you want that token to be short-lived because it cannot be blacklisted in case it's stolen (an attacker can use it until it expires). You can of course blacklist access tokens using i.e. Redis, but your auth flow won't be decentralised anymore. All services will have to validate that token using the asymmetric public key AND check if it's blacklisted or not (better just ask authentication service if it's valid or not).
This is how I would go about it:
5 minute access token as JWT (self-contained, don't need to store it
anywhere).
7 day refresh token for one-time usage: generate random secret (don't need to sign it/encrypt it), store it in Redis with a 7 day TTL (or MySQL with a valid_until timestamp). On /refresh_token validate the provided token (check if it's in Redis/MySQL) and delete it. Generate a new access and refresh token pair. (I like to rotate refresh tokens as well, it makes it a bit more secure: it's probably already rotated=invalid if stolen)
This way the auth flow stays decentralised and refresh tokens can be revoked if they are stolen.
Refresh tokens should be encrypted in storage. The OAuth 2.0 Threat Model and Security Considerations RFC goes into this:
4.5.2. Threat: Obtaining Refresh Token from Authorization Server Database
This threat is applicable if the authorization server stores refresh tokens as handles in a database. An attacker may obtain refresh tokens from the authorization server's database by gaining access to the database or launching a SQL injection attack.
Impact: Disclosure of all refresh tokens.
Countermeasures:
Enforce credential storage protection best practices
(Section 5.1.4.1).
Bind token to client id, if the attacker cannot obtain the
required id and secret (Section 5.1.5.8).
And then the referenced section 5.1.4.1.3:
5.1.4.1.3. No Cleartext Storage of Credentials
The authorization server should not store credentials in clear text. Typical approaches are to store hashes instead or to encrypt credentials. If the credential lacks a reasonable entropy level (because it is a user password), an additional salt will harden the storage to make offline dictionary attacks more difficult.
Note: Some authentication protocols require the authorization server to have access to the secret in the clear. Those protocols cannot be implemented if the server only has access to hashes. Credentials should be strongly encrypted in those cases.

AWS Cognito - Validating Tokens with Cognito Node.js

My understanding is that upon successful login Cognito provides my service three tokens for a user, access, ID and refresh. In order to verify a token I'm using jsonwebtoken (jwt.verify(accessToken, pem)). This is all fine, I'm able to verify a token and obtain a new access token with my refresh token if it's expired.
However, my accessToken is valid for one hour. If I want to revoke all of a users tokens using cognitoUser.globalSignOut(), that token will pass my JWT verification using the JWT library for 60 mins as that is all done server side.
Is there a way to send a token to AWS Cognito and ask "Hey is this Token still valid?"
This thread might help you understand how a call to globalSignOut() affects the validity of the 3 tokens.
Is it possible to revoke AWS Cognito IdToken?
Cognito does not have an API to check the validity of the token. You will have to call one of your APIs and check if the call was successful or not.

Is the IdentityServer3 session configurable so it expires when the access token expires?

I need the IdentityServer3 session to expire at the same time as the access token. When the access token expires the user is being redirected to IdSvr it's just automatically issuing new Id and Access tokens. I want to force the user to authenticate again when the access token expires. I'm using the Implicit flow so I don't believe refresh token lifetimes come into play. I'm also using the OIDC-client-JS library.
Your approach doesn't make sense -- what would happen if there were 2 different access tokens?
The better approach is from the client to pass the prompt=login or max_age parameter on the authorization request. See the docs for more info: https://identityserver.github.io/Documentation/docsv2/endpoints/authorization.html

is the Authorization code in OAuth 2 is used only once for the lifetime of the client Application running server?

I am reading this blog on how OAuth2 works. It is an excellent source and I guess I have understood the basics of how OAuth2 works.
when reading about Authorization grant, that involves granting access to the Application server (my server) which exchanges the authorization code it received from authorization sever (eg facebook) through the redirect URI registered.
myserver then exchanges this authorization code for access_token and refresh token. when the access token is expired, refresh token is used to get a new access token.
Q1) From this flow, I see that the authorization code given by facebook is used only once from my server to get the access_token. For subsequent requests, this authorization code is not used. Is this correct ?
If the user log-in to my server after 3 days during which the access token has expired, my server will use refresh token to get a new access token and use this access token.
Q2) Does the refresh token expire or each time a refresh token is used to get a new access token, a new refresh token is provided?
Q1) RFC6749, Section 4.1.2 Authorization Response: The client MUST NOT use the authorization code more than once.
Q2) RFC6749, Section 6 Refreshing an Access Token: The authorization server MAY issue a new refresh token, in which case the client MUST discard the old refresh token and replace it with the new refresh token.