Social / SSO Login
How social sign-in (Google, Facebook, Apple, GitHub) and SSO work in Nest Auth — the one universal flow, the login request shape, account linking, and how to call it from every SDK.
"Sign in with Google / Apple / …" and enterprise SSO all work the same way in Nest Auth: your frontend obtains a credential from the provider, then hands it to one endpoint — POST /auth/login — tagged with which provider it came from. The backend verifies the credential with that provider, finds or creates the matching user, and returns a normal session. There's no Nest-Auth-hosted redirect/callback page to configure — you own the provider handshake on the client, Nest Auth owns the verification and the session.
The universal flow
Steps 4–6 are identical for every provider — only step 4 (how the credential is verified) differs. That's why adding a custom provider means writing only a validate() method.
Built-in providers
Enable a provider by adding its config block to NestAuthModule.forRoot({ … }); that registers it and its POST /auth/login provider name.
| Provider | providerName | Config block | Guide |
|---|---|---|---|
google | google: { clientId, clientSecret } | Google OAuth | |
facebook | facebook: { appId, appSecret } | Facebook OAuth | |
| Apple | apple | apple: { clientId, teamId, keyId, privateKey } | Apple OAuth |
| GitHub | github | github: { clientId, clientSecret } | GitHub OAuth |
| Anything else (Microsoft, Okta, Discord, internal SSO…) | your choice | customAuthProviders: [ … ] | Custom provider |
Each provider is off until you configure it — no config block, no registration.
Set up a provider, step by step
A complete walkthrough with Google (every built-in follows the same five steps — see each provider's page for its exact config keys).
1. Create the OAuth app in the provider's console. In Google Cloud Console → Create Credentials → OAuth client ID → Web application. Add your app's origin to Authorized JavaScript origins (and, if you use the redirect flow, your callback to Authorized redirect URIs). Copy the Client ID and Client secret.
2. Install the provider's optional peer dependency.
3. Configure the module (secrets from env — never hard-code them):
That single block registers the google provider and its POST /auth/login handler. Each provider's config keys:
| Provider | Config block |
|---|---|
google | { clientId, clientSecret, redirectUri, audiences? } |
facebook | { appId, appSecret, redirectUri } |
apple | { clientId (Service ID), teamId, keyId, privateKey, redirectUri, audiences? } |
github | { clientId, clientSecret, redirectUri } |
4. Get the provider token on the frontend. Use the provider's own SDK — e.g. @react-oauth/google's <GoogleLogin> gives you an ID token in response.credential.
5. Send it to POST /auth/login with createUserIfNotExists: true (see Calling it from each SDK for React / client / RN / Flutter):
That's the whole setup. The provider-specific pages (Google, Facebook, Apple, GitHub) cover the token/id-token nuances and console specifics.
The login request
Every social/SSO sign-in is the same POST /auth/login shape — a providerName plus a credentials object the provider needs:
token— the credential from the provider (an ID token, access token, or provider auth code, depending on the provider/flow).type— Google-only, selects ID-token vs access-token verification. Other providers ignore it.firstName/lastName/avatarUrl/name— optional. Apple only returns the user's name on the first authorization (and never an avatar), so capture it on the client and forward it here to persist it. Other providers fill these from their own profile data.
First-time users need
createUserIfNotExists: true. A social login for someone who doesn't have an account yet only provisions a new user when the request carriescreateUserIfNotExists: true— otherwise it returns401. The client SDK'ssocialLogin()sets it for you; with rawlogin()/ HTTP, add it yourself.
What happens on the backend
- The provider's
validate()verifies the credential with the provider and returns a normalized{ userId (the provider's user id), email, emailVerified?, metadata }. - Nest Auth looks up
nest_auth_identitiesforprovider+providerId. Found → that user is logged in. - Not found → if
registration.enabled !== false, a newNestAuthUser+ identity row are created;UserRegisteredEventfires. Otherwise the login is rejected. - A session is issued (
UserLoggedInEventalways fires).
Account linking & the verified-email gate
If a social login's email matches an existing account (e.g. someone who signed up with email/password), Nest Auth can attach the new social identity to that user. As of 2.8.0 this only happens when the provider verified the email (social.requireVerifiedEmailForLinking, default true) — so an attacker can't register an unverified-email social account to hijack an existing user. To restore the old link-by-email behavior (not recommended):
emailVerifiedAt on the user is lifted only when the provider actually attests the email (email_verified / a verified primary email) — never blanket-stamped.
MFA on social sign-in
Built-in social providers set skipMfa = true: the user already proved their identity to Google/Apple/etc., so Nest Auth doesn't issue its own MFA challenge on top. If your policy still requires app-level MFA after a social login, enforce it in a loginHooks.onLogin hook.
Calling it from each SDK
The call is the same everywhere — login({ providerName, credentials }) — you just get the provider token differently per platform.
React (@ackplus/nest-auth-react)
See React → Hooks.
Vanilla JS / any framework (@ackplus/nest-auth-client)
See Client → AuthClient.
React Native / Expo (@ackplus/nest-auth-react-native)
Get the token from a native SDK (e.g. @react-native-google-signin/google-signin, Apple's expo-apple-authentication) and pass it through the shared client / hook. For Apple, forward the first-sign-in firstName / lastName:
See React Native → Authentication.
Flutter (nest_auth_flutter)
Use the native sign-in helper to get the provider credential, then log in through the Dart client. See Flutter → Authentication.
Custom / enterprise SSO
Anything not built in — Microsoft, Okta, Auth0, Discord, an internal IdP — is a custom provider: you implement one validate() method that verifies the credential and returns the normalized user, and Nest Auth handles the identity lookup, user creation, linking, session, and events. See also the external role resolver recipe for mapping IdP groups → roles.
Related
- Google · Facebook · Apple · GitHub OAuth guides.
- Custom OAuth provider.
- Link multiple providers to one account.
POST /auth/loginreference.