Creating Custom AWS Cognito Domain

One of the things I’ve been working on lately is creating a custom AWS Cognito Domain for use with Cognito login portal. To add a cherry on top, I’m tasked to do this using Terraform.

One of the error messages I kept bumping into is one that looks like this:

Custom domain is not a valid subdomain: Was not able to resolve the root domain, please ensure an A record exists for the root domain. (Service: AWSCognitoIdentityProviderService; Status Code: 400; Error Code: InvalidParameterException; Request ID: xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx; Proxy: null)

What does the error mean?

Cognito is designed to be an extension to your web application. Its job is to handle user registration and sign on. When a custom domain is created for this purpose, it is expected that you have an existing website to use it with.

Typically, websites have a URL like this: my-website.com

As a best practice, Amazon recommends using the “auth” subdomain with Cognito: auth.my-website.com.

So in order for us to register auth.my-website.com for use, it requires a Route53 A record for my-website.com. The A stands for “Alias” in DNS terms.

Great, but where would this alias point to? Your S3 bucket, CloudFront distribution, or web server! This alias record must exist in Route53 before the custom (sub)domain can be created.

How would creating custom domain look like using AWS Console?

An example of creating a custom domain for AWS Cognito using AWS Console

What About Terraform?

I’m glad you asked. Lucky for us, Terraform has provided us with a great example in its documentation for how this is done. To save you time, here’s the code snippet.

resource "aws_cognito_user_pool_domain" "main" {
  domain          = "example-domain.example.com"
  certificate_arn = aws_acm_certificate.cert.arn
  user_pool_id    = aws_cognito_user_pool.example.id
}

resource "aws_cognito_user_pool" "example" {
  name = "example-pool"
}

data "aws_route53_zone" "example" {
  name = "example.com"
}

resource "aws_route53_record" "auth-cognito-A" {
  name    = aws_cognito_user_pool_domain.main.domain
  type    = "A"
  zone_id = data.aws_route53_zone.example.zone_id
  alias {
    evaluate_target_health = false
    name                   = aws_cognito_user_pool_domain.main.cloudfront_distribution_arn
    # This zone_id is fixed
    zone_id = "Z2FDTNDATAQYW2"
  }
}

The result of generating the custom domain with Cognito is that it returns a CloudFront Distribution ARN which will be the target for our Route53 A Record for the custom domain. The Zone ID is fixed and is one provided by AWS.

Very neat! I hope this post has helped you. Until next time.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s