AWS Cognito provides authentication, authorization, and user management for web and mobile apps and can be provisioned reproducibly with Terraform. Infrastructure as Code replaces console experimentation with version-controlled, reviewable Cognito configurations that can be deployed consistently across environments. The reference material covers the full stack from hosted UI OAuth flow to user pool schemas, app clients, Lambda triggers, domains, groups, and community Terraform modules.
Cognito Authentication Flow with Hosted UI
AWS Cognito is an authentication service that lets you add secure user sign-up, sign-in, and access control to your applications. The general flow of Cognito with the hosted UI starts when a user clicks Login on your app.
The browser redirects to https://
The Cognito Hosted UI prompts user for email/password and after login redirects to https://yourapp.com/callback?code=AUTH_CODE.
The browser receives the redirect and the frontend captures code and sends request to Cognito POST /oauth2/token with code, clientid, redirecturi.
The Cognito Token Endpoint returns ID Token with user info, Access Token for API access, and Refresh Token for session renewal.
This flow is the foundation for building a signup login site with Terraform including hosted UI, OAuth flow, and best practices.
Terraform Project Structure and Prerequisites
Setting up AWS Cognito with Terraform requires a comprehensive guide to configuring Amazon Cognito user authentication using Terraform Infrastructure as Code.
Prerequisites listed in reference material include:
- AWS CLI configured
- Terraform installed
- Basic understanding of authentication concepts
- Web or mobile application ready for integration
A typical project structure is:
- aws-cognito-terraform/
- ├── main.tf
- ├── variables.tf
- ├── outputs.tf
- └── terraform.tfvars
This layout separates provider configuration, resource definitions, inputs, and outputs for reproducible deployments.
Core Resources: User Pool, App Client, Identity Pool
Basic Cognito Configuration begins with the provider.
hcl
provider "aws" {
region = var.aws_region
}
User Pool resource defines the directory. A minimal production-ready example sets name, username attributes, auto verified attributes, password policy, verification message template, schema, and tags.
hcl
resource "aws_cognito_user_pool" "main" {
name = "${var.project_name}-user-pool"
username_attributes = ["email"]
auto_verified_attributes = ["email"]
password_policy {
minimum_length = 8
require_lowercase = true
require_numbers = true
require_symbols = true
require_uppercase = true
}
verification_message_template {
default_email_option = "CONFIRM_WITH_CODE"
email_subject = "Account Verification Code"
email_message = "Your verification code is {####}"
}
schema {
attribute_data_type = "String"
name = "email"
required = true
mutable = true
string_attribute_constraints {
min_length = 7
max_length = 256
}
}
tags = {
Environment = var.environment
}
}
App Client attaches to the user pool and controls auth flows.
hcl
resource "aws_cognito_user_pool_client" "main" {
name = "${var.project_name}-client"
user_pool_id = aws_cognito_user_pool.main.id
generate_secret = false
explicit_auth_flows = [
"ALLOW_USER_SRP_AUTH",
"ALLOW_REFRESH_TOKEN_AUTH"
]
}
Identity Pool ties Cognito to AWS resource access.
hcl
resource "aws_cognito_identity_pool" "main" {
identity_pool_name = "${var.project_name}-identity-pool"
allow_unauthenticated_identities = false
cognito_identity_providers
}
A simpler user pool example allows users to sign up with email and password with a single client for development.
hcl
resource "aws_cognito_user_pool" "garden_tour_user_pool" {
name = "garden_tour_user_pool"
username_attributes = ["email"]
auto_verified_attributes = ["email"]
password_policy {
minimum_length = 6
temporary_password_validity_days = 2
}
schema {
attribute_data_type = "String"
developer_only_attribute = false
mutable = true
name = "email"
required = true
string_attribute_constraints {
min_length = 1
max_length = 256
}
}
lambda_config {
custom_message = module.lambda.lambda_arn
}
}
hcl
resource "aws_cognito_user_pool_client" "garden_tour_client_development" {
name = "garden_tour_client_development"
user_pool_id = aws_cognito_user_pool.garden_tour_user_pool.id
generate_secret = false
refresh_token_validity = 90
prevent_user_existence_errors = "ENABLED"
explicit_auth_flows = [
"ALLOW_REFRESH_TOKEN_AUTH",
"ALLOW_USER_PASSWORD_AUTH",
]
}
Module-Based Approach: lgallard and terraformita
Terraform modules provide a comprehensive solution for implementing AWS Cognito authentication in your applications.
The lgallard/cognito-user-pool module creates Amazon Cognito User Pools, configure its attributes and resources such as app clients, domain, resource servers. Amazon Cognito User Pools provide a secure user directory that scales to hundreds of millions of users. As a fully managed service, User Pools are easy to set up without any worries about standing up server infrastructure.
You can use this module to create a Cognito User Pool using default values or use detailed definition to set every aspect of the Cognito User Pool.
Check the examples where you can see simple example using default values, simpleextended version which adds app clients, domain, resource servers resources, complete version with detailed example, or withbranding example that demonstrates managed login branding capabilities.
Simple example:
hcl
module "aws_cognito_user_pool_simple" {
source = "lgallard/cognito-user-pool/aws"
user_pool_name = "mypool"
ignore_schema_changes = true
tags = {
Owner = "infra"
Environment = "production"
Terraform = true
}
}
Configuration options include Cognito user pool log delivery for notification errors and threat-protection user activity logs. Notification logs use userNotification with ERROR and CloudWatch Logs.
The terraformita/terraform-aws-cognito module provides comprehensive solution for implementing AWS Cognito authentication.
Lambda Triggers and Permissions
This blog shows terraform configuration you need to let cognito invoke lambda triggers with Terraform.
The essential resource needed is the user pool and client with explicit auth flows. Lambda permission must allow Cognito to invoke the function.
hcl
resource "aws_lambda_permission" "allow_cognito_invoke_trigger" {
statement_id = "AllowExecutionFromCognito"
action = "lambda:InvokeFunction"
function_name = module.lambda.lambda_function_name
principal = "cognito-idp.amazonaws.com"
source_arn = aws_cognito_user_pool.garden_tour_user_pool.arn
}
Lambda config can be attached to user pool.
hcl
lambda_config {
custom_message = module.lambda.lambda_arn
}
Configuration Patterns and Best Practices
Setting up Cognito through AWS console is fine for experimentation, but for production workloads you want infrastructure as code. Terraform gives you reproducible, version-controlled Cognito configurations that you can review, test, and deploy consistently across environments.
Let's build a complete Cognito setup with Terraform - user pool, app client, groups, Lambda triggers, domain, and all the supporting resources.
Basic User Pool starts with user pool itself, then app client, then identity pool, domain, resource servers, and groups.
Password policy choices differ between examples: minimumlength 8 with requirelowercase, requirenumbers, requiresymbols, requireuppercase versus minimumlength 6 with temporarypasswordvalidity_days 2.
Explicit auth flows commonly used:
- ALLOWUSERSRP_AUTH
- ALLOWREFRESHTOKEN_AUTH
- ALLOWUSERPASSWORD_AUTH
Client settings often set generatesecret = false for public clients and refreshtoken_validity in days.
Common Configuration Examples
| Resource | Example Name | Key Attributes |
|---|---|---|
| awscognitouser_pool | gardentouruser_pool | usernameattributes = ["email"], autoverifiedattributes = ["email"], passwordpolicy minimum_length = 6 |
| awscognitouser_pool | main | usernameattributes = ["email"], autoverifiedattributes = ["email"], passwordpolicy minimum_length = 8 with symbol/upper/lower/number requirements |
| awscognitouserpoolclient | gardentourclient_development | generatesecret = false, refreshtokenvalidity = 90, preventuserexistenceerrors = "ENABLED" |
| awscognitouserpoolclient | main | generatesecret = false, explicitauthflows ALLOWUSERSRPAUTH, ALLOWREFRESHTOKEN_AUTH |
| awscognitoidentity_pool | main | allowunauthenticatedidentities = false |
| Module | Source | Purpose |
|---|---|---|
| lgallard/cognito-user-pool/aws | lgallard | User pool, app clients, domain, resource servers |
| terraformita/terraform-aws-cognito | terraformita | Comprehensive Cognito authentication solution |
Conclusion
Terraform enables declarative, auditable AWS Cognito deployments that match production requirements for security, observability, and repeatability. User pool definition establishes identity schema, verification and password policy, and attribute constraints. App client configuration governs OAuth flows, token lifetimes, and secret handling. Identity pool integration bridges authentication to AWS authorization. Lambda triggers and permissions extend user lifecycle with custom messaging and validation. Module-based approaches reduce boilerplate while preserving granular control over schema, branding, domain, and resource servers. Combining hosted UI redirect flow knowledge with Terraform resource definitions produces end-to-end signup login sites that are infrastructure as code ready, reviewable, and consistent across environments.