Cognito User Pool Module
This module creates and configures an AWS Cognito User Pool with support for external identity providers (Entra ID, Google), custom domains, MFA, and customizable email templates.
Features
- Cognito User Pool with admin-only user creation
- Multi-factor authentication (MFA) support with software tokens
- External identity provider integration:
- Microsoft Entra ID (Azure AD) via OIDC
- Google OAuth
- Pre-token generation Lambda for external IDP group passthrough
- Custom domain support with Route53 DNS management
- Customizable email templates for invitations and verification
- Account recovery via email and phone
Usage
Basic Example
module "cognito_pool" {
source = "./modules/cognito_pool"
create = true
cognito_pool_name = "my-app-federated"
}
With MFA Enabled
module "cognito_pool" {
source = "./modules/cognito_pool"
create = true
cognito_pool_name = "secure-user-pool"
mfa_configuration = "ON" # Required for all users
}
With Entra ID (Azure AD) Integration
module "cognito_pool" {
source = "./modules/cognito_pool"
create = true
cognito_pool_name = "enterprise-federated"
entra_provider = {
client_id = "c7ab4d19-581b-4c69-b09b-2f066b7281d2"
tenant_id = "e184a7ee-f2d8-48a3-9f0b-388319478763"
# client_secret_parameter defaults to "/cognito/external/idp/entra/CLIENT_SECRET"
}
}
With Google Integration
module "cognito_pool" {
source = "./modules/cognito_pool"
create = true
cognito_pool_name = "consumer-federated"
google_provider = {
client_id = "660314451535-e75j9m339mjmb8u37402v6oabvbuaouk.apps.googleusercontent.com"
# client_secret_parameter defaults to "/cognito/external/idp/google/CLIENT_SECRET"
}
}
With Custom Domain
module "cognito_pool" {
source = "./modules/cognito_pool"
create = true
cognito_pool_name = "branded-user-pool"
custom_domain = {
domain = "auth.example.com"
certificate_arn = data.terraform_remote_state.acm_global.outputs.acm_certificate_arn
hosted_zone_name = "example.com" # or use hosted_zone_id directly
}
}
With Custom Email Templates
module "cognito_pool" {
source = "./modules/cognito_pool"
create = true
cognito_pool_name = "my-app-federated"
invite_message_template = {
email_subject = "MyApp – Your Account Has Been Created"
email_message = <<-HTML
<html>
<body>
<h2>Welcome to MyApp</h2>
<p>Your credentials:</p>
<ul>
<li>Username: {username}</li>
<li>Temporary password: {####}</li>
</ul>
<p>Sign in at <a href="https://app.example.com">https://app.example.com</a></p>
</body>
</html>
HTML
sms_message = "Your MyApp username is {username} and temporary password is {####}"
}
verification_message_template = {
email_subject = "MyApp – Verify Your Email"
email_message = <<-HTML
<html>
<body>
<h2>MyApp</h2>
<p>Your verification code: {####}</p>
</body>
</html>
HTML
}
}
Full Production Example
module "cognito_pool" {
source = "./modules/cognito_pool"
create = true
cognito_pool_name = "production-federated"
mfa_configuration = "ON"
# Multiple identity providers
entra_provider = {
client_id = "c7ab4d19-581b-4c69-b09b-2f066b7281d2"
tenant_id = "e184a7ee-f2d8-48a3-9f0b-388319478763"
}
google_provider = {
client_id = "660314451535-e75j9m339mjmb8u37402v6oabvbuaouk.apps.googleusercontent.com"
}
# Custom branded domain
custom_domain = {
domain = "auth.app.example.com"
certificate_arn = data.terraform_remote_state.acm_global.outputs.acm_certificate_arn
hosted_zone_name = "app.example.com"
}
# Custom email templates (optional - defaults use cognito_pool_name)
invite_message_template = {
email_subject = "MyApp – Your Account Has Been Created"
email_message = <<-HTML
<html>
<body>
<h2>Welcome to MyApp</h2>
<p>Username: {username}</p>
<p>Temporary password: {####}</p>
<p>Sign in at <a href="https://app.example.com">https://app.example.com</a></p>
</body>
</html>
HTML
sms_message = "Your MyApp username is {username} and temporary password is {####}"
}
verification_message_template = {
email_subject = "MyApp – Verify Your Email"
email_message = <<-HTML
<html>
<body>
<h2>MyApp</h2>
<p>Your verification code: {####}</p>
</body>
</html>
HTML
}
}
# App client with all identity providers
module "cognito_app" {
source = "./modules/cognito_app"
create = true
client_app_name = "my-web-app"
cognito_user_pool_id = module.cognito_pool.aws_cognito_pool_id
callback_urls = [
"https://app.example.com/oauth/openid/callback",
"http://localhost:8000/callback"
]
explicit_auth_flows = ["ALLOW_REFRESH_TOKEN_AUTH"]
allowed_oauth_flows = ["code"]
allowed_oauth_scopes = ["openid", "email", "profile"]
supported_identity_providers = concat(["COGNITO"], module.cognito_pool.identity_provider_names)
}
Identity Provider Configuration
Microsoft Entra ID (Azure AD)
The module automatically configures:
- OIDC issuer URL derived from tenant ID
- Standard scopes: openid profile email
- Attribute mapping for email, name, username, and groups
- Custom entra_groups attribute for group passthrough
Prerequisites:
1. Store the Entra client secret in SSM Parameter Store (default: /cognito/external/idp/entra/CLIENT_SECRET)
2. Configure your Entra app registration with the Cognito callback URL: https://<cognito-domain>/oauth2/idpresponse
Entra App Registration Settings:
- Redirect URI: https://auth.example.com/oauth2/idpresponse
- Token configuration: Add groups claim to ID token
The module automatically configures:
- Google OAuth provider
- Standard scopes: email profile openid
- Attribute mapping for email, name, given_name, family_name, picture, and username
Prerequisites:
1. Store the Google client secret in SSM Parameter Store (default: /cognito/external/idp/google/CLIENT_SECRET)
2. Configure your Google OAuth consent screen and credentials
3. Add authorized redirect URI: https://<cognito-domain>/oauth2/idpresponse
Pre-Token Generation Lambda
When external identity providers are configured, the module automatically deploys a Lambda function that:
- Intercepts the pre-token generation event (V3_0)
- Extracts group claims from external IDPs (Entra groups via custom:entra_groups)
- Passes through external groups to the cognito:groups claim
- Merges external groups with any existing Cognito groups
This allows your application to use external IDP groups for access control without manually syncing groups to Cognito.
MFA Configuration
| Value | Description |
|---|---|
OFF |
MFA disabled (default) |
OPTIONAL |
Users can enable MFA in their account settings |
ON |
MFA required for all users |
When MFA is enabled (OPTIONAL or ON), software token (TOTP) authentication is automatically configured.
Custom Domain Requirements
- ACM certificate must be in
us-east-1region (CloudFront requirement) - Either
hosted_zone_idorhosted_zone_namemust be provided - The module creates the Route53 A record automatically pointing to CloudFront
- Uses Managed Login Version 2 for modern login experience
Outputs
The module provides several outputs for integration with the cognito_app module:
| Output | Description |
|---|---|
aws_cognito_pool_id |
User pool ID for app client configuration |
aws_cognito_pool_arn |
User pool ARN for IAM policies |
aws_cognito_domain |
Cognito domain for OAuth endpoints |
identity_provider_names |
List of configured IDP names for supported_identity_providers |
domain_cloudfront_distribution |
CloudFront endpoint for custom domain DNS |
pre_token_lambda_arn |
ARN of the pre-token Lambda (if created) |
Modules
| Name | Source | Version |
|---|---|---|
| pre_token_lambda | terraform-aws-modules/lambda/aws | ~> 7.0 |
Inputs
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| attribute_mapping | Attribute mapping of IDP attributes to Cognito Pool attributes | map(string) |
{} |
no |
| cognito_pool_name | Cognito pool name | string |
n/a | yes |
| create | Whether to create the Cognito user pool | bool |
n/a | yes |
| custom_domain | Custom domain for Cognito hosted UI. Requires an ACM certificate in us-east-1. | object({ |
null |
no |
| entra_provider | Entra (Azure AD) OIDC identity provider configuration. All Microsoft endpoints are derived from tenant_id. | object({ |
null |
no |
| google_provider | Google identity provider configuration | object({ |
null |
no |
| invite_message_template | Custom invite message template for new users. If not provided, a minimal default using cognito_pool_name is used. | object({ |
null |
no |
| mfa_configuration | MFA configuration for Cognito-native users: OFF (disabled), OPTIONAL (user can enable), or ON (required for all users) | string |
"OFF" |
no |
| verification_message_template | Custom verification message template. If not provided, a minimal default using cognito_pool_name is used. | object({ |
null |
no |
Outputs
| Name | Description |
|---|---|
| aws_cognito_domain | Cognito domain, add as authorized JS origins and as authorized redirect url to IDP followed by /oauth2/idpresponse |
| aws_cognito_pool_arn | Cognito user pool arn |
| aws_cognito_pool_id | Cognito user pool id |
| domain_cloudfront_distribution | CloudFront distribution endpoint for custom domain DNS setup (CNAME target) |
| domain_cloudfront_distribution_zone_id | CloudFront distribution hosted zone ID for custom domain DNS setup (Route53 alias) |
| identity_provider_names | List of configured identity provider names for use in cognito_app supported_identity_providers |
| pre_token_lambda_arn | ARN of the pre-token generation Lambda function (empty if not created) |