AWS Cognito Terraform Deep Dive: Infrastructure as Code for Authentication

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://.auth..amazoncognito.com/login with responsetype=code, clientid and redirect_uri.

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.

Sources

  1. towardsaws.com
  2. thecloudpanda.com
  3. github.com
  4. github.com
  5. fallenstedt.com
  6. oneuptime.com

Related Posts