Let users sign in with an account they already have. Universal Login shows a button per provider you've enabled, and the rest happens behind the scenes.
# Enable Google for an applicationcurl -X POST https://your-app.authaz.io/api/v1/applications/{appId}/auth/oauth \ -H "X-API-Key: $AUTHAZ_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "provider": "google", "clientId": "GOOGLE_OAUTH_CLIENT_ID.apps.googleusercontent.com", "clientSecret": "GOCSPX-...", "scopes": ["openid", "email", "profile"] }'
User clicks Sign in with Google on Universal Login.
Authaz redirects to Google's consent screen.
Google returns to Authaz at /auth/oauth/google/callback?code=....
Authaz exchanges that code with Google for an ID token, reads the email and profile.
Authaz creates (or finds) the user, then redirects back to your app with an Authaz authorization code.
Your backend exchanges the Authaz code for tokens — same as the password flow.
The user's social provider only ever talks to Authaz. Your app sees a normal OAuth 2.0 + PKCE flow against Authaz, regardless of which provider the user picked.
If a user signs in with Google using you@example.com, then later signs in with GitHub using the same verified email, Authaz links them into a single user record by default. Their access token's sub is stable across both methods.
You can opt out of automatic linking per application — pass linkAccountsByEmail: false in the application's config — in which case the second provider creates a fresh user.
If your application is multi-tenant, each tenant can have its own OAuth provider config — useful when one tenant uses their own Google Workspace OAuth app:
Authaz only asks the social provider for the scopes you configure. Email and profile are usually enough; request more (e.g. https://www.googleapis.com/auth/calendar.readonly) only if your app actually needs them.
The user's scope decisions are visible in the OIDC id_token returned to your app — you can read claims like email, name, picture directly without an extra round-trip.