I want to force-refresh the AWS cognito token in the client, so that as soon as a user logs in the app immediately uses the refresh token to get a new access token (with longer exp time). I've read about initiateAuth and cognitoUser.refreshSession() methods, but I'm not sure which one I need to use? I'm trying the below method and I am getting a new token back but it's always just valid for 1 more hour (at least that is what I see when I check the exp time on the token). I want to get a token that is valid for 30 days (which is what I have configured in cognito). Any help will be greatly appreciated!
const getTokens = function(session) {
return {
accessToken: session.getAccessToken(),
idToken: session.getIdToken(),
refreshToken: session.getRefreshToken()
};
cognitoUser.refreshSession(refreshToken, (err, session) => {
if (err) {
console.log(err);
} else {
const tokens = getTokens(session);
console.log(tokens);
localStorage.setItem("sessionTokens", JSON.stringify(tokens));
}
}
The ID and Access token in Cognito are valid for 1 hour and this is not configurable. You mentioned you have configured the tokens to last for 30 days, this is the validity/expiry time of your refresh tokens.
Calling certain methods on the client side SDKs (Amplify or identity SDK) will automatically check the validity and expiry time of the tokens and refresh them if needed.
This has now changed as can be seen here:
https://aws.amazon.com/about-aws/whats-new/2020/08/amazon-cognito-user-pools-supports-customization-of-token-expiration/
Cognito recently added options to configure the token validity.
Refresh tokens can have a TTL from 60 minutes to 365 days.
ID tokens and Access tokens can have a TTL from 5 minutes to 1 day
just look in the details of your user pool app client, the new fields are in there for easy configuration.
Related
I have a project with NodeJS with jwt for managing user authentication. After a period of time, my app stops working and my server prints the following:
return done(new TokenExpiredError('jwt expired', new Date(payload.exp * 1000)));
^
TokenExpiredError: jwt expired
Now, the person who was working in this project before me had this code for managing the tokens:
static generateToken(username, type, id) {
return jwt.sign(
{
username,
type,
id
},
API_SECRET,
{
expiresIn: '7d'
}
);
}
static generateRefreshToken(username, type, id) {
return jwt.sign(
{
username,
type,
id
},
API_SECRET_REFRESH,
{
expiresIn: '30d'
}
);
}
My guess is that the issue is the expiresIn: '7d' (since I'm quite new with jwt). I also know what we can omit the expiresIn field to make the token not expire at all. My question is: Is it safe to omit said field or there's another way to tackle this kind of error message? Since every time that message pops up, I have th delete the entire browsing history of my browser (or run my project in incognito mode) in order for it to start working again.
You should not create a token that does not expire. So, you should keep the expiresIn config.
That being said, you don't have to use refresh token strategy. There are a lot of ways to handle this. For example, you can do the following:
Create /check-token endpoint that will check if the current token is still valid.
Create token when user logs in. Token will be valid for 7 days for example.
Each time user opens your application call the /check-token endpoint. If current token is not valid, logout the user. If current token is valid, generate new token that will be valid for another 7 days and continue to authenticate the user with new token.
Yes, this is one of the most common problems, it is possible to solve it with a refresh token, what this function does is that when the token expires, a request is made from the front to obtain a new one, here is a link with an example of implementation in node js:
Link: https://www.bezkoder.com/jwt-refresh-token-node-js/
The problem is that even after expiration time that is 5 min for ID token and access token, the session is still validated for some reason I cannot understand. Can someone help me what should I Do?
let cognitoUser = userPool.getCurrentUser();
if (cognitoUser != null) {
await cognitoUser.getSession((err, session) => {
if (err) {
console.error(err.message);
return;
}
console.log('session validity: ' + session.isValid());
I tried waiting for 5 min or more to check if token has expired or not but it still says that it is valid whereas I was expecting it will go to refresh token function.
Ok, so I found what getSession does. It gets a token from your local storage, object storage or refresh token. Suppose it doesn't find the currentUserSession when you call getCurrenUser(). In that case, it will use the refresh token to get the session. It simply means that the already available session data was nullified and replaced with the new one you just got. The session will always stay valid whenever it uses a refresh token to get session data.
I'm implementing jwt token for user verification purposes. I sign a jwt token whenever a user sign-ins and store that token in my database. Then whenever the user wants to access their personal information, they send me their token and I check if such token exists in the database, if it does, I allow access (please reccommend if you know better ways for user verification). The thing is, I want my token to expire every 24 hours, which means every 24 hours I want the token in my database to become an empty string, however I did some experiments:
const jwt = require('jsonwebtoken')
var token = jwt.sign({d:'tt'}, 'prvateKey', {expiresIn: 1000});
setTimeout(()=>{
console.log(token)
}, 3000)
the code above console logs the actual token instead of an empty string, null, or something like that.
So is my code somewhat wrong or does expiration mean something different than what I think?
jwt.sign returns the token as a string. This will not automatically become empty on expiry, it's just a string. However, the token will become invalid. You can check token validity using the jwt.verify method. jwt.verify will error if the token is not valid.
The expiresIn option is a convenience to set the token exp claim. This is what the jwt spec says about this claim:
The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing.
https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4
The jsonwebtoken package documentation also says:
expiresIn: expressed in seconds or a string describing a time span zeit/ms.
https://www.npmjs.com/package/jsonwebtoken#token-expiration-exp-claim
With the jsonwebtoken package, an expired token actually translates in the verify() function throwing an exception with a TokenExpiredError name when passing it the token for processing.
var jwt = require("jsonwebtoken")
var data = {
"data": "some data"
}
var secret = "secret"
var token = jwt.sign({ data }, secret, { expiresIn: 1 })
setTimeout(function () {
try {
var payload = jwt.verify(token, secret)
} catch (error) {
console.log(error.name) // output: TokenExpiredError
}
}, 1000)
Using https://github.com/netlify/gotrue-js to interface with netlify's authentication service (called "Identity") how frequently is it necessary to do the following:
const user = auth.currentUser();
const jwt = user.jwt();
jwt
.then(response => console.log("This is a JWT token", response))
.catch(error => {
console.log("Error fetching JWT token", error);
throw error;
});
Will the resulting JWT be valid forever? For the duration of the user's logged-in session? Or does it expire after a given amount of time?
Generally JWTs contain can (optionally) contain an exp (expiration) claim, that contains the time when it will expire.
I don't have experience with GoTrue, but according to their documentation you can configure the expiration, and it's set to a default value of 3600 seconds.
As the library also works with refresh tokens, you won't have to re-authenticate again after the token expires but use the refresh token to get a new access token.
I'm using the access refresh jwt authentication flow and want the client to send a refresh token to get a new access token every 10 minutes after it received the access token. I also want to make sure that if the user closes their laptop for an hour and comes back to it that a new access token request is also sent. What is the best way to implement this behavior in React/redux, where the user will always have a valid access token and seamlessly keeps their "session" going?
To achieve that you can conditionnally check the expiration of the token before each request instead of setting a timer.
This will depend on the way you communicate with the server but the idea is to store client side the jwt token, his expiration and the refresh token (and his expiration too if needed) then use some sort of middleware before each request that need the auth :
const authClientMiddleware = (done) => {
if (new Date(localStorage.getItem('expiration')) <= new Date()) {
getNewToken(localStorage.getItem('refreshToken')).then(() => done()).catch(() => logout());
} else {
done();
}
}