Users & Authentication

Signing in your end users, MFA, and account recovery.

Guides

How do I set up MFA for my users?

Turn on multi-factor authentication for your project's users, choose an enforcement mode, and pick which second factors to allow.

How do I let users sign in with their phone number?

Enable SMS one-time-passcode sign-in so your users can authenticate with a verified phone number.

Common questions

How does Forte handle authentication for me?

Every request to your service goes through Forte first, which validates the caller's session before your code runs. You get sign-up, sign-in (Google, email or SMS one-time codes, passwords), session management, and bot protection without writing any auth code — your service just reads the authenticated user from the request.

Read the documentation

How do I let users sign in with Google?

Configure your Google OAuth Client ID in your project settings, render Google's Sign-In button in your app, and pass the returned credential to Forte's callback endpoint. Forte verifies the token, creates or links the user, and returns a session token.

Google contact methods count as verified from the start, and if a user with the same email already exists in the project, the Google account is linked to them instead of creating a duplicate.

Read the documentation

How long do user sessions last?

Session tokens last 365 days by default. You can renew a token before it expires with any duration you choose, and calling the logout endpoint invalidates it immediately. Tokens are cryptographically signed and opaque — they can only be validated or invalidated by Forte.

Read the documentation

What authentication methods does Forte support?

Forte supports email and SMS one-time-passcode sign-in, password-based sign-in, and Google OAuth out of the box. You can also turn on multi-factor authentication, with hardware security keys, authenticator app codes, email/SMS codes, and backup codes as second factors.

Signing in with other OAuth/OIDC providers beyond Google is in Closed Alpha — contact Forte support to get it enabled for your project.

Read the documentation

How do I let users sign in with a password?

Turn on password login in your project's authentication settings, where you also set strength rules — minimum length plus optional uppercase, lowercase, digit, and symbol requirements. Users can set a password at sign-up or later, then sign in with any of their verified contact methods plus the password.

One-time-code login stays available either way, so users always have a recovery path.

Read the documentation

How do I disable Forte authentication for some or all of my routes?

Add authentication path exclusions to your service. Exclusions use Ant-style patterns — "/public/**" opens everything under /public, and "/**" makes the whole service public. CORS preflight (OPTIONS) requests are always allowed through automatically.

Read the documentation

How does password reset work?

Your app calls the password-reset endpoint with the user's email or phone number, and Forte sends the reset to their first verified contact method. Depending on your project's reset mode, the user receives either a generated 16-character password or a single-use reset link (30-minute expiry) pointing at your reset page.

The request always returns success whether or not the account exists, so attackers can't probe for registered emails.

Read the documentation

Why didn't my user receive their one-time passcode?

The most common cause is deliberate: Forte silently skips sending when no user owns that contact, or when the contact is unverified on an account that already has a verified owner — the response looks identical either way to prevent account-existence probing.

Beyond that, resends are throttled to one per 60 seconds and codes expire after 10 minutes, so have the user wait out the cooldown and request a new code.

Read the documentation

How do I stop bots from creating fake accounts?

Add Google reCAPTCHA v3 to your project: create a score-based site in the reCAPTCHA admin console, use the site key in your frontend, and save the secret key in your Forte project settings. Forte then validates a reCAPTCHA token on every sign-up and login and rejects requests that score like bots. It runs invisibly — real users never see a challenge.

Read the documentation

What happens if a user never verifies their email or phone number?

An unverified contact reserves the identifier for 10 minutes after the last verification code was sent. After that it goes stale, and another user can claim the same email or phone number by registering with it — the stale entry is removed from the original account.

Until someone else actually claims it, the original user can still recover: signing in with a one-time code or completing a password reset verifies the contact and ends its staleness.

Read the documentation

How do I suspend or delete a user?

Open the user in the console's Users dashboard (or use the server-side API) and choose Suspend or Delete. Suspending blocks authentication and invalidates the user's existing sessions but keeps the record, and you can reactivate them later.

Permanent hard-delete is only available in sandbox projects — in live projects, suspend instead.

Read the documentation

How do I authenticate users from a mobile app?

The same client-side API works outside the browser — the difference is cookies. Read the session token from the login response and send it on later requests in an "Authorization: Bearer" header instead of relying on the Forte-User-Session-Token cookie.

The session token is the user's credential, not your project's: never ship FORTE_API_TOKEN inside an app.

Read the documentation

Can I customize the emails and texts Forte sends to my users?

Yes — the email subject, email HTML body, and SMS body are editable per project under your project's notification settings, for both login one-time codes and password resets. Templates support variables like {{code}}, {{projectName}}, {{contactValue}}, and for resets {{newPassword}} or {{resetUrl}}. Leave a field blank to use Forte's built-in default.

Read the documentation