Skip to content

Instantly share code, notes, and snippets.

@kndt84
Last active May 17, 2024 03:11
Show Gist options
  • Select an option

  • Save kndt84/5be8e86a15468ed1c8fc3699429003ad to your computer and use it in GitHub Desktop.

Select an option

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
};
};
@anildbest83

Copy link
Copy Markdown

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
Copy Markdown

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

@ubugnu

ubugnu commented Aug 28, 2018

Copy link
Copy Markdown

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
Copy Markdown

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

afraz-khan commented Jan 3, 2020

Copy link
Copy Markdown

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

vaibhavkumargautam commented Nov 28, 2020

Copy link
Copy Markdown

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
Copy Markdown

Thank very much

@medmin

medmin commented Jun 27, 2021

Copy link
Copy Markdown

what if accessToken is expired ?

@vaibhavkumargautam

Copy link
Copy Markdown

You need to resend request with your refresh token

@shanitohl

Copy link
Copy Markdown

Thanks Thanks

@omaksimovich

Copy link
Copy Markdown

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
Copy Markdown

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
Copy Markdown

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

@not-steve-jobs

not-steve-jobs commented Feb 17, 2023

Copy link
Copy Markdown

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
Copy Markdown

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