Overview

This post explains the complete OIDC Authorization Code flow when a user logs in via an external IdP (like Google) through Cognito User Pool.

The Complete Flow

┌──────────┐      ┌─────────────┐      ┌─────────────────┐      ┌──────────┐
│  Browser │      │  Your App   │      │     Cognito     │      │  Google  │
│          │      │  (Backend)  │      │   User Pool     │      │   IdP    │
└────┬─────┘      └──────┬──────┘      └────────┬────────┘      └────┬─────┘
     │                   │                      │                    │
     │ 1. Click "Login with Google"             │                    │
     │──────────────────>│                      │                    │
     │                   │                      │                    │
     │ 2. Redirect to Cognito                   │                    │
     │<──────────────────│                      │                    │
     │                   │                      │                    │
     │ 3. Browser goes to Cognito /oauth2/authorize                  │
     │─────────────────────────────────────────>│                    │
     │                   │                      │                    │
     │ 4. Cognito redirects to Google           │                    │
     │<─────────────────────────────────────────│                    │
     │                   │                      │                    │
     │ 5. Browser goes to Google login          │                    │
     │───────────────────────────────────────────────────────────────>│
     │                   │                      │                    │
     │ 6. User enters credentials               │                    │
     │───────────────────────────────────────────────────────────────>│
     │                   │                      │                    │
     │ 7. Google redirects with code            │                    │
     │<───────────────────────────────────────────────────────────────│
     │                   │                      │                    │
     │ 8. Browser goes to Cognito /oauth2/idpresponse                │
     │─────────────────────────────────────────>│                    │
     │                   │                      │                    │
     │                   │    9. Cognito exchanges code with Google  │
     │                   │                      │───────────────────>│
     │                   │                      │<───────────────────│
     │                   │                      │                    │
     │                   │   10. Cognito validates Google's tokens   │
     │                   │   11. Cognito creates/updates user        │
     │                   │   12. Cognito generates its own auth code │
     │                   │                      │                    │
     │ 13. Cognito redirects with Cognito code  │                    │
     │<─────────────────────────────────────────│                    │
     │                   │                      │                    │
     │ 14. Browser goes to your app /callback   │                    │
     │───────────────────>                      │                    │
     │                   │                      │                    │
     │                   │ 15. App exchanges Cognito code for tokens │
     │                   │─────────────────────>│                    │
     │                   │<─────────────────────│                    │
     │                   │                      │                    │
     │ 16. App stores tokens, user logged in    │                    │
     │<──────────────────│                      │                    │

Step-by-Step Details

Step 3: Browser to Cognito

GET https://your-domain.auth.us-east-1.amazoncognito.com/oauth2/authorize
    ?client_id=abc123clientid
    &response_type=code
    &scope=openid email profile
    &redirect_uri=https://yourapp.com/callback
    &identity_provider=Google
ParameterPurpose
client_idYour Cognito App Client ID
response_type=codeRequest authorization code (not tokens directly)
scopeWhat user info to request
redirect_uriWhere Cognito sends user after authentication
identity_providerSkip Cognito hosted UI, go directly to Google

Step 5: Browser to Google

GET https://accounts.google.com/o/oauth2/v2/auth
    ?client_id=google-client-id.apps.googleusercontent.com
    &response_type=code
    &scope=openid email profile
    &redirect_uri=https://your-domain.auth.us-east-1.amazoncognito.com/oauth2/idpresponse
    &state=xyz789

Note: redirect_uri points back to Cognito, not your app.

Step 8: Google redirects to Cognito

GET https://your-domain.auth.us-east-1.amazoncognito.com/oauth2/idpresponse
    ?code=google-auth-code-xyz
    &state=xyz789

Step 9: Cognito exchanges code with Google (server-to-server)

POST https://oauth2.googleapis.com/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=google-auth-code-xyz
&client_id=google-client-id.apps.googleusercontent.com
&client_secret=google-client-secret
&redirect_uri=https://your-domain.auth.../oauth2/idpresponse

Google responds:

{
  "access_token": "ya29...",
  "id_token": "eyJhbG...",
  "refresh_token": "1//...",
  "expires_in": 3600
}

Steps 10-12: Cognito internal processing

  1. Validate Google’s ID token: Fetch Google’s JWKS, verify signature, check aud matches Cognito’s Google client ID
  2. Create/update user: Map Google claims to Cognito attributes, create user if first login
  3. Generate Cognito’s auth code: A new code for your app to exchange

Step 14: Cognito redirects to your app

GET https://yourapp.com/callback
    ?code=cognito-auth-code-abc

Step 15: Your app exchanges Cognito code

POST https://your-domain.auth.us-east-1.amazoncognito.com/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=cognito-auth-code-abc
&client_id=abc123clientid
&client_secret=your-cognito-client-secret
&redirect_uri=https://yourapp.com/callback

Cognito responds:

{
  "access_token": "eyJraWQ...",
  "id_token": "eyJraWQ...",
  "refresh_token": "eyJjdHk...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Two Separate OIDC Flows

FlowClientIdPTokens Received
Flow ACognitoGoogleGoogle’s tokens (used internally by Cognito)
Flow BYour AppCognitoCognito’s tokens (what your app uses)

Your app never sees Google’s tokens—only Cognito’s.

Two Authorization Codes

  1. Google’s code → Cognito exchanges at Google’s /token endpoint
  2. Cognito’s code → Your app exchanges at Cognito’s /token endpoint

What Cognito’s ID Token Contains

{
  "iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXXXX",
  "aud": "abc123clientid",
  "sub": "12345678-1234-1234-1234-123456789012",
  "email": "user@gmail.com",
  "identities": [
    {
      "providerName": "Google",
      "userId": "google-user-id-123",
      "providerType": "Google"
    }
  ],
  "token_use": "id"
}
ClaimMeaning
issCognito User Pool URL (not Google)
audYour Cognito App Client ID
subCognito’s user ID (not Google’s)
identitiesShows which external IdP the user came from

Where Each Secret Lives

SecretWhere ConfiguredUsed By
Google Client IDCognito → Federation → GoogleCognito (to redirect to Google)
Google Client SecretCognito → Federation → GoogleCognito (to exchange code)
Cognito App Client IDYour app’s configYour app (to call Cognito)
Cognito App Client SecretYour app’s configYour app (to exchange code)

Why Two Flows?

This architecture provides:

  1. Abstraction: Your app only talks to Cognito, regardless of which IdP the user chose
  2. Unified tokens: Same token format whether user logged in with Google, Facebook, or username/password
  3. User management: Cognito maintains user records, linking external identities
  4. Security: Google credentials (client secret) stay in Cognito, not in your app