Sayantam Dey on Product Development

Authentication and Authorization with AWS - Cognito Sign-up and Sign-in

Oct 17, 2021
Cognito User and Identity Pools

Amazon Web Services (AWS) provides Cognito to delegate authentication and authorization out of applications completely. This post is part two of the series on Authentication and Authorization with AWS, while the first part is on AWS IAM Concepts.

AWS Cognito delivers a managed service that enables applications to register and sign-in users. It supports sign-in from social providers such as Facebook, Google, plus enterprise identity providers via SAML and OpenID Connect (OIDC).

There are two kinds of pools in AWS Cognito.

User Pools

Cognito User Pools is a scalable managed service that provides a secure identity store. All the users have a programmable directory profile.

Identity Pools

Cognito Identity Pools provide AWS credentials for both authenticated as well as unauthenticated users (guests). The AWS credentials provided to guests are temporary.

Sign up and Sign-in

Cognito User Pools offer standard workflows for user registration and sign-in. It also provides hooks to inject custom logic to process incoming requests. The hooks are implemented using AWS Lambda.

Cognito user registration and sign-in workflow

Anyone with appropriate privileges can create a User Pool through the user interface or the CLI / API. Creating a User Pool is a straightforward affair.

One of the steps is to create an app client that will use this User Pool. The step sets some defaults values that are adjustable for token expiry. The tokens are the following.

  • Access Token: Authorizes access to one or more server resources.
  • ID Token: Additional token in the OpenID Connect (OIDC) that contains information about a user and their

authentication status.

  • Refresh Token: Special kind of token to renew an access token.

The other step to watch out for is settings for the app client.

  • The callback URLs need to be HTTPS unless the domain is localhost.
  • OAuth 2.0 flows and scopes need to be selected to activate the Hosted UI. These selections depend on your

authorization workflows. To see how it all works, you can choose "Implicit grant" for flows. It is sufficient to check the "profile" scope for scopes, but you could add more.

After creating the User Pool and setting up the app client, the Cognito UI should activate the Hosted UI.

Cognito Hosted UI Login

Depending on the User Pool settings, Cognito will send a verification link to the email provided at sign-up. Follow the process to sign up as a new user, and come back to the sign-in screen. On sign-in, Cognito will redirect to the callback URLs provided with the app client. So, the listener service must be running before the sign-in.

The following sets up a simple listener available at /sign-in path.

/* This code is for illustrative purposes only. Libraries published by AWS or specialized packages are recommended 
 * for production level code. 
 */ 

import express from 'express'
import https from 'https'

const {
  appClienId, 
  appClientSecret,
  port = 9000,
  domain,
  region
} = process.env

const authSecret = Buffer.from(`${appClienId}:${appClientSecret}`).toString('base64')

const app = express()

app.use(express.urlencoded({extended: true}))

app.get('/sign-in', (req, res) => {
  console.log(req.query)
  let tokenBody = ''
  const tokenRequest = https.request({
    hostname: `${domain}.auth.${region}.amazoncognito.com`,
    port: 443,
    path: '/oauth2/token',
    method: 'POST',
    headers: {
      "Authorization": `Basic ${authSecret}`,
      "Content-Type": "application/x-www-form-urlencoded"
    }
  }, (tokenRes) => {
    tokenRes.setEncoding("utf-8");
    tokenRes.on('data', (chunk) => {
      tokenBody += chunk
    })

    tokenRes.on('end', () => {
      console.log(tokenBody)
      res.sendStatus(tokenRes.statusCode)
    })
  })

  tokenRequest.on('error', (error) => {
    console.error(`problem with request: ${error.message}`)
    res.sendStatus(500)
  })

  const formData = `grant_type=authorization_code&redirect_uri=http://localhost:${port}/sign-in&code=${req.query.code}`
  tokenRequest.write(formData)
  tokenRequest.end()
})

app.listen(port, () => {
  console.log(`Listening at http://localhost:${port}`)
})

Start the listener.

# Set environment variables
# export port=9000
# ...
$ node index.js

Now sign in to the Hosted UI, and on success, the listener will log the request query parameters to the console and request the TOKEN endpoint. If this request is successful, the response is a JSON body with id_token, access_token, refresh_token, expires_in, and token_type set to Bearer.

{ "code": "70d0740d-ab1a-4527-b3e3-cdca79w4c093" }
{
  "id_token": "BOrLrMd",
  "access_token": "WqtQU9t",
  "refresh_token": "iOJiKV1",
  "expires_in": 3600,
  "token_type": "Bearer"
}

A successful response completes the sign-up and sign-in use case workflow.

Coming up next

The following posts will explore other use cases such as federating access to AWS resources, integrating with SAML, API Gateway Authorization, and AWS Single Sign-On (SSO).

Enjoyed this post? Follow this blog to never miss out on future posts!

Related Posts

⏳

Authentication and Authorization with AWS - API Gateway
Dec 29 2021

AWS Cognito User Pools and Federated Identities can be used to authorize API gateway requests.

⏳

Authentication and Authorization with AWS - Federated Access
Nov 21 2021

AWS Cognito Identity Pools provide authenticated users access to AWS resources.

⏳

Authentication and Authorization with AWS - Cognito SAML Integration
Nov 14 2021

AWS Cognito integrates with a corporate identity provider such as Active Directory (AD) using SAML.

⏳

Authentication and Authorization with AWS - About IAM
Sep 12 2021

Amazon Web Services (AWS) references a dizzying number of concepts, resources, patterns, and best practices to provide a fully managed…