Skip to content

Instantly share code, notes, and snippets.

@kndt84
Last active May 17, 2024 03:11
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
};
};
@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