AWS Cognito + ALB Auth Portal

A minimal employee access portal using AWS ALB for OAuth2 authentication and FastAPI for group-based authorization.

https://github.com/davidbmar/2026-jan-vibecodeportal-aws-cognito-alb-auth-portal  ·  public  ·  shipped

What it is

This project is a reference implementation of an 'Employee Access Portal' deployed on AWS. It leverages the Application Load Balancer (ALB) to handle the heavy lifting of OpenID Connect (OIDC) authentication with AWS Cognito, passing user identity via HTTP headers to a backend FastAPI application running on EC2. The application enforces fine-grained, group-based access control (e.g., Engineering, HR) and provides a simple UI for viewing user details and protected areas. It includes infrastructure-as-code (Terraform) for one-command deployment and seeded test users.

Features

Quickstart

./scripts/deploy.sh
USER_POOL_ID=$(cd terraform/envs/tier5 && terraform output -raw cognito_user_pool_id)
aws cognito-idp admin-set-user-password --user-pool-id $USER_POOL_ID --username dmar@capsule.com --password "YourSecurepw23!" --permanent --region us-east-1
cd terraform/envs/tier5 && terraform output -raw alb_dns_name

Architecture

flowchart TD
    User([User Browser]) -->|HTTPS| ALB[Application Load Balancer]
    ALB -->|Auth Required| Cognito[AWS Cognito User Pool]
    Cognito -->|OIDC Callback| ALB
    ALB -->|x-amzn-oidc-* Headers| EC2[EC2 Instance]
    subgraph EC2_Instance [EC2 Instance]
        FastAPI[FastAPI App]
        Cache[(In-Memory Cache)]
    end
    EC2 --> FastAPI
    FastAPI --> Cache
    FastAPI -->|IAM Role| CognitoAPI[Cognito API]
    CognitoAPI -->|Group Membership| FastAPI
    ALB -->|Health Check Bypass| FastAPI

How it's built

The infrastructure is defined in Terraform, provisioning a VPC, public subnets, an Internet Gateway, an ALB, an EC2 instance (t3.micro), and a Cognito User Pool with custom auth triggers (Lambda functions for email-based MFA). The ALB listener rules route unauthenticated traffic to Cognito and bypass authentication for health checks. The EC2 instance runs a systemd-managed FastAPI service, initialized via user_data scripts. The app reads `x-amzn-oidc-data` or similar ALB-injected headers to identify users and queries Cognito (via IAM role) to resolve group memberships, caching results in memory.

How it runs

sequenceDiagram
    participant User as User Browser
    participant ALB as Application Load Balancer
    participant Cognito as AWS Cognito
    participant App as FastAPI App
    participant DB as DynamoDB/MFA

    User->>ALB: GET /areas/engineering
    ALB->>Cognito: Authenticate-Cognito Action
    Cognito->>User: Redirect to Hosted UI
    User->>Cognito: Submit Credentials
    Cognito->>DB: Trigger CreateAuthChallenge (MFA)
    DB->>User: Send Email Code
    User->>Cognito: Submit MFA Code
    Cognito->>DB: VerifyAuthChallenge
    Cognito->>ALB: Return OIDC Tokens
    ALB->>App: Forward Request + User Headers
    App->>App: Extract Email from Headers
    App->>App: Check Group Cache
    alt Cache Miss
        App->>Cognito: ListGroupsForUser (IAM)
        Cognito-->>App: Return Groups
        App->>App: Update Cache
    end
    alt Authorized
        App-->>User: Render Engineering Page
    else Denied
        App-->>User: Redirect to /denied
    end

How to apply & reuse

Use this as a starter template for internal tools requiring secure, group-based access without building a custom auth backend. It demonstrates how to offload authentication to the load balancer layer, reducing application complexity. The Terraform modules can be adapted for other AWS regions or integrated into existing VPCs. The custom MFA Lambda triggers provide a pattern for implementing step-up authentication or custom verification flows beyond standard SMS/TOTP.

At a glance

CapabilitiesOIDC Authentication OffloadingGroup-Based Access ControlCustom MFA FlowsInfrastructure as CodeHeader-Based Identity Propagation
ComponentsFastAPI BackendTerraform ModulesCognito Lambda TriggersALB Listener RulesJinja2 Templates
TechPythonFastAPITerraformAWS CognitoAWS ALBAWS EC2AWS LambdaAWS DynamoDB
Depends onAWS CLITerraform >= 1.0jqPython 3.9+
Integrates withAWS SES (for MFA emails)AWS IAM (for EC2 role)AWS Route53 (optional DNS)
PatternsLoad Balancer Auth PatternSidecar-less IdentityCache-Aside Group LookupCustom Challenge MFA
Reuse tagsaws-authcognito-mfaalb-oidcterraform-ec2fastapi-rbac

Repo hygiene

✓ all on main — nothing unmerged.