Using Cognito for users management in your Serverless application

David
David
Feb 15, 2019 · 5 min read

One of the cool API Gateway features is the way it handles access control. Among other options, it can leverage IAM credentials or API keys to authorize your endpoints, but if none of that fits your needs it also has Lambda (formerly Custom) Authorizers, which pretty much lets you set your own rules. However, in certain cases you don’t only need a way of protecting your API, but you also want to let users register in your app, verify their email addresses, reset passwords or allow them to login and register using social providers such as Facebook. You could certainly build all those features from the ground up and store your users’ data in a database of your choice, but why would you do that when all you need to do is run serverless deploy? Cognito User Pools provides that and much more, just by adding some Cloud Formation resources to the serverless.yml file, your serverless app will have users management capabilities. (Working example here)

Image for post
Image for post

What is a Cognito User Pool?

It’s important to note that the outcome of Cognito when a user logs in is a JSON Web Token, not AWS credentials, which means that you can pretty much use it with any API you build. However, if you’re using API Gateway, this task becomes much simpler, as Cognito already has a Lambda Authorizer you can use. Let’s see how we can integrate it in our Serverless app.

Creating a Cognito User Pool in your Serverless service

CognitoUserPool:
Type: "AWS::Cognito::UserPool"
Properties:
MfaConfiguration: OFF
UserPoolName: my-user-pool
UsernameAttributes:
- email
Policies:
PasswordPolicy:
MinimumLength: 6
RequireLowercase: False
RequireNumbers: True
RequireSymbols: False
RequireUppercase: True

The user pool is not enough on its own, we also need to create an App Client. The App Client allows applications (mobile, web, server-side, etc.) to issue requests to the Cognito APIs that are normally unauthenticated, such as APIs to register, sign in or recover passwords. We just need to add the resource below:

CognitoUserPoolClient:
Type: "AWS::Cognito::UserPoolClient"
Properties:
ClientName: my-user-pool-client
GenerateSecret: False
UserPoolId:
Ref: CognitoUserPool

That was pretty easy, but how can our users sign up? We could just go ahead and integrate the User Pool with our app using either the Javascript, Android or iOS SDKs. Even though that should be fairly straightforward, we’ll take an easier road: we’ll use Cognito’s Hosted UI.

Using the Hosted UI

Image for post
Image for post
Cognito User Pool App Client Settings

Almost there, only one step left! Before you move on, take note of the Client ID that appears on top of the page, because you’re going to need it afterwards. Now go ahead and select Domain name, where you’ll create the domain your users will sign in and register from:

Image for post
Image for post
Cognito Domain Name Settings

And that’s it! Direct your users to https://<your_domain>/login?response_type=token&client_id=<your_app_client_id>&redirect_uri=<your_callback_url> and you won’t need to handle sign ins, registrations or password resets. Go ahead and replace the missing pieces in the previous URL with your own Cognito URL, Client ID and Callback URL, paste it into your browser and try it out yourself. After successfully signing in or registering, you’ll be redirected to https://<your_callback_url>/#id_token=123456789tokens123456789&expires_in=3600&token_type=Bearer, just remember that you’ll have to store the value of id_token in your front-end app to call the API.

Protecting API Gateway Endpoints

ApiGatewayAuthorizer:
DependsOn:
- ApiGatewayRestApi
Type: AWS::ApiGateway::Authorizer
Properties:
Name: cognito-authorizer
IdentitySource: method.request.header.Authorization
RestApiId:
Ref: ApiGatewayRestApi
Type: COGNITO_USER_POOLS
ProviderARNs:
- Fn::GetAtt: [CognitoUserPool, Arn]

Last but not least, we have to attach the newly created authorizer to the endpoints we’d like to protect:

registeredOnly:
handler: handler.hiUsers
events:
- http:
path: /hiUsers
method: get
authorizer:
type: COGNITO_USER_POOLS
authorizerId:
Ref: ApiGatewayAuthorizer

Now, whenever we want to access the /hiUsers endpoint, we must provide a valid id_token in the HTTP Authorization header.

Conclusion

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store