Single Sign-On (SSO)
Enable social authentication with Google, Discord, Facebook, or custom OAuth2 providers in VitNode.
VitNode provides built-in OAuth2 single sign-on. Register an adapter in your API configuration, and authentication buttons automatically appear on /login and /register.
Quick start
Register an SSO adapter in apps/api/src/vitnode.api.config.ts:
import { GoogleSSOApiPlugin } from "@vitnode/core/api/adapters/sso/google"
import { buildApiConfig } from "@vitnode/core/vitnode.config"
export const vitNodeApiConfig = buildApiConfig({
authorization: {
ssoAdapters: [
GoogleSSOApiPlugin({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
],
},
})A Google button automatically renders on your login and registration forms, brand mark included - the built-in adapters ship their own icons, and a custom one can add its own.
Supported Providers
Google Cloud Console setup with OpenID email verification
Discord
Discord Developer Portal with identify and email scopes
Meta Developers app with Facebook Login
Custom OAuth2 Adapter
Connect GitHub, Apple, or any OAuth2 provider
Provider Icons
Put a brand mark on the login buttons
Callback URLs
When configuring OAuth2 applications in provider developer consoles, use the following redirect URI pattern:
https://your-domain.com/login/sso/{provider_id}For example: https://your-domain.com/login/sso/google.
How Accounts Link
When a user signs in via SSO:
- Known Identity: The provider account was linked before, so the user is signed straight into it.
- Existing Email Match: An account already uses that address. The visitor is asked for that account's password; once it checks out, the provider identity is linked to the account and they are signed in. From then on that provider signs them straight in (case 1). A social login can never take over an account on its own - the password is what proves ownership.
- New Visitor: A new user is created with their social display name, email, and avatar.
SSO confirms the email
A provider only hands VitNode an address it has verified itself (the built-in adapters refuse anything else), so a social sign-in doubles as email confirmation:
- a new visitor starts out with
emailVerified: true, even when an email adapter is configured and password sign-ups would have to confirm first; - a known identity or a freshly linked account whose address is still unconfirmed is marked confirmed - provided the address the provider returned is the one on the account. An account whose email was changed since the link was made is left alone.
Linking an existing account
The callback answers 409 with a short-lived, signed link offer - the
account's email, whether it has a password, and a token good for ten minutes.
The login page turns that into a "Connect Provider to your account" form: the
email is shown read-only, the visitor types their password, and
POST /users/sso/{providerId}/link verifies both before it writes the
core_users_sso row and mints a session. The token carries the provider account
id, so nothing about which identity gets linked is taken from the browser.
An account created by another provider has no password to confirm with. When an email adapter is configured the form offers Set a password (the ordinary reset flow) and asks them to try the provider again afterwards; without one it points back to the login page.
Every successful link emits user.sso.linked.
The address the provider returns is matched in its canonical form, so a Google account that reports jan.kowalski@gmail.com finds the member who registered as jankowalski@gmail.com instead of quietly becoming a second account. See One Mailbox, One Account.
Learn More
Custom forms
Solve a captcha challenge in a form you built yourself - the useCaptcha hook's isReady, getToken and onReset, and where to mount the widget.
Provider Icons
Put a brand mark on your SSO login buttons - an inline SVG or image URL from the adapter, or a React component registered in the browser.