Mapping of AWS Cognito options to Terraform

Chandan Singh
5 min readAug 7, 2021

I wanted to move the AWS Cognito setup to Terraform however, I couldn’t find any tutorial or instructions on how to do so with Cognito settings mapping to Terraform’s aws module.

You can find below the settings of AWS Cognito mapped to Terraform modules.

Note: you can find the terraform code at: https://github.com/chandan-singh/terraform-aws-cognito

General settings

Policies

maps to

# Terraform 1.0.3 & aws 3.xresource "aws_cognito_user_pool" "pool" {
...
password_policy {
minimum_length = 8
require_numbers = true
require_symbols = false
require_lowercase = true
require_uppercase = true
temporary_password_validity_days = 7
}

admin_create_user_config {
allow_admin_create_user_only = false
}
...
}

MFA and verifications

maps to

# Terraform 1.0.3 & aws 3.xmfa_configuration = "OFF"account_recovery_setting {
recovery_mechanism {
name = "verified_email"
priority = 1
}
# recovery_mechanism {
# name = "verified_phone_number"
# priority = 2
# }
}
auto_verified_attributes = ["email"]# sms_configuration {
# external_id = "..."
# sns_caller_arn = "..."
# }

Advanced security

maps to

user_pool_add_ons {
advanced_security_mode = "OFF" # "AUDIT", "ENFORCED"
}

Message customizations

maps to

email_configuration {
# source_arn = "<SES ARN>"
# from_email_address = "chandan s <chandans@example.com>"
# reply_to_email_address = "contact@example.com"
email_sending_account = "COGNITO_DEFAULT" # "DEVELOPER" for SES account
...
}

maps to

verification_message_template {
default_email_option = "CONFIRM_WITH_CODE" # "CONFIRM_WITH_LINK"
# email_message = ""
# email_message_by_link = ""
# email_subject = ""
# email_subject_by_link = ""
# sms_message = ""
}

Tags

maps to

tags {
# Environment = "production"
}

Devices

maps to

#   device_configuration {
# challenge_required_on_new_device = false
# device_only_remembered_on_user_prompt = true # false equates to "Always" remember, true is "User Opt In," and not using a device_configuration block is "No."
# }

App Clients

Adding a new App Client

If you need more details on parameters, please look at:

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_client

You can find the mapping below.

maps to

resource "aws_cognito_user_pool_client" "app_client" {
name = "<client_name>"
user_pool_id = aws_cognito_user_pool.pool.id token_validity_units {
refresh_token = "days" # "seconds", "minutes", "hours", "days"
access_token = "minutes" # "seconds", "hours", "days"
id_token = "hours" # "seconds", "minutes", "days"
}
refresh_token_validity = 30 # 30 days
access_token_validity = 60 # 60 minutes
id_token_validity = 1 # 1 hour
generate_secret = true
...
}

maps to

resource "aws_cognito_user_pool_client" "app_client" {
...
prevent_user_existence_errors = "ENABLED" # "LEGACY", "ENABLED"explicit_auth_flows = ["ALLOW_CUSTOM_AUTH", "ALLOW_USER_SRP_AUTH", "ALLOW_REFRESH_TOKEN_AUTH"]

# "ALLOW_ADMIN_USER_PASSWORD_AUTH", "ALLOW_CUSTOM_AUTH", "ALLOW_USER_PASSWORD_AUTH", "ALLOW_USER_SRP_AUTH", "ALLOW_REFRESH_TOKEN_AUTH"

enable_token_revocation = true
}

maps to

allowed_oauth_scopes = ["email", "phone", "openid", "profile", "aws.cognito.signin.user.admin"]resource "aws_cognito_user_pool_client" "app_client" {
...
read_attributes = ["address", "birthdate", "email", "email_verified", "family_name", "gender", "given_name", "locale", "middle_name", "name", "nickname", "phone_number", "phone_number_verified", "picture", "preferred_username", "profile", "updated_at", "website", "zoneinfo"] write_attributes = ["address", "birthdate", "email", "family_name", "gender", "given_name", "locale", "middle_name", "name", "nickname", "phone_number", "picture", "preferred_username", "profile", "updated_at", "website", "zoneinfo"]...
}

App Client Settings

maps to

supported_identity_providers = ["COGNITO"] # "COGNITO", "Facebook", "SignInWithApple", "Google", "LoginWithAmazon"callback_urls = ["https://example.com/"]default_redirect_uri = "https://example.com/" # URL must be one of the URL in callback_urlslogout_urls   = ["https://example.com/logout"]# OAuth 2.0
allowed_oauth_flows_user_pool_client = true
allowed_oauth_flows = ["code", "implicit"] # "code", "implicit", "client_credentials"]allowed_oauth_scopes = ["email", "profile"] # "phone", "email", "openid", "profile", "aws.cognito.signin.user.admin"

Domain name

maps to

resource "aws_cognito_user_pool_domain" "main" {
domain = "<example-domain>"
user_pool_id = aws_cognito_user_pool.user_pool.id
}

maps to

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.pool.id
}

resource "aws_cognito_user_pool" "pool" {
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"
}
}

UI Customization

maps to

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

resource "aws_cognito_user_pool_domain" "example" {
domain = "example"
user_pool_id = aws_cognito_user_pool.pool.id
}

resource "aws_cognito_user_pool_ui_customization" "example" {
css = ".label-customizable {font-weight: 400;}"
image_file = filebase64("logo.png")

# Refer to the aws_cognito_user_pool_domain resource's
# user_pool_id attribute to ensure it is in an 'Active' state
user_pool_id = aws_cognito_user_pool_domain.example.user_pool_id
}

Federation

Identity Providers and attribute mapping

maps to

resource "aws_cognito_user_pool" "pool" {
name = "example-pool"
auto_verified_attributes = ["email"]
}

resource "aws_cognito_identity_provider" "example_provider" {
user_pool_id = aws_cognito_user_pool.pool.id
provider_name = "Google"
provider_type = "Google"

provider_details = {
client_id = "your client_id"
client_secret = "your client_secret"
authorize_scopes = "email"
}

attribute_mapping = {
email = "email"
username = "sub"
}
}

If you found it useful, don’t forget to give a few claps ;)

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response