AWS Cognito + Google SSO Migration Guide
Overview
This guide provides step-by-step instructions for migrating the architecture-docs site from AWS Amplify basic authentication to Amazon Cognito with Google as the identity provider (IdP).
Repository: architecture-docs Current Deployment: AWS Amplify - https://eng.adaction.com Tech Stack: mkdocs, Node.js 18+, Python Credentials Location: 1Password "Engineering" vault
Table of Contents
- Prerequisites
- Phase 1: Pre-Implementation Discovery
- Phase 2: Google OAuth Setup
- Phase 3: Create Cognito User Pool
- Phase 4: Domain Whitelist Configuration
- Phase 5: Google IdP Integration
- Phase 6: Amplify Integration
- Phase 7: Testing & Validation
- Phase 8: Migration Execution
- Rollback Procedures
- Troubleshooting
Prerequisites
- AWS Console access with permissions to:
- Amazon Cognito
- AWS Amplify
- AWS Lambda
- CloudWatch Logs
- IAM (for role creation)
- Google Cloud Console access (for OAuth setup)
- List of authorized email domains (@adaction.com, @adgem.com, etc.)
- Access to 1Password "Engineering" vault
Phase 1: Pre-Implementation Discovery
1.1 Document Current Basic Auth Configuration
- Log into AWS Console and navigate to AWS Amplify
- Select the
architecture-docsapplication - Go to App settings → Access control
- Take screenshots of the current basic auth configuration
- Note down:
- Username/password scheme (if applicable)
- Restricted branches
- Any IP allowlists or restrictions
- Store screenshots in a secure location for rollback reference
1.2 Identify Authorized Domains
Create a list of email domains that should have access:
- @adaction.com
- @adgem.com
- (Add any additional domains as needed)
Document this list for use in the domain whitelist Lambda function.
Phase 2: Google OAuth Setup
2.1 Check for Existing Google OAuth Credentials
- Access 1Password "Engineering" vault
- Search for "Google OAuth" or "architecture-docs" entries
- Look for:
- Client ID
- Client Secret
- Project name
If credentials exist, proceed to 2.3 Verify Configuration. If not, continue to 2.2.
2.2 Create New Google OAuth Client (If Needed)
- Go to Google Cloud Console
- Create a new project or select existing project:
- Project name:
architecture-docs-auth(or similar) -
Note the Project ID
-
Enable Google+ API:
- Navigate to APIs & Services → Library
- Search for "Google+ API"
-
Click Enable
-
Configure OAuth Consent Screen:
- Go to APIs & Services → OAuth consent screen
- Select Internal (for organization-only access)
- Fill in application details:
- App name:
Architecture Docs - User support email: Your email
- Developer contact email: Your email
- App name:
- Add scopes:
emailprofileopenid
-
Save and continue
-
Create OAuth 2.0 Client ID:
- Go to APIs & Services → Credentials
- Click Create Credentials → OAuth client ID
- Application type: Web application
- Name:
Architecture Docs - Cognito - Authorized redirect URIs: (You'll update this after creating Cognito User Pool)
- Format:
https://<your-cognito-domain>.auth.<region>.amazoncognito.com/oauth2/idpresponse - You'll get this URL in Phase 3
- Format:
-
Click Create
-
Save credentials:
- Copy the Client ID
- Copy the Client Secret
- Store both in 1Password "Engineering" vault under "Architecture Docs - Google OAuth"
2.3 Verify Configuration
Ensure you have: - ✅ Google Cloud project created - ✅ OAuth consent screen configured (Internal) - ✅ OAuth 2.0 Client ID and Secret - ✅ Credentials stored securely in 1Password
Phase 3: Create Cognito User Pool
3.1 Create User Pool
- Open AWS Console and navigate to Amazon Cognito
- Click Create user pool
3.2 Configure Sign-in Experience
Step 1: Configure sign-in experience - Authentication providers: - Select Federated identity providers - Check Google - Cognito user pool sign-in options: - Select Email - Click Next
3.3 Configure Security Requirements
Step 2: Configure security requirements - Password policy: - Select Cognito defaults or customize based on security requirements - Multi-factor authentication: - Select Optional MFA or No MFA (recommended: Optional) - If Optional: Enable Authenticator apps - User account recovery: - Check Email only - Click Next
3.4 Configure Sign-up Experience
Step 3: Configure sign-up experience - Self-service sign-up: - Disable self-service sign-up (we'll control access via domain whitelist) - Attribute verification: - Check Send email message, verify email address - Required attributes: - Keep default (email is already required) - Click Next
3.5 Configure Message Delivery
Step 4: Configure message delivery
- Email provider:
- Select Send email with Cognito (or configure SES if high volume expected)
- SES Region: Choose appropriate region if using SES
- FROM email address: no-reply@verificationemail.com (or your domain)
- Click Next
3.6 Integrate Your App
Step 5: Integrate your app
- User pool name: architecture-docs-user-pool
- Hosted authentication pages:
- Check Use the Cognito Hosted UI
- Domain:
- Domain type: Cognito domain
- Cognito domain: architecture-docs-auth (or unique name)
- Click Check availability
- Initial app client:
- App client name: architecture-docs-amplify
- Client secret: Generate a client secret
- Allowed callback URLs: https://eng.adaction.com/oauth2/callback
- Also add: https://eng.adaction.com
- Allowed sign-out URLs: https://eng.adaction.com
- Advanced app client settings:
- OAuth 2.0 grant types:
- Check Authorization code grant
- OpenID Connect scopes:
- Check: openid, email, profile
- Click Next
3.7 Review and Create
Step 6: Review and create - Review all settings - Click Create user pool
3.8 Note Important Values
After creation, note down:
- User Pool ID: <region>_xxxxxxxxx
- User Pool ARN: arn:aws:cognito-idp:<region>:<account-id>:userpool/<pool-id>
- App Client ID: From app client settings
- App Client Secret: From app client settings
- Cognito Domain: https://architecture-docs-auth.auth.<region>.amazoncognito.com
Store these values securely in 1Password under "Architecture Docs - AWS Cognito".
Phase 4: Domain Whitelist Configuration
To restrict access to specific email domains, we'll create a Lambda trigger for pre-authentication.
4.1 Create Lambda Function
- Navigate to AWS Lambda in the console
- Click Create function
- Configure:
- Function name:
architecture-docs-domain-whitelist - Runtime: Python 3.12
- Permissions: Create new role with basic Lambda permissions
- Click Create function
4.2 Add Function Code
Replace the default code with:
import json
# List of allowed email domains
ALLOWED_DOMAINS = [
'adaction.com',
'adgem.com',
# Add more domains as needed
]
def lambda_handler(event, context):
# Get the user's email from the event
email = event['request']['userAttributes'].get('email', '')
# Extract domain from email
domain = email.split('@')[-1].lower() if '@' in email else ''
# Check if domain is in allowed list
if domain not in ALLOWED_DOMAINS:
raise Exception(f'Access denied: Email domain {domain} is not authorized')
# If domain is allowed, return the event to continue the flow
return event
- Click Deploy
4.3 Configure Lambda Permissions
- Go to Configuration → Permissions
- Note the execution role name (e.g.,
architecture-docs-domain-whitelist-role-xxxxx) - Click on the role name to open IAM
- Ensure the role has basic Lambda execution permissions (should be automatic)
4.4 Attach Lambda Trigger to Cognito
- Return to Amazon Cognito → User pools
- Select
architecture-docs-user-pool - Go to User pool properties → Lambda triggers
- Under Authentication, select Pre authentication trigger
- Select the Lambda function:
architecture-docs-domain-whitelist - Click Save changes
4.5 Test Domain Whitelist
Before proceeding, test with: - An email from an allowed domain (should succeed) - An email from a non-allowed domain (should be rejected)
Phase 5: Google IdP Integration
5.1 Add Google as Identity Provider
- In Amazon Cognito → User pools →
architecture-docs-user-pool - Go to Sign-in experience → Federated identity provider sign-in
- Click Add identity provider
- Select Google
5.2 Configure Google Identity Provider
- Client ID: Paste the Google OAuth Client ID from Phase 2
- Client secret: Paste the Google OAuth Client Secret from Phase 2
- Authorized scopes:
profile email openid - Attribute mapping:
- Google attribute:
email→ User pool attribute:email - Google attribute:
name→ User pool attribute:name - Google attribute:
sub→ User pool attribute:username - Click Add identity provider
5.3 Update Google OAuth Redirect URI
- Go back to Google Cloud Console
- Navigate to APIs & Services → Credentials
- Select your OAuth 2.0 Client ID
- Under Authorized redirect URIs, add:
https://architecture-docs-auth.auth.<region>.amazoncognito.com/oauth2/idpresponse- Replace
<region>with your AWS region (e.g.,us-east-1) - Click Save
5.4 Update App Client to Use Google
- Return to Cognito User Pool
- Go to App integration → App clients and analytics
- Select
architecture-docs-amplifyapp client - Under Hosted UI settings, click Edit
- Identity providers:
- Check Google
- Uncheck Cognito user pool (only allow Google login)
- Click Save changes
Phase 6: Amplify Integration
6.1 Configure Cognito in Amplify
- Navigate to AWS Amplify in the console
- Select the
architecture-docsapplication - Go to App settings → Access control
- Click Manage access
6.2 Add Cognito Authentication
- Access control type:
- Select Restrict access with Cognito
- Select a Cognito user pool:
- Choose:
architecture-docs-user-pool - Apply access control to:
- Select All branches or specific branches as needed
- Recommended: Apply to
mainbranch initially - Keep basic authentication?
- Disable the current basic auth
- Note: Keep the configuration saved elsewhere for rollback
- Click Save
6.3 Verify Amplify Configuration
- Go to App settings → Access control
- Verify:
- ✅ Cognito user pool is selected
- ✅ Branches are protected
- ✅ Basic auth is disabled
Phase 7: Testing & Validation
7.1 Test Authentication Flow
- Open the architecture-docs site in incognito/private window:
- URL: https://eng.adaction.com
- You should be redirected to Cognito Hosted UI
- Click Continue with Google
- Authenticate with a Google account from an allowed domain
- Verify you're redirected back to the docs site
- Verify the site loads correctly and all pages are accessible
7.2 Test Domain Whitelist
- Attempt to sign in with a Google account from a non-allowed domain
- Verify access is denied with an appropriate error message
- Check CloudWatch Logs for the Lambda function to verify the trigger fired
7.3 Test Sign-Out
- Sign out from the docs site (look for sign-out link or clear session)
- Verify you're redirected to the Cognito sign-in page
- Sign in again to verify re-authentication works
7.4 Test with Multiple Users
- Have 3-5 team members test authentication
- Test from different browsers and devices
- Collect feedback on user experience
- Verify all users from allowed domains can access
7.5 Verify CloudWatch Logs
- Navigate to CloudWatch → Log groups
- Check logs for:
- Lambda function:
/aws/lambda/architecture-docs-domain-whitelist - Cognito: Look for authentication events
- Verify no unexpected errors
Phase 8: Migration Execution
8.1 Pre-Migration Checklist
Verify the following before migration: - [ ] Cognito User Pool created and configured - [ ] Google IdP integrated and tested - [ ] Domain whitelist Lambda tested with allowed/denied domains - [ ] Amplify configured to use Cognito (but not yet active in production) - [ ] Test users successfully authenticated - [ ] Rollback procedure documented and reviewed - [ ] Team notified of migration timing - [ ] Basic auth configuration backed up
8.2 Execute Migration
- Coordinate with team:
- Announce maintenance window (5-10 minutes expected)
-
Have team members ready to test immediately after
-
Enable Cognito in Amplify:
- Go to AWS Amplify →
architecture-docs→ Access control - If not already done, configure Cognito as described in Phase 6
-
Click Save
-
Disable Basic Auth:
- Remove basic auth configuration from Amplify
-
Save changes
-
Monitor deployment:
- Watch CloudWatch logs for authentication events
- Check for any errors in Lambda function logs
8.3 Immediate Post-Migration Validation
- Have 3-5 team members test access immediately
- Verify all can authenticate successfully
- Check for any error messages or issues
- Monitor CloudWatch Logs for anomalies
8.4 Communication
- Notify team that migration is complete
- Share sign-in URL: https://eng.adaction.com
- Provide brief instructions:
- "Click 'Continue with Google'"
- "Use your @adaction.com or @adgem.com email"
- Share link to troubleshooting guide (see below)
Rollback Procedures
If issues occur during or after migration, follow these steps to rollback to basic authentication.
When to Rollback
- Critical authentication failures affecting multiple users
- Cognito service issues preventing access
- Domain whitelist incorrectly blocking authorized users
- Any P0 issue preventing team access to documentation
Rollback Steps
-
Log into AWS Console → Amplify →
architecture-docs -
Re-enable Basic Auth:
- Go to App settings → Access control
- Click Manage access
- Select Restrict access with a username and password
- Enter the previous basic auth credentials (from Phase 1 screenshots)
- Apply to the same branches
-
Click Save
-
Disable Cognito:
- While in Access control settings
- Remove or disable Cognito authentication
-
Click Save
-
Verify Rollback:
- Open the docs site in incognito window
- Verify basic auth prompt appears
-
Enter credentials and verify access
-
Notify Team:
- Inform team that rollback was executed
- Provide basic auth credentials via secure channel
- Schedule post-mortem to review issues
Post-Rollback Actions
- Review CloudWatch Logs to identify root cause
- Fix identified issues in Cognito/Lambda configuration
- Re-test in a staging environment if possible
- Schedule new migration attempt after fixes are validated
User Management
Adding New Authorized Domains
- Navigate to AWS Lambda →
architecture-docs-domain-whitelist - Update the
ALLOWED_DOMAINSlist in the function code:python ALLOWED_DOMAINS = [ 'adaction.com', 'adgem.com', 'newdomain.com', # Add new domain here ] - Click Deploy
- Test with a user from the new domain
Removing Domains
- Navigate to AWS Lambda →
architecture-docs-domain-whitelist - Remove the domain from the
ALLOWED_DOMAINSlist - Click Deploy
- Existing sessions may remain active until they expire
Adding Individual Users (Outside Whitelisted Domains)
If you need to grant access to a specific user outside the allowed domains:
Option 1: Add their domain to the whitelist (if others from that domain should have access)
Option 2: Create a Cognito user directly (bypasses the Lambda trigger for pre-created users)
1. Go to Amazon Cognito → architecture-docs-user-pool
2. Go to Users tab
3. Click Create user
4. Enter email address
5. Set temporary password (user will be prompted to change)
6. Click Create user
Note: The domain whitelist Lambda only runs on federated (Google) authentication, not for direct Cognito users.
Removing User Access
For federated users (Google): - Access is controlled by domain whitelist - Simply remove their domain from the whitelist (affects all users from that domain)
For individual Cognito users:
1. Go to Amazon Cognito → architecture-docs-user-pool
2. Go to Users tab
3. Select the user
4. Click Disable user or Delete user
Troubleshooting
Issue: "Access denied: Email domain X is not authorized"
Cause: User's email domain is not in the whitelist
Resolution: 1. Verify the user's email domain should have access 2. Add the domain to the Lambda whitelist (see User Management) 3. Have user retry authentication
Issue: "Invalid redirect URI" or OAuth error
Cause: Mismatch between Cognito callback URLs and Google OAuth configuration
Resolution:
1. Verify Cognito domain and app client callback URLs match exactly
2. Check Google Cloud Console → OAuth Client → Authorized redirect URIs
3. Ensure the URI is: https://<cognito-domain>.auth.<region>.amazoncognito.com/oauth2/idpresponse
4. Update as needed and retry
Issue: User authenticated but gets "Access Denied" from Amplify
Cause: Amplify not properly configured to recognize Cognito user pool
Resolution: 1. Check Amplify Access Control settings 2. Verify the correct Cognito User Pool is selected 3. Ensure the branch is properly protected with Cognito 4. Check CloudWatch Logs for detailed error messages
Issue: "Client authentication failed" error
Cause: Google OAuth client secret mismatch or expiration
Resolution: 1. Verify Google OAuth client secret in Google Cloud Console 2. Update the secret in Cognito User Pool → Identity providers → Google 3. Retry authentication
Issue: Lambda function errors in CloudWatch
Cause: Lambda syntax error, permission issue, or unexpected event structure
Resolution:
1. Check CloudWatch Logs → /aws/lambda/architecture-docs-domain-whitelist
2. Review the error message
3. Common fixes:
- Verify Lambda has correct execution role
- Check for typos in ALLOWED_DOMAINS list
- Ensure Lambda is attached to correct Cognito trigger
Issue: Users get signed out frequently
Cause: Short session timeout or token expiration
Resolution: 1. Go to Cognito User Pool → App integration → App client 2. Check Token expiration settings 3. Increase Access token and ID token expiration (e.g., 24 hours) 4. Increase Refresh token expiration (e.g., 30 days)
Monitoring and Maintenance
CloudWatch Dashboards
Consider creating a CloudWatch dashboard to monitor: - Cognito authentication success/failure metrics - Lambda invocation counts and errors - Amplify access logs
Regular Maintenance Tasks
- Quarterly: Review and update allowed domains list
- Monthly: Review CloudWatch Logs for authentication anomalies
- As needed: Rotate Google OAuth client secrets
- After major changes: Test authentication flow end-to-end
Additional Resources
- Amazon Cognito Documentation
- AWS Amplify Access Control
- Google OAuth 2.0 Documentation
- Cognito Lambda Triggers
Document Version History
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0 | 2025-10-30 | Initial | Created comprehensive migration guide |
Questions or Issues? Contact the Engineering team or refer to the troubleshooting section above.