Skip to content

Instantly share code, notes, and snippets.

@oieduardorabelo
Created February 24, 2021 05:11
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save oieduardorabelo/fbd9780c7897b53418b86c7c5bda745f to your computer and use it in GitHub Desktop.
Save oieduardorabelo/fbd9780c7897b53418b86c7c5bda745f to your computer and use it in GitHub Desktop.
Sample of Cognito with Server-Sider Authentication
PORT=xxx
COGNITO_USER_POOL_ID=xxx
COGNITO_CLIENT_ID=xxx
COOKIE_SESSION_SECRET=xxx
COOKIE_SESSION_NAME=xxx
AWS_REGION=xxx
AWS_ACCESS_KEY_ID=xxx
AWS_SECRET_ACCESS_KEY=xxx
require("dotenv").config();
let express = require("express");
let session = require("cookie-session");
let chance = require("chance").Chance();
let aws = require("aws-sdk");
let {
PORT,
COOKIE_SESSION_SECRET,
COOKIE_SESSION_NAME,
COGNITO_USER_POOL_ID,
COGNITO_CLIENT_ID,
} = process.env;
let app = express();
let cognito = new aws.CognitoIdentityServiceProvider();
app.use(
session({
secret: COOKIE_SESSION_SECRET,
name: COOKIE_SESSION_NAME,
cookie: {
secure: false,
httpOnly: true,
},
})
);
app.get("/", async (req, res) => {
if (req.session.user) {
return res.redirect("/me");
}
let email = chance.email();
let password = chance.string({ length: 6 });
await cognito
.signUp({
ClientId: COGNITO_CLIENT_ID,
Username: email,
Password: password,
})
.promise();
await cognito
.adminConfirmSignUp({
UserPoolId: COGNITO_USER_POOL_ID,
Username: email,
})
.promise();
let tokens = await cognito
.adminInitiateAuth({
AuthFlow: "ADMIN_USER_PASSWORD_AUTH",
ClientId: COGNITO_CLIENT_ID,
UserPoolId: COGNITO_USER_POOL_ID,
AuthParameters: {
USERNAME: email,
PASSWORD: password,
},
})
.promise();
// {
// ChallengeParameters: {},
// AuthenticationResult: {
// AccessToken: '...',
// ExpiresIn: 3600,
// TokenType: 'Bearer',
// RefreshToken: '...',
// IdToken: '...'
// }
// }
let user = await cognito
.adminGetUser({
UserPoolId: COGNITO_USER_POOL_ID,
Username: email,
})
.promise();
// {
// Username: '0b344599-36e7-4dd2-bf82-d8d451ea0332',
// UserAttributes: [
// { Name: 'sub', Value: '0b344599-36e7-4dd2-bf82-d8d451ea0332' },
// { Name: 'email_verified', Value: 'false' },
// { Name: 'email', Value: 'senobupa@ho.bn' }
// ],
// UserCreateDate: 2021-02-24T04:56:35.649Z,
// UserLastModifiedDate: 2021-02-24T04:56:36.996Z,
// Enabled: true,
// UserStatus: 'CONFIRMED'
// }
req.session.user = {
cognitoId: user.Username,
email: user.UserAttributes.find((key) => key.Name === "email").Value,
// accessToken: tokens.AuthenticationResult.AccessToken,
// refreshToken: tokens.AuthenticationResult.RefreshToken,
// idToken: tokens.AuthenticationResult.IdToken,
};
return res.redirect("/me");
});
app.get("/logout", async (req, res) => {
await cognito
.adminUserGlobalSignOut({
UserPoolId: COGNITO_USER_POOL_ID,
Username: req.session.user.cognitoId,
})
.promise();
req.session = {};
return res.redirect("/me");
});
app.get("/me", async (req, res) => {
res.send({ user: req.session.user });
});
app.listen(PORT, () => {
console.log(`[APP] Up and running at ::${PORT}`);
});
@oieduardorabelo
Copy link
Author

oieduardorabelo commented Feb 24, 2021

The example above assumes a few things:

  • There's NO MFA CONFIGURED in the Cognito User Pool
  • There's NO ATTRIBUTE VERIFICATION by the Cognito User Pool (e.g. email, phone number etc)
  • Password policy is "Minimum length: 6" only (e.g. numbers, special character verification are turned off)

If you have any of them, they are called "AuthChallenge", more information in https://aws.amazon.com/blogs/mobile/customizing-your-user-pool-authentication-flow/, and you will need to call the correct Cognito API to respond to the challenge.

Details about the Server-Side Authentication Flow:

https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html#amazon-cognito-user-pools-server-side-authentication-flow

From the docs:

The server-side app calls the AdminInitiateAuth API operation (instead of InitiateAuth). This operation requires AWS admin credentials. This operation returns the authentication parameters.

You can either use IAM Role (credentials resolved automatically by the "aws-sdk") or AWS Credentials environment variables by exporting AWS_ACCESS_KEY_ID=xxx and `AWS_SECRET_ACCESS_KEY=xxx, like in the example above,

Make sure your Cognito App Client only supports admin based (aka server-side) authentication:

Screen Shot 2021-02-24 at 6 14 01 pm

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