Social sign-in
Your app’s users can sign in with Google or GitHub. Each project uses its own OAuth app from each provider, so the consent screen shows your app’s name.
This is sign-in for your app’s users. Signing in to the VAIF Studio console is separate; see Single sign-on.
Set up a provider
Section titled “Set up a provider”-
Create an OAuth app at the provider.
- Google: Google Cloud console > APIs & Services > Credentials > Create credentials > OAuth client ID, type Web application.
- GitHub: Settings > Developer settings > OAuth Apps > New OAuth App.
-
Register the callback URL. In the console, open Authentication > Providers and choose the provider. Copy the Callback URL it shows into the provider: Google calls it an Authorized redirect URI, GitHub an Authorization callback URL. It looks like this:
https://api.vaif.studio/projects/{projectId}/auth/oauth/google/callbackThe provider sends its code to VAIF, where your client secret is. It never goes to your app.
-
Paste the client ID and secret and turn the provider on. The secret is stored encrypted and never shown again. To change other settings later, leave the secret blank and the saved one is kept.
-
Add your app’s origin to the allowed redirect URLs (Authentication > URL configuration), for example
https://myapp.com. After sign-in, VAIF only sends users back to an origin on that list. It must use https, excepthttp://localhostfor development. With an empty list, sign-in is refused.
Social sign-in needs a plan that includes it, and how many providers a project can turn on depends on the plan. See Plans.
Sign users in
Section titled “Sign users in”With @vaifstudio/client, create the client with your project ID and publishable key, as for any other sign-in:
import { createVaifClient } from "@vaifstudio/client";
const vaif = createVaifClient({ baseUrl: "https://api.vaif.studio", projectId: "YOUR_PROJECT_ID", apiKey: "YOUR_PUBLISHABLE_KEY",});
// On your sign-in page: sends the browser to the provider's consent screen.await vaif.auth.signInWithOAuth({ provider: "google", redirectUrl: "https://myapp.com/auth/callback" });On the page you named as redirectUrl, finish the sign-in:
// https://myapp.com/auth/callbackconst result = await vaif.auth.handleOAuthCallback();
if ("mfaRequired" in result) { // The user has two-factor sign-in on: ask for their code, then // await vaif.auth.mfa.verify(result.challengeToken, code);} else { console.log("signed in", result.user.id, result.isNewUser ? "(new account)" : ""); // result.accessToken is the same kind of token /auth/login returns.}handleOAuthCallback() reads ?code and ?state from the address bar, exchanges them for a session, and removes them from the URL. The session is the same as an email and password sign-in: see Session management.
To render buttons only for the providers you turned on, call vaif.auth.listOAuthProviders().
Security built in
Section titled “Security built in”- PKCE and a one-time code. The SDK creates a PKCE pair and keeps the verifier in
sessionStorageuntil the callback. The redirect back to your app carries only a one-time code that expires after 5 minutes and is useless without that verifier. No token is ever put in a URL. - State is checked. A callback this browser did not start is refused (
OAUTH_STATE_MISMATCH), so nobody can sign a visitor in to someone else’s account. - Exact redirects. Only origins on the allowed redirect URLs, checked when the sign-in starts and again when it returns.
Outside a browser
Section titled “Outside a browser”On a server or in a native app, call getOAuthSignInUrl(), open the url it returns, and keep its codeVerifier. When the user lands on your redirect URL, pass the values back:
const { url, state, codeVerifier } = await vaif.auth.getOAuthSignInUrl({ provider: "github", redirectUrl: "https://myapp.com/auth/callback",});// ...open url, then on the callback:const session = await vaif.auth.handleOAuthCallback({ code: "CODE_FROM_THE_URL", state, codeVerifier });Accounts and email addresses
Section titled “Accounts and email addresses”- A provider account that has signed in before always signs in to the same user.
- The provider must vouch for the email address. A GitHub account with no verified email is refused (
email_not_verified). - Linking by verified email only. When a new provider account’s verified email matches an existing user whose email is also verified, it signs in to that user. If the existing user’s email was never verified, the sign-in is refused (
account_exists): the user signs in with their password, verifies their email, and can then use social sign-in. - Otherwise a new user is created (if Allow sign-up is on) with the email marked verified and no password. The user can add one later with a password reset.
- Suspended and locked users cannot sign in this way either, and a user with two-factor sign-in on is always asked for their code.
Errors on the redirect
Section titled “Errors on the redirect”When a sign-in is refused, the browser comes back to your redirect URL with ?error= and a readable error_description. handleOAuthCallback() throws a VaifError whose code is OAUTH_ plus the error in capitals, with the description as its message:
error |
Meaning |
|---|---|
access_denied |
The user cancelled on the provider’s screen |
email_not_verified |
The provider account has no verified email |
account_exists |
A user with this email exists but their email is not verified |
identity_conflict |
The user already has a different account from this provider |
signup_disabled |
New sign-ups are turned off for the project |
quota_exceeded |
The project cannot take new users on its plan |
user_banned / account_locked |
The user is suspended or temporarily locked |
provider_not_enabled / provider_error |
The provider is off, or the provider could not complete the sign-in |
| Route | Use |
|---|---|
GET /projects/{projectId}/auth/oauth/providers |
Providers turned on for the project |
POST /projects/{projectId}/auth/oauth/{provider}/start |
Body { redirectUrl, codeChallenge, codeChallengeMethod: "S256", state }; answers { url }, the consent page |
GET /projects/{projectId}/auth/oauth/{provider}/callback |
Where the provider returns; redirects to your app |
POST /projects/{projectId}/auth/oauth/token |
Body { code, codeVerifier }; answers the same shape as /auth/login |
GET /projects/{projectId}/auth/oauth-apps |
Provider setup and each provider’s callback URL, for project developers |
PUT /projects/{projectId}/auth/oauth-apps/{provider} |
Body { clientId, clientSecret, enabled } (the secret only when setting it); project admins |
DELETE /projects/{projectId}/auth/oauth-apps/{provider} |
Remove a provider; project admins |