Skip to content

Cognito App Client Module

This module creates and configures an AWS Cognito User Pool App Client with OAuth 2.0/OIDC support, automatic credential storage in SSM Parameter Store, and optional UI customization.

Client Types

This module supports two types of Cognito app clients:

  • Confidential clients (default): Used for server-side applications that can securely store client secrets. These clients have generate_secret = true.
  • Public clients: Used for Single Page Applications (SPAs), mobile apps, and other public clients that cannot securely store secrets. These clients have generate_secret = false.

Public clients should use the Authorization Code flow with PKCE (Proof Key for Code Exchange) for secure authentication without a client secret.

Features

  • OAuth 2.0/OIDC app client with configurable flows and scopes
  • Automatic storage of client credentials in AWS SSM Parameter Store
  • Token validity configuration (access, ID, and refresh tokens)
  • Support for multiple identity providers (Cognito, Entra, Google)
  • UI customization with custom logo support (legacy hosted UI)
  • Managed Login branding for modern login pages (requires ESSENTIALS or PLUS tier)

Usage

Basic Example

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

  client_id_ssm_parameter     = "/myapp/cognito/client_id"
  client_secret_ssm_parameter = "/myapp/cognito/client_secret"

  callback_urls                = ["https://app.example.com/oauth/openid/callback"]
  explicit_auth_flows          = ["ALLOW_REFRESH_TOKEN_AUTH"]
  allowed_oauth_flows          = ["code"]
  allowed_oauth_scopes         = ["openid", "email", "profile"]
  supported_identity_providers = ["COGNITO"]
}

SPA/Public Client Example

Use this configuration for Single Page Applications that cannot securely store client secrets:

module "cognito_spa" {
  source = "./modules/cognito_app"

  create               = true
  client_app_name      = "my-spa-app"
  cognito_user_pool_id = module.cognito_pool.aws_cognito_pool_id
  generate_secret      = false  # No secret for SPA clients
  client_id_ssm_parameter = "/myspa/cognito/client_id"
  # Note: client_secret_ssm_parameter is not needed for public clients

  callback_urls = [
    "https://app.example.com/callback",
    "http://localhost:3000/callback"  # For local development
  ]

  # SPA-appropriate auth flows
  explicit_auth_flows          = ["ALLOW_USER_SRP_AUTH", "ALLOW_REFRESH_TOKEN_AUTH"]
  allowed_oauth_flows          = ["code"]  # Authorization code with PKCE
  allowed_oauth_scopes         = ["openid", "email", "profile"]
  supported_identity_providers = ["COGNITO"]
}

Recommended SPA Configuration:

Setting Recommendation Reason
generate_secret false SPAs cannot securely store secrets
allowed_oauth_flows ["code"] Authorization code flow with PKCE is the most secure option for SPAs
explicit_auth_flows ["ALLOW_USER_SRP_AUTH", "ALLOW_REFRESH_TOKEN_AUTH"] SRP for sign-in, refresh tokens for session management
callback_urls Include HTTPS production URLs and localhost for development SPAs often run locally during development

With Multiple Identity Providers

module "cognito_app" {
  source = "./modules/cognito_app"

  create               = true
  client_app_name      = "enterprise-app"
  cognito_user_pool_id = module.cognito_pool.aws_cognito_pool_id

  client_id_ssm_parameter     = "/myapp/cognito/client_id"
  client_secret_ssm_parameter = "/myapp/cognito/client_secret"

  callback_urls = [
    "https://app.example.com/oauth/openid/callback",
    "http://localhost:8000/callback"  # For local development
  ]

  explicit_auth_flows          = ["ALLOW_REFRESH_TOKEN_AUTH"]
  allowed_oauth_flows          = ["code"]
  allowed_oauth_scopes         = ["openid", "email", "profile"]
  supported_identity_providers = ["COGNITO", "Google", "Entra"]
}

With Managed Login Branding (Default Theme)

module "cognito_app" {
  source = "./modules/cognito_app"

  create               = true
  client_app_name      = "branded-app"
  cognito_user_pool_id = module.cognito_pool.aws_cognito_pool_id

  client_id_ssm_parameter     = "/myapp/cognito/client_id"
  client_secret_ssm_parameter = "/myapp/cognito/client_secret"

  callback_urls                = ["https://app.example.com/oauth/openid/callback"]
  explicit_auth_flows          = ["ALLOW_REFRESH_TOKEN_AUTH"]
  allowed_oauth_flows          = ["code"]
  allowed_oauth_scopes         = ["openid", "email", "profile"]
  supported_identity_providers = ["COGNITO"]

  # Use Cognito's default branding
  managed_login_branding = {
    use_defaults = true
  }
}
locals {
  branding_settings = {
    categories = {
      global = {
        colorSchemeMode = "DYNAMIC"  # Supports light/dark mode
      }
    }
    components = {
      form = {
        logo = {
          enabled       = true
          formInclusion = "IN"
          location      = "CENTER"
          position      = "TOP"
        }
      }
      primaryButton = {
        lightMode = {
          defaults = {
            backgroundColor = "4f069aff"  # Purple
            textColor       = "ffffffff"  # White
          }
          hover = {
            backgroundColor = "3d0578ff"
            textColor       = "ffffffff"
          }
        }
        darkMode = {
          defaults = {
            backgroundColor = "7b2fc9ff"
            textColor       = "ffffffff"
          }
          hover = {
            backgroundColor = "9b4fe9ff"
            textColor       = "ffffffff"
          }
        }
      }
    }
  }
}

module "cognito_app" {
  source = "./modules/cognito_app"

  create               = true
  client_app_name      = "custom-branded-app"
  cognito_user_pool_id = module.cognito_pool.aws_cognito_pool_id

  client_id_ssm_parameter     = "/myapp/cognito/client_id"
  client_secret_ssm_parameter = "/myapp/cognito/client_secret"

  callback_urls                = ["https://app.example.com/oauth/openid/callback"]
  explicit_auth_flows          = ["ALLOW_REFRESH_TOKEN_AUTH"]
  allowed_oauth_flows          = ["code"]
  allowed_oauth_scopes         = ["openid", "email", "profile"]
  supported_identity_providers = ["COGNITO", "Google", "Entra"]

  managed_login_branding = {
    use_defaults = false
    settings     = jsonencode(local.branding_settings)
    assets = [
      {
        bytes      = filebase64("${path.module}/assets/logo_for_white.png")
        category   = "FORM_LOGO"
        color_mode = "LIGHT"
        extension  = "PNG"
      },
      {
        bytes      = filebase64("${path.module}/assets/logo_for_dark.png")
        category   = "FORM_LOGO"
        color_mode = "DARK"
        extension  = "PNG"
      },
      {
        bytes      = filebase64("${path.module}/assets/background_for_light.png")
        category   = "PAGE_BACKGROUND"
        color_mode = "LIGHT"
        extension  = "PNG"
      }
    ]
  }
}

Token Validity

The module configures the following default token validity periods:

Token Type Validity Unit
Access Token 2 hours
ID Token 2 hours
Refresh Token 30 days

SSM Parameters

Client credentials are automatically stored in SSM Parameter Store:

Parameter Path Description
var.client_id_ssm_parameter App client ID
var.client_secret_ssm_parameter App client secret (only created when generate_secret = true)

UI Customization with Managed Login Branding

For the modern managed login experience (requires ESSENTIALS or PLUS user pool tier):

  • use_defaults: Use Cognito's default branding (mutually exclusive with settings)
  • settings: Custom JSON settings for branding configuration
  • assets: List of custom assets (logos, backgrounds) with base64-encoded content

Asset Categories

Category Description
FORM_LOGO Logo displayed on the login form
PAGE_BACKGROUND Background image for the login page

Color Modes

Mode Description
LIGHT Asset used when light mode is active
DARK Asset used when dark mode is active

Supported Extensions

Extension Format
PNG PNG
JPEG JPEG
SVG SVG

Inputs

Name Description Type Default Required
allowed_oauth_flows allowed oauth scopes: code, implicit, and client_credentials list(string) n/a yes
allowed_oauth_scopes allowed oauth scopes: code, implicit, and client_credentials list(string) n/a yes
callback_urls List of callback URLs for the Cognito App Client list(string) n/a yes
client_app_name Name of the Cognito App Client string n/a yes
client_id_ssm_parameter SSM parameter path to store the Cognito App Client ID string n/a yes
client_secret_ssm_parameter SSM parameter path to store the Cognito App Client secret. Only used when generate_secret is true. string null no
cognito_user_pool_id ID of the Cognito User Pool to which this App Client belongs string n/a yes
create Whether to create the Cognito App Client bool n/a yes
explicit_auth_flows List of explicit authentication flows for the Cognito App Client list(string) n/a yes
generate_secret Whether to generate a client secret. Set to false for SPA/public clients that cannot securely store secrets. bool true no
managed_login_branding Managed login page branding configuration. Requires ESSENTIALS or PLUS user pool tier.
object({
use_defaults = optional(bool, false)
settings = optional(string, null)
assets = optional(list(object({
bytes = string
category = string
color_mode = string
extension = string
})), [])
})
null no
supported_identity_providers List of supported identity providers for the Cognito App Client list(string) n/a yes

Outputs

Name Description
client_id OPENID client
client_secret OPENID secret (empty string if generate_secret is false)