Authentication
Forte provides built-in authentication for your project's users. You configure the authentication methods you want to support, and Forte handles user creation, session management, and security. Your application interacts with Forte's SDK to authenticate users and manage their sessions.
Forte supports Google OAuth and one-time-passcode (OTP) login over email or SMS. For password-based sign-in, see Passwords.
The authentication flows on this page are part of Forte's client-side API (forte.users.*). Call them directly from your frontend — the response sets the Forte-User-Session-Token cookie automatically. Never call these from code that also holds FORTE_API_TOKEN.
Google OAuth
Google OAuth lets your users sign in with their Google accounts. Forte manages the entire OAuth flow. Configure your Google OAuth Client ID on your project, and Forte handles the rest: token verification, user creation, deduplication, CAPTCHAs, and session management.
How It Works
- Your application renders Google's Sign-In button using your project's Google OAuth Client ID.
- When a user completes the Google sign-in flow, Google returns a credential token to your application.
- Your application sends the credential token to Forte's callback endpoint, along with a reCAPTCHA token if bot protection is enabled.
- Forte verifies the token, creates or links the user, and returns a session token.
Example
import { GoogleLogin } from "@react-oauth/google";
import { ForteClient } from "@forteplatforms/sdk";
const forte = new ForteClient();
function LoginButton({ projectId }: { projectId: string }) {
const handleSuccess = async (response) => {
const csrfToken = crypto.randomUUID();
// If reCAPTCHA is configured on your project, execute before calling the callback
const recaptchaToken = await grecaptcha.execute("YOUR_RECAPTCHA_SITE_KEY", {
action: "login",
});
const result = await forte.users.googleAuthLoginCallback({
projectId,
gCsrfToken: csrfToken,
credential: response.credential,
recaptchaToken, // optional — required if reCAPTCHA is configured
});
// result.userObject — the authenticated user
// result.sessionToken.sessionToken — use for subsequent requests
// result.sessionToken.expirationTime — token expiry (default: 365 days)
console.log("Logged in as", result.userObject.fullName);
};
return <GoogleLogin onSuccess={handleSuccess} />;
}Setup
Configure your Google OAuth Client ID on your project in the Console or via the CLI. Once configured, your application can use Google's Sign-In button and send the resulting credential to Forte.
User Creation and Linking
- If the user is signing in for the first time, Forte automatically creates a new user account with a verified Google contact method.
- If a user with the same email already exists in the project, Forte links the Google account to the existing user.
- Google OAuth contact methods are verified by default since Google has already verified the user's email.
Response
A successful authentication returns:
- The user object with the user's profile and contact methods
- A session token for authenticating subsequent requests
- The session token's expiration time (defaults to 365 days)
Forte automatically sets a Forte-User-Session-Token cookie on the response. Your application can use either the cookie or the session token from the response body to authenticate subsequent requests.
Bot Protection with reCAPTCHA
Forte supports Google reCAPTCHA v3 for automatic bot protection on your project's authentication endpoints. When configured, Forte validates a reCAPTCHA token on every sign-up and login request, rejecting requests that appear to come from bots or automated scripts.
reCAPTCHA v3 runs invisibly in the background — your users never see a challenge or checkbox. Instead, Google assigns a risk score to each request, and Forte rejects requests with scores that indicate automated or suspicious activity.
reCAPTCHA is only enforced when a secret key is configured on your project. If no key is set, authentication endpoints work normally without reCAPTCHA validation.
Why Use reCAPTCHA
- Prevent credential stuffing: Block automated login attempts that test stolen credentials against your application.
- Stop spam registrations: Prevent bots from creating fake user accounts in bulk.
- No user friction: reCAPTCHA v3 is invisible — legitimate users are never interrupted with challenges.
Setup
- Go to the Google reCAPTCHA admin console and create a new site.
- Select Score based (v3) as the reCAPTCHA type.
- Add your application's domain(s) to the allowed domains list.
- Google will provide two keys:
- Site key — use this in your frontend to load the reCAPTCHA script and generate tokens.
- Secret key — set this in your Forte project settings.
- In the Forte Console, go to Project Settings and enter your reCAPTCHA v3 secret key.
Frontend Integration
Load the reCAPTCHA v3 script in your application and execute it before calling Forte's authentication endpoints. Pass the resulting token as recaptchaToken in your SDK calls.
// Load reCAPTCHA v3 script in your HTML:
// <script src="https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY"></script>
// Execute reCAPTCHA before authentication
const recaptchaToken = await grecaptcha.execute("YOUR_SITE_KEY", {
action: "login", // use "login" or "signup" for Google OAuth
});
// Pass the token to the Forte SDK
const result = await forte.users.googleAuthLoginCallback({
projectId,
gCsrfToken: csrfToken,
credential: response.credential,
recaptchaToken,
});Error Handling
If reCAPTCHA validation fails, Forte returns a 400 error with the error code RECAPTCHA_VALIDATION_FAILED. This can happen when:
- The reCAPTCHA token is missing or invalid.
- The request received a low risk score (indicating bot-like behavior).
- The token has expired (tokens are valid for a short time after generation).
reCAPTCHA Actions
When executing reCAPTCHA on your frontend, use these action names to match what Forte expects:
| Endpoint | Action |
|---|---|
| Google OAuth login/signup | login or signup |
| User registration | register |
| OTP login request | login |
OTP Login (Email and SMS)
Forte supports passwordless sign-in via a 6-digit one-time passcode sent to the user's email or phone number. The same API powers both channels — the request body's email or phoneNumber field selects which one. Codes are time-limited (10 minutes), single-use, attempt-limited (5 tries), and hashed at rest.
The flow is SDK-driven so you can build whatever sign-in UI fits your app. The notification templates rendered to your users are customizable on a per-project basis — see Notification Templates in the Console.
OTP login uses the same emailLoginEnabled and phoneLoginEnabled flags as registration. Enable the channel you want in your project settings before calling createOtpLogin.
How It Works
- Your app collects an email address or phone number.
- Your app calls
createOtpLoginwith that contact. Forte returns apendingLoginIdand the code'sexpirationTime. - If a user with that verified contact method exists, Forte sends a 6-digit code to it. If not, Forte returns the same response shape but sends nothing — this prevents account-existence enumeration.
- The user enters the code in your UI; your app calls
completeOtpLoginwith thependingLoginIdand code. Forte verifies, marks the code consumed, and returns a session token. The session cookie (Forte-User-Session-Token) is also set on the response. - If the user needs a new code, your app calls
resendLoginOtp. Resends are throttled to once every 60 seconds and never extend the original 10-minute window.
Request OTP
import { ForteClient } from "@forteplatforms/sdk";
const forte = new ForteClient();
// Email channel
const emailRequest = await forte.users.createOtpLogin({
projectId,
createOtpLoginRequest: {
email: "alice@example.com",
recaptchaToken, // optional — required if reCAPTCHA is configured
},
});
// SMS channel
const smsRequest = await forte.users.createOtpLogin({
projectId,
createOtpLoginRequest: {
phoneNumber: "+15551234567",
recaptchaToken,
},
});
// Stash pendingLoginId — you'll need it to verify or resend.
const { pendingLoginId, expirationTime } = emailRequest;Exactly one of email or phoneNumber must be set. Sending both, or neither, returns a 400 with NO_CONTACT_METHOD_PROVIDED.
Verify OTP
const result = await forte.users.completeOtpLogin({
projectId,
pendingLoginId,
completeOtpLoginRequest: { code: "123456" },
});
// result.userObject — the authenticated user
// result.sessionToken.sessionToken — use for subsequent requests
// result.sessionToken.expirationTime — 365 days from nowA wrong code returns 400 INVALID_VERIFICATION_CODE and increments the pending login's attempt counter. After 5 failed attempts the pending login is locked — even the correct code will be rejected and the user must request a new one. Expired and already-consumed codes return the same error.
Resend
const resent = await forte.users.resendLoginOtp({
projectId,
pendingLoginId,
});
// Same response shape as createOtpLogin.Resends within 60 seconds of the last send return 429 VERIFICATION_CODE_RATE_LIMITED. After the throttle window passes, a fresh 6-digit code is generated and sent; the 10-minute expiration window is not extended.
Example Sign-In Component (SMS)
By continuing, you agree to receive a one-time passcode via SMS.
Your sign-in UI must display the message "By continuing, you agree to receive a one-time passcode via SMS" before sending an OTP. This is a compliance requirement for SMS-based authentication.
Customizing the Message
The email subject, email HTML body, and SMS body are all editable per project under the Login OTP tab in your project's notification settings. Supported template variables in login-OTP templates: {{code}}, {{projectName}}, {{contactValue}}. ({{userFullName}} is intentionally unsupported here — at OTP send time, the user's identity has not yet been confirmed.)
Next Steps
- Learn about Contact Methods and how verification works
- Understand Sessions and token management