Using cognito in serverless

Setup Cognito in serverless

Firstly, you have to add Cognito User Pool and User Pool Client resources to the serverless file:

CognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: ${self:custom.CognitoUserPoolName}
Policies:
PasswordPolicy:
RequireLowercase: true
RequireSymbols: false
RequireUppercase: false
MinimumLength: 6
CognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: user-pool-client
UserPoolId:
Ref: CognitoUserPool
ExplicitAuthFlows:
- ADMIN_NO_SRP_AUTH
GenerateSecret: false

For convenience, we will declare a custom variable at the top level of the serverless file:

custom:
CognitoUserPoolName: user-pool # Name for your cognito user pool

If you want to autoconfirm users who sign up, you need to add preSignUp function to your lambda functions list:

preSignUp:
handler: handler.preSignUp
events:
- cognitoUserPool:
pool: ${self:custom.CognitoUserPoolName}
trigger: PreSignUp
existing: true

And write the following handler for this function

module.exports.preSignUp = async (event, context, callback) => {
  // Confirm the user
  event.response.autoConfirmUser = true;
  // Return to Amazon Cognito
  callback(null, event);
};

If you want to authorize your lambda functions using Cognito user pool, you need to add a resource Authorizer:

MyCognitoAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
AuthorizerResultTtlInSeconds: 300
IdentitySource: method.request.header.Authorization
RestApiId:
Ref: ApiGatewayRestApi
Name: MyCognitoAuthorizer
Type: COGNITO_USER_POOLS
ProviderARNs:
- {"Fn::Join": ["", ["arn:aws:cognito-idp:", {Ref: "AWS::Region"}, ":", {Ref: "AWS::AccountId"}, ":userpool/", Ref: CognitoUserPool]]}

And add authorizer for selected function, for example:

functions:
# This function will add note
addNote:
handler: handler.addNote
events:
- http:
path: /add/
method: put
cors:
origin: '*'
headers:
- Content-Type
- Authorization
allowCredentials: false
authorizer:
type: COGNITO_USER_POOLS
authorizerId:
Ref: MyCognitoAuthorizer

Integrating frontend with Cognito using amazon-cognito-identity-js

Registering a user with the application. One needs to create a CognitoUserPool object by providing a UserPoolId and a ClientId and signing up by using a username, password.

var poolData = {
UserPoolId: '...', // Your user pool id here
ClientId: '...', // Your client id here
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
userPool.signUp('username', 'password', attributeList, null, function(
err,
result
) {
if (err) {
alert(err.message || JSON.stringify(err));
return;
}
var cognitoUser = result.user;
console.log('user name is ' + cognitoUser.getUsername());
});

To login you need to authenticate a user with the Amazon Cognito Identity service.

var authenticationData = {
Username: 'username',
Password: 'password',
};
var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(
authenticationData
);
var poolData = {
UserPoolId: '...', // Your user pool id here
ClientId: '...', // Your client id here
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
var userData = {
Username: 'username',
Pool: userPool,
};
var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function(result) {
var accessToken = result.getAccessToken().getJwtToken();
},
onFailure: function(err) {
alert(err.message || JSON.stringify(err));
},
});

Signing out from the application.

cognitoUser.signOut();

Retrieving the current user from local storage.

var poolData = {
UserPoolId: '...', // Your user pool id here
ClientId: '...', // Your client id here
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
var cognitoUser = userPool.getCurrentUser();
if (cognitoUser != null) {
cognitoUser.getSession(function(err, session) {
if (err) {
alert(err.message || JSON.stringify(err));
return;
}
console.log('session validity: ' + session.isValid());
// NOTE: getSession must be called to authenticate user before calling getUserAttributes
cognitoUser.getUserAttributes(function(err, attributes) {
if (err) {
// Handle error
} else {
// Do something with attributes
}
});
});
}