Skip to content

Instantly share code, notes, and snippets.

@kndt84
Last active August 13, 2023 10:55
Show Gist options
  • Save kndt84/5be8e86a15468ed1c8fc3699429003ad to your computer and use it in GitHub Desktop.
Save kndt84/5be8e86a15468ed1c8fc3699429003ad to your computer and use it in GitHub Desktop.
Sample code: how to refresh session of Cognito User Pools with Node.js and Express
const AWS = require('aws-sdk');
const CognitoUserPool = require('amazon-cognito-identity-js-node').CognitoUserPool;
const CognitoUserSession = require('amazon-cognito-identity-js-node').CognitoUserSession;
const CognitoUser = require('amazon-cognito-identity-js-node').CognitoUser;
const CognitoIdToken = require('amazon-cognito-identity-js-node').CognitoIdToken;
const CognitoAccessToken = require('amazon-cognito-identity-js-node').CognitoAccessToken;
const CognitoRefreshToken = require('amazon-cognito-identity-js-node').CognitoRefreshToken;
const cfg = require('config').config;
const COGNITO_IDENTITY_POOL_ID = cfg.COGNITO_IDENTITY_POOL_ID;
const COGNITO_USER_POOL_ID = cfg.COGNITO_USER_POOL_ID;
const COGNITO_CLIENT_ID = cfg.COGNITO_CLIENT_ID;
const AWS_API_GATEWAY_HOSTNAME = cfg.AWS_API_GATEWAY_HOSTNAME;
const AWS_REGION = cfg.AWS_REGION;
// Redirect to "/login" if a user is not logged-in.
exports.authorize = require('connect-ensure-login').ensureLoggedIn('/login');
exports.authorizeUser = function(req, res, next) {
AWS.config.region = AWS_REGION;
const tokens = req.user.tokens;
AWS.config.credentials = getCognitoIdentityCredentials(tokens);
AWS.config.credentials.get(function(err) {
if (err) throw err;
req.session.identityId = AWS.config.credentials.identityId;
const credentials = AWS.config.credentials.data.Credentials;
req.session.AWSCredentials = getAWSCredentials(credentials);
next();
});
};
exports.checkTokenExpiration = function(req, res, next) {
const AccessToken = new CognitoAccessToken({AccessToken: req.user.tokens.accessToken});
const IdToken = new CognitoIdToken({IdToken: req.user.tokens.idToken});
const RefreshToken = new CognitoRefreshToken({RefreshToken: req.user.tokens.refreshToken});
const sessionData = {
IdToken: IdToken,
AccessToken: AccessToken,
RefreshToken: RefreshToken
};
const cachedSession = new CognitoUserSession(sessionData);
if (cachedSession.isValid()) {
next();
} else {
cognitoUser = getCognitoUser(req);
cognitoUser.refreshSession(RefreshToken, (err, session) => {
if (err) throw err;
const tokens = getTokens(session);
AWS.config.credentials = getCognitoIdentityCredentials(tokens);
AWS.config.credentials.get(function() {
const credentials = AWS.config.credentials.data.Credentials;
req.session.AWSCredentials = getAWSCredentials(credentials);
next();
});
});
}
};
getCognitoUser = function(req) {
const poolData = {
UserPoolId : COGNITO_USER_POOL_ID,
ClientId : COGNITO_CLIENT_ID
};
const userPool = new CognitoUserPool(poolData);
const userData = {
Username : req.user.email,
Pool : userPool
};
return new CognitoUser(userData);
};
getTokens = function(session) {
return {
accessToken: session.getAccessToken().getJwtToken(),
idToken: session.getIdToken().getJwtToken(),
refreshToken: session.getRefreshToken().getToken()
};
};
getCognitoIdentityCredentials = function(tokens) {
const loginInfo = {};
loginInfo[`cognito-idp.${AWS_REGION}.amazonaws.com/${COGNITO_USER_POOL_ID}`] = tokens.idToken;
const params = {
IdentityPoolId: COGNITO_IDENTITY_POOL_ID,
Logins: loginInfo
};
return new AWS.CognitoIdentityCredentials(params);
};
getAWSCredentials = function(credentials) {
return {
accessKey: credentials.AccessKeyId,
secretKey: credentials.SecretKey,
sessionToken: credentials.SessionToken,
region: AWS_REGION,
invokeUrl: 'https://' + AWS_API_GATEWAY_HOSTNAME
};
};
@ispulkit
Copy link

Thanks!

@coreylight
Copy link

Thank you!

@anildbest83
Copy link

When cachedSession.isValid() is false you get the Cognito User using user email. Can't we get the tokens again with refresh token only?

@jayasimhaprasad
Copy link

i was searching for this code for the past 2 days. Thank you for taking time to put this code up #

@ubugnu
Copy link

ubugnu commented Aug 28, 2018

Question: in the official documentation (or better said: official examples) Use case 32, they use AWS.config.credentials.needsRefresh() to test session validity, you are using cachedSession.isValid().
I've tried the first, I got a session that needs refresh every time I refresh a brower window.

@ToddHoff
Copy link

Is there a way to just pass in the tokens from the web client down to the lambda function and make 'amazon-cognito-identity-js' use those tokens without needing the login name?

@afraz-khan
Copy link

afraz-khan commented Jan 3, 2020

Can you explain, how it is being checked that session is valid or not. Because, right in yr code, i dont see any productive use of isValid().

@vaibhavkumargautam
Copy link

vaibhavkumargautam commented Nov 28, 2020

Can you explain, how it is being checked that session is valid or not. Because, right in yr code, I don't see any productive use of isValid().

Yes, it has productive use. Access id and token come with an expiration time which can be configured from the console.

Here is the code behind isvalid(). It checks expiration time.

 isValid() {
const now = Math.floor(new Date() / 1000);

return now < this.accessToken.getExpiration() && now < this.idToken.getExpiration();
}

@ocemarcus
Copy link

Thank very much

@medmin
Copy link

medmin commented Jun 27, 2021

what if accessToken is expired ?

@vaibhavkumargautam
Copy link

You need to resend request with your refresh token

@shanitohl
Copy link

Thanks Thanks

@omaksimovich
Copy link

Hello everyone! Thanks a lot for the answer.
For people who faced with Unable to verify secret hash for client while refreshing the token, you can check the top answer for python

Short answer: simple use cognito:username from a token as userName for refresh token request signing

@trangnguyen-freec
Copy link

Hello everyone!

How can I tell aws cognito make current access token is invalid after I call adminInitiateAuth or initiateAuth to refresh token?
Please help me.

@zeestack
Copy link

I think you may need to revoke tokens before initiating auth via admin or initiateAuth.

@not-steve-jobs
Copy link

not-steve-jobs commented Feb 17, 2023

getCognitoUser = function(req) { const poolData = { UserPoolId : COGNITO_USER_POOL_ID, ClientId : COGNITO_CLIENT_ID }; const userPool = new CognitoUserPool(poolData); const userData = { Username : req.user.email, Pool : userPool }; return new CognitoUser(userData); };

here I can write any email, and result success )

I think this not correct

@Francowerner
Copy link

Does anyone here know how to update this to AWS v3 javascript sdk? i dont understand a thing about the new modular architecture

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment