Using Cognito to authorize users
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 | |
| } | |
| }); | |
| }); | |
| } |