Single Sign-On (SSO)
Custom SSO Adapter
Build a custom OAuth2 Single Sign-On adapter for any provider with the SSOApiPlugin interface.
VitNode includes built-in SSO adapters for Google, Discord, and Facebook. You can connect any other OAuth2 provider (e.g. GitHub, Apple, Slack) by implementing the SSOApiPlugin interface. State cookie generation, user session linking, and login buttons are handled automatically.
Quick start: GitHub SSO Adapter
Implement the 5 interface methods and register the adapter in vitnode.api.config.ts:
1. Build the Adapter
import type { SSOApiPlugin } from "@vitnode/core/api/models/sso"
import { getRedirectUri } from "@vitnode/core/api/models/sso"
export const GitHubSSOApiPlugin = ({
clientId,
clientSecret,
}: {
clientId: string
clientSecret: string
}): SSOApiPlugin => {
const id = "github"
const redirectUri = getRedirectUri(id)
return {
id,
name: "GitHub",
// 1. Build Authorization URL
getUrl: ({ state }) =>
`https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=read:user,user:email&state=${state}`,
// 2. Exchange Authorization Code for Token
fetchToken: async (code) => {
const response = await fetch("https://github.com/login/oauth/access_token", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
client_id: clientId,
client_secret: clientSecret,
code,
redirect_uri: redirectUri,
}),
})
return await response.json()
},
// 3. Retrieve User Profile & Email
fetchUser: async ({ access_token, token_type }) => {
const headers = { Authorization: `${token_type} ${access_token}` }
// Fetch Profile
const userRes = await fetch("https://api.github.com/user", { headers })
const user = await userRes.json()
// Fetch Primary Email
const emailRes = await fetch("https://api.github.com/user/emails", { headers })
const emails: Array<{ email: string; primary: boolean; verified: boolean }> =
await emailRes.json()
const primaryEmail = emails.find((e) => e.primary && e.verified)?.email ?? user.email
return {
id: String(user.id),
email: primaryEmail,
username: user.login,
avatarUrl: user.avatar_url,
}
},
}
}2. Register in API Configuration
import { buildApiConfig } from "@vitnode/core/vitnode.config"
import { GitHubSSOApiPlugin } from "./utils/sso/github"
export const vitNodeApiConfig = buildApiConfig({
authorization: {
ssoAdapters: [
GitHubSSOApiPlugin({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
}),
],
},
})A GitHub login button automatically renders on /login and /register, and /login/sso/github routes incoming authentication requests.
SSOApiPlugin Interface Reference
Prop
Type