AWS Amplify application with a Vite React frontend (Cognito OIDC authentication) and a Python Lambda backend.
├── frontend/ # Vite React application
│ ├── src/
│ │ ├── main.jsx # OIDC AuthProvider setup
│ │ ├── App.jsx # Login/logout, backend call, modal
│ │ └── components/
│ │ └── Modal.jsx # Modal dialog component
│ ├── .env.example # Environment variable template
│ ├── .prettierrc # Prettier configuration
│ └── eslint.config.js # ESLint + Prettier configuration
├── backend/
│ ├── lambda_function.py # Lambda handler (JWT-validated /user endpoint)
│ ├── requirements.txt # Python dependencies
│ └── template.yaml # AWS SAM template
├── scripts/
│ ├── setup_infrastructure.py # Python orchestrator (all 21 steps)
│ ├── setup-amplify-app.sh # Create Amplify application
│ ├── setup-cognito.sh # Create Cognito User Pool
│ ├── deploy-frontend.sh # Deploy frontend to Amplify
│ ├── deploy-backend.sh # Deploy backend via SAM
│ ├── configure-amplify-hostnames.sh # Configure custom domains
│ ├── configure-amplify-certificates.sh # Configure SSL certificates
│ └── configure-amplify-environment.sh # Set environment variables
├── .github/workflows/
│ ├── deploy-staging.yml # CI/CD: deploy on push to dev
│ └── deploy-production.yml # CI/CD: deploy on push to prod
└── amplify.yml # Amplify build specification
- Node.js 20+
- Python 3.12+
- AWS CLI configured with appropriate credentials
- AWS SAM CLI
# Create Cognito User Pool for staging
./scripts/setup-cognito.sh staging us-east-1
# Create Cognito User Pool for production
./scripts/setup-cognito.sh production us-east-1
# Create the Amplify application
./scripts/setup-amplify-app.sh hello-nu-project us-east-1Go to Settings → Secrets and variables → Actions and add these secrets:
| Secret | Description | Example |
|---|---|---|
| Shared | ||
AWS_GITHUB_IAM_DEPLOYMENT_ROLE |
IAM role ARN for GitHub OIDC federation | arn:aws:iam::123456789012:role/GitHubDeploy |
AMPLIFY_APP_ID |
Amplify application ID | d1234abcdef |
| Staging | ||
STAGING_OIDC_AUTHORITY |
Cognito issuer URL | https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxx |
STAGING_OIDC_CLIENT_ID |
Cognito app client ID | 1abc2def3ghi4jkl5mno |
STAGING_HOST |
Staging hostname (used to build redirect URIs) | dev.hello-nu.com |
STAGING_API_URL |
REST API URL via custom domain | https://api.hello-nu.com/dev-rest |
STAGING_COGNITO_USER_POOL_ID |
Cognito User Pool ID | us-east-1_mzDMV2ad3 |
STAGING_COGNITO_USER_POOL_ARN |
Cognito User Pool ARN | arn:aws:cognito-idp:us-east-1:… |
STAGING_COGNITO_CLIENT_ID |
Cognito App Client ID (for SAM deploy) | 1abc2def3ghi4jkl5mno |
STAGING_ALLOWED_ORIGINS |
CORS allowed origins | https://dev.hello-nu.com |
| Production | ||
PRODUCTION_OIDC_AUTHORITY |
Cognito issuer URL | https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxx |
PRODUCTION_OIDC_CLIENT_ID |
Cognito app client ID | 6pqr7stu8vwx9yza0bcd |
PRODUCTION_HOST |
Production hostname | hello-nu.com |
PRODUCTION_API_URL |
REST API URL via custom domain | https://api.hello-nu.com/rest |
PRODUCTION_COGNITO_USER_POOL_ID |
Cognito User Pool ID | us-east-1_z9zCMkKGw |
PRODUCTION_COGNITO_USER_POOL_ARN |
Cognito User Pool ARN | arn:aws:cognito-idp:us-east-1:… |
PRODUCTION_COGNITO_CLIENT_ID |
Cognito App Client ID (for SAM deploy) | 6pqr7stu8vwx9yza0bcd |
PRODUCTION_ALLOWED_ORIGINS |
CORS allowed origins — never * |
https://hello-nu.com |
Note:
STAGING_OIDC_CLIENT_IDandSTAGING_COGNITO_CLIENT_IDhold the same value (the Cognito app client ID). The former is injected asVITE_OIDC_CLIENT_IDat frontend build time; the latter is passed to SAM deploy for the HTTP API JWT authorizer.
Set these in App settings → Environment variables (or via configure-amplify-environment.sh).
Use branch-level overrides to give dev and prod branches different values.
| Variable | Purpose | Set on branch |
|---|---|---|
| Frontend (VITE_*) | ||
VITE_OIDC_AUTHORITY |
Cognito issuer URL | dev, prod |
VITE_OIDC_CLIENT_ID |
Cognito app client ID | dev, prod |
VITE_DEV_HOST |
Staging hostname for redirect URIs | dev |
VITE_PROD_HOST |
Production hostname for redirect URIs | prod |
VITE_API_URL |
REST API URL via custom domain | dev, prod |
| Backend (SAM deploy) | ||
COGNITO_USER_POOL_ID |
Cognito User Pool ID | dev, prod |
COGNITO_USER_POOL_ARN |
Cognito User Pool ARN | dev, prod |
COGNITO_CLIENT_ID |
Cognito App Client ID | dev, prod |
ALLOWED_ORIGINS |
CORS allowed origins | dev, prod |
The amplify.yml build spec reads these variables at build time. The frontend
section derives VITE_OIDC_REDIRECT_URI and VITE_OIDC_POST_LOGOUT_REDIRECT_URI
from VITE_DEV_HOST / VITE_PROD_HOST based on $AWS_BRANCH.
# Frontend
cd frontend
cp .env.example .env
# Edit .env with your Cognito values
npm install
npm run dev
# Backend (test locally with SAM)
cd backend
sam local start-api# Associate a custom domain
./scripts/configure-amplify-hostnames.sh <app-id> example.com
# Check certificate status
./scripts/configure-amplify-certificates.sh <app-id> example.com- Staging: Push to
devorfeature/**branches triggers deployment to the staging environment. - Production: Push to
prodtriggers deployment to the production environment.
Both pipelines lint, format-check, build the frontend, and deploy both frontend (Amplify) and backend (SAM/Lambda).
Redirect and logout URLs are managed per environment via GitHub Secrets, injected at build time:
| Environment | Redirect URI | Post-Logout URI |
|---|---|---|
| Local dev | http://localhost:5173/login/callback |
http://localhost:5173/logout |
| Staging | https://dev.hello-nu.com/login/callback |
https://dev.hello-nu.com/logout |
| Production | https://hello-nu.com/login/callback |
https://hello-nu.com/logout |
The frontend reads VITE_OIDC_REDIRECT_URI and VITE_OIDC_POST_LOGOUT_REDIRECT_URI at build time. If not set, it falls back to window.location.origin with /login/callback and /logout paths. The Cognito app client must also be configured with matching callback and logout URLs.
Built with Vite + React. Uses react-oidc-context (backed by oidc-client-ts) for AWS Cognito OIDC authentication.
- Login: Redirects to Cognito Hosted UI
- Click Backend: Calls the
/userAPI endpoint with the JWT token and displays the username in a modal dialog
Python Lambda behind API Gateway with a Cognito authorizer. The /user endpoint extracts the username from the JWT token and returns it.
Three API types are deployed per environment behind the custom domain api.hello-nu.com:
| API Type | Staging Base Path | Production Base Path | Auth |
|---|---|---|---|
| REST API | dev-rest |
rest |
Cognito Authorizer |
| HTTP API | dev-http |
http |
JWT (Cognito) |
| WebSocket | dev-ws |
ws |
AWS_IAM ($connect) |
Each REST/HTTP API exposes:
- GET /user — Lambda + Cognito auth
- OPTIONS /user — Lambda + no auth (CORS preflight)
WebSocket API routes: $connect (AWS_IAM), $disconnect, $default.
Apache License 2.0