This guide connects one Google OAuth web client to the shared Cognito user pool
at auth.dtcdev.click. Cognito then serves Google login to Dapier, DataOps,
System Design Studio, AI Engineering Gym, and Datamailer. Do not create a
separate Google OAuth client for each service: Google returns to Cognito first,
and Cognito returns to the selected service client afterward.
You need:
- permission to manage a Google Cloud project associated with the
datatalks.clubGoogle Workspace organization; - permission to update
dtcdev-shared-auth/google-oauthin AWS Secrets Manager; - permission to run that repository's shared-auth deployment workflow;
- access to one
@datatalks.clubGoogle account for the allowed test and one non-domain Google account for the rejection test.
Never paste the OAuth client secret into chat, an issue, a command argument that will be logged, or a tracked file.
- Open the Google Cloud console and select the project that will own the OAuth client.
- Open Google Auth Platform → Branding and configure:
- app name:
DataTalksClub Development Auth; - a monitored
@datatalks.clubuser-support email; - developer contact information;
dtcdev.clickas an authorized domain if the console requests it.
- app name:
- Open Google Auth Platform → Audience.
- Select Internal when the project belongs to the
datatalks.clubGoogle Workspace organization. This is preferred because Google then limits the app to organization members before Cognito's own domain guard runs. - If Internal is unavailable, select External. While the app remains in
Testing, add every allowed
@datatalks.clubaccount under Test users. Publish or verify the app before expecting other users to sign in.
The AWS domain-guard Lambda remains mandatory even with an Internal audience. It validates the mapped, verified email during first federation and every later Google authentication rather than trusting a browser-supplied domain hint.
Open Google Auth Platform → Clients, select Create client, and use:
| Field | Value |
|---|---|
| Application type | Web application |
| Name | DTC Development Cognito |
| Authorized JavaScript origin | https://auth.dtcdev.click |
| Authorized redirect URI | https://auth.dtcdev.click/oauth2/idpresponse |
The redirect URI must match exactly, including HTTPS and the
/oauth2/idpresponse path. This is Cognito's identity-provider response
endpoint, not any individual service callback.
After selecting Create, securely capture the client ID and client secret. The client ID is not confidential; the client secret is.
Open AWS Secrets Manager in us-east-1 and create a secret named:
dtcdev-shared-auth/google-oauth
Choose Other type of secret and store two key/value pairs:
| Key | Value |
|---|---|
client_id |
The Google OAuth client ID |
client_secret |
The matching Google OAuth client secret |
GitHub stores neither value. The GitHub deployment role can inspect only the secret's version metadata; the CloudFormation service role resolves the actual values within AWS and supplies them directly to Cognito.
Run Deploy shared authentication in DataTalksClub/aws-infra:
gh workflow run deploy-shared-auth.yml --repo DataTalksClub/aws-infraThe workflow uses GitHub OIDC to assume the least-privilege AWS deployment
role, reads the current non-secret version ID, updates the
dtcdev-shared-auth stack in us-east-1, and verifies the Google provider.
Only CloudFormation's AWS service role can read the credential value.
After it succeeds, this repository's CI and deploy auth policy workflow deploys and verifies the domain-guard Lambda independently. It does not need or read the Google OAuth client secret.
The automated verifier requires AWS access but no user credentials:
uv run --with boto3 python scripts/verify_deployment.py --liveIt checks that all five Cognito application clients enable Google as their
only identity provider, their callback/logout registrations match
config/clients.json, the Google provider maps the email and email_verified
claims the guard reads, each Google authorization request reaches
accounts.google.com, the deployed guard allows a verified @datatalks.club
address and rejects both another domain and a missing email_verified, and no
disposable Codex test users remain.
Then use private browser windows for the two human checks:
- Sign in with a real
@datatalks.clubGoogle account and confirm the service returns to its authenticated page. - Sign out from both the service and Google/Cognito, open a fresh private window, and attempt sign-in with a non-domain Google account. Confirm it is rejected.
Repeat the allowed login once for each service because each has its own Cognito client and callback:
https://dapier.dtcdev.click/auth/loginhttps://ops.dtcdev.click/loginhttps://sds.dtcdev.click/loginhttps://gym.dtcdev.click/loginhttps://datamailer.dtcdev.click/admin/login/
Do not record passwords, authorization codes, cookies, ID tokens, or the OAuth client secret in screenshots or issue comments.
Create a replacement Web application client using the same origin and redirect URI. Google client secrets should be treated as passwords; do not try to recover or reuse a value that may have been exposed.
Use this order to avoid unnecessary downtime:
- Create the replacement Google OAuth client.
- Create a new version of
dtcdev-shared-auth/google-oauthin AWS Secrets Manager with the replacementclient_idandclient_secretvalues. - Run the
aws-infrashared-auth deployment workflow; it passes the new version ID so Cognito refreshes both values. - Complete an allowed Google sign-in.
- delete the old OAuth client in Google Cloud;
- rerun the automated verifier and the non-domain rejection test.
redirect_uri_mismatch: compare the Google client redirect character for character withhttps://auth.dtcdev.click/oauth2/idpresponse.- Google says access is limited to test users: add the account under Audience → Test users, publish the External app, or use an Internal Workspace project.
- Cognito returns to an invalid callback: compare the service with
config/clients.jsonand the Cognito app-client callback list. - A non-domain account signs in: stop testing, disable Google on the Cognito clients, and inspect the deployed PreSignUp and PreAuthentication Lambda triggers before restoring access.