DEV Community

Cover image for AWS Amplify + Amazon Cognito + AWS CDK: A Complete Setup Guide
Anne for AWS Community Builders

Posted on

AWS Amplify + Amazon Cognito + AWS CDK: A Complete Setup Guide

Setting up AWS Amplify with Amazon Cognito using CDK is mostly straightforward. The tricky parts?

  • GitHub integration (PAT → GitHub App migration)
  • Cognito email configuration with SES
  • Automating login page branding (which isn’t supported in CDK yet)

This article walks you through the full setup with the important details without unnecessary boilerplate.

Amplify App with CDK

You can create your Amplify app in CDK using Level 1 Cloudformation constructs. That part is pretty simple if you know CDK. However, the GitHub integration still requires a Personal Access Token (PAT) for the initial setup in CDK. If you go to the Amplify console after your deployment, it will immediately suggest you to migrate to GitHub App authentication. This can be done easily following the steps in the console. From now on you can revoke the PAT and replace it with a random string in your CDK code (at least 1 char length).

Cognito User Pool (Email as Login)

Here’s a clean CDK example:

new cognito.UserPool(this, 'MyUserPool', {
  signInAliases: { email: true },
  autoVerify: { email: true },
  standardAttributes: {
    email: { required: true, mutable: true },
    givenName: { required: false, mutable: true },
    familyName: { required: false, mutable: true },
  },
  userInvitation: {
    emailSubject: 'Access to My App',
    emailBody: "Hello,<br>Your username: {username}<br>Password: {####}",
  },
  userVerification: {
    emailSubject: 'Verification Code',
    emailBody: 'Your verification code: {####}',
  },
  accountRecovery: cognito.AccountRecovery.EMAIL_ONLY,
});
Enter fullscreen mode Exit fullscreen mode

A few notes to the user pool:

  • signInAliases set to email will allow your users to login via email instead of using a dedicated username. Also in the email templates the username will be rendered as the user's email in this case
  • The email templates are for inviting new users as well as password reset. Especially if your users don't speak English it can be very useful to replace the standard template. The templates also support basic HTML (e.g., for line breaks).
  • Custom attributes are also possible to define, however, keep in mind that they are not searchable in Cognito.

Custom Email Sender with SES

To send invitation and password recovery emails from your own domain, you need to configure Amazon SES:

new ses.EmailIdentity(this, 'Identity', {
  identity: ses.Identity.email('my@email.com'),
});
Enter fullscreen mode Exit fullscreen mode

Please make sure, that SES in your account is out of sandbox mode, your identity is successfully verified and don't forget to grant permissions to send emails to the user pool:

emailIdentity.grant(
  new ArnPrincipal(myUserPool.userPoolArn),
  'ses:SendEmail'
);
Enter fullscreen mode Exit fullscreen mode

User Pool Client for Nuxt

Your frontend needs a client:

new cognito.UserPoolClient(this, 'Client', {
  userPool,
  generateSecret: true,
  preventUserExistenceErrors: true,
  supportedIdentityProviders: [
    cognito.UserPoolClientIdentityProvider.COGNITO,
  ],
  oAuth: {
    callbackUrls: ['https://myapp.com/auth/callback'],
    logoutUrls: ['https://myapp.com'],
    scopes: [
      cognito.OAuthScope.OPENID,
      cognito.OAuthScope.PROFILE,
    ],
    flows: {
      authorizationCodeGrant: true,
      implicitCodeGrant: true,
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

Key settings:

  • generateSecret: true (needed for SSR (e.g., Nuxt))
  • authorizationCodeGrant (recommended secure flow)
  • preventUserExistenceErrors (avoids user enumeration leaks)

Nuxt OAuth Configuration

In your nuxt.config.ts you have to add the oauth configuration for using Cognito:

oauth: {
  cognito: {
    clientId: COGNITO_CLIENT_ID,
    clientSecret: COGNITO_CLIENT_SECRET,
    region: COGNITO_REGION,
    userPoolId: COGNITO_USER_POOL_ID,
    redirectURL: COGNITO_REDIRECT_URL,
    authorizationParams: {
      lang: 'en'
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

In here you can define a language parameter so that your users will see the login page in their native language. Currently supported language can be found in the AWS docs.

Custom Domain

In order to use your own domain instead of a default AWS cognito domain you can add one to your user pool like this:

myUserPool.addDomain('Domain', {
  customDomain: {
    domainName: 'auth.myapp.com',
    certificate: props.certificate,
  },
  managedLoginVersion: cognito.ManagedLoginVersion.NEWER_MANAGED_LOGIN,
});
Enter fullscreen mode Exit fullscreen mode

The certificate in this case was created in another stack using the AWS certificate manager. Also, I am using the new AWS Managed Login (not the Hosted UI).

Automating the Styling of the Cognito New Managed Login

AWS provides a nice UI in the console to style the new managed login (logo, favicon, colors in dark and bright mode etc.), however, this can't be managed through CDK (yet?). But here's a workaround:

  1. Style your managed login in the AWS console
  2. Export the configuration with the AWS CLI and save the output into a JSON file.
aws cognito-idp describe-managed-login-branding \
  --user-pool-id YOUR_USER_POOL_ID \
  --managed-login-branding-id YOUR_BRANDING_ID
Enter fullscreen mode Exit fullscreen mode
  1. Apply the styling e.g. in your CI/CD pipeline after the deployment like this
aws cognito-idp update-managed-login-branding \
  --user-pool-id $USER_POOL_ID \
  --managed-login-branding-id $MANAGED_LOGIN_BRANDING_ID \
  --settings file://login-settings.json
Enter fullscreen mode Exit fullscreen mode

Conclusion

Setting up Cognito with CDK can require a bit of fumbling around with the configurations. However, once set up Cognito is a strong reliable way to authenticate your users for your Amplify hosted app.

Top comments (0)