Mapping of AWS Cognito options to Terraform
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 = trueallowed_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 ;)