diff --git a/docs/content/docs/(guides)/concepts/sign-up-rules.mdx b/docs/content/docs/(guides)/concepts/sign-up-rules.mdx index 3b97f7975d..7acfcada5d 100644 --- a/docs/content/docs/(guides)/concepts/sign-up-rules.mdx +++ b/docs/content/docs/(guides)/concepts/sign-up-rules.mdx @@ -2,7 +2,7 @@ title: Sign-up Rules description: Control who can sign up for your application with customizable rules. icon: ShieldCheck -lastModified: "2026-02-24" +lastModified: "2026-03-20" --- Sign-up rules let you control who can sign up for your application. You can create rules that evaluate sign-up attempts based on conditions like email domain or authentication method, then allow, reject, or restrict users accordingly. @@ -31,6 +31,9 @@ When building rule conditions, you have access to these context variables: | `emailDomain` | string | The domain part of the email (after @) | | `authMethod` | string | The authentication method: `password`, `otp`, `oauth`, or `passkey` | | `oauthProvider` | string | The OAuth provider ID if using OAuth (e.g., `google`, `github`), empty string otherwise | +| `countryCode` | string | ISO 3166-1 alpha-2 country code detected at sign-up (e.g., `US`, `DE`, `JP`). Empty string if unavailable. | +| `riskScores.bot` | number | Bot risk score from 0-100. Higher values indicate higher likelihood of automated sign-up attempts. | +| `riskScores.free_trial_abuse` | number | Free trial abuse risk score from 0-100. Higher values indicate abuse patterns like disposable emails or repeated sign-ups. | The condition builder supports these operations on string values: @@ -39,6 +42,9 @@ The condition builder supports these operations on string values: - `endsWith("suffix")` - Check if value ends with a suffix - `matches("regex")` - Check if value matches a regular expression - `==` and `!=` - Exact equality comparisons +- `in` - Check if value is in a list (e.g., `countryCode in ["US", "CA"]`) + +For numeric fields like risk scores, you can use comparison operators: `>`, `>=`, `<`, `<=`. You can combine multiple conditions using AND/OR logic. @@ -100,6 +106,27 @@ Allow password sign-ups from any domain, but restrict OAuth sign-ups: 2. Rule 2: `authMethod == "oauth"` → Restrict 3. Default: Allow +### Block high-risk bot sign-ups + +Block sign-ups with a high bot risk score: + +- Condition: `riskScores.bot > 70` +- Action: Reject + +### Restrict sign-ups from specific countries + +Require manual review for sign-ups from certain countries: + +- Condition: `countryCode in ["XX", "YY"]` (replace with actual country codes) +- Action: Restrict + +### Combined fraud signals + +Block sign-ups with multiple fraud indicators: + +- Condition: `riskScores.bot > 50 && riskScores.free_trial_abuse > 50` +- Action: Reject + ## Analytics The dashboard shows analytics for each rule, including how many times it's been triggered over the past 48 hours. Use this to understand your sign-up patterns and tune your rules. diff --git a/docs/content/docs/(guides)/others/self-host.mdx b/docs/content/docs/(guides)/others/self-host.mdx index a3d11afafb..ec24ee66c9 100644 --- a/docs/content/docs/(guides)/others/self-host.mdx +++ b/docs/content/docs/(guides)/others/self-host.mdx @@ -1,6 +1,6 @@ --- title: Self-host -lastModified: "2026-01-10" +lastModified: "2026-03-20" --- @@ -121,3 +121,23 @@ To manage your dashboard configs with this account, manually go into the databas Go back to the dashboard, refresh the page, and you should see the "Stack Dashboard" project. We recommend disabling new user sign-ups to your internal project to avoid unauthorized account and project creations. Now, create a new project for your app and follow the [normal setup process](../getting-started/setup.mdx). Add `NEXT_PUBLIC_STACK_API_URL=https://your-backend-url.com` to your app's environment variables so that it connects to your API backend instead of the default Stack Auth API backend (https://api.stack-auth.com). + +## Bot protection (Turnstile) + +Stack Auth uses Cloudflare Turnstile to protect sign-up flows from bots. By default, self-hosted instances use Cloudflare's development test keys, which always pass without showing a challenge. + +For production, configure your own Turnstile keys from the [Cloudflare Dashboard](https://dash.cloudflare.com/?to=/:account/turnstile): + +| Environment Variable | Description | +|---------------------|-------------| +| `NEXT_PUBLIC_STACK_BOT_CHALLENGE_SITE_KEY` | Turnstile site key for visible challenges. | +| `NEXT_PUBLIC_STACK_BOT_CHALLENGE_INVISIBLE_SITE_KEY` | Turnstile site key for invisible challenges. | +| `STACK_TURNSTILE_SECRET_KEY` | Turnstile secret key for server-side verification. | + +Optional settings: + +| Environment Variable | Description | +|---------------------|-------------| +| `STACK_DISABLE_BOT_CHALLENGE` | Set to `true` to disable Turnstile entirely. | +| `STACK_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE` | Set to `true` to allow sign-ups even when the visible challenge fails (not recommended for production). | +| `STACK_TRUSTED_PROXY` | Set to `vercel` or `cloudflare` to trust the respective reverse proxy for reading client IP addresses. Required for accurate IP-based fraud detection when running behind a proxy. | diff --git a/docs/content/docs/sdk/types/user.mdx b/docs/content/docs/sdk/types/user.mdx index 7c9c6d4da8..1197d377e0 100644 --- a/docs/content/docs/sdk/types/user.mdx +++ b/docs/content/docs/sdk/types/user.mdx @@ -1609,14 +1609,16 @@ The `ServerUser` object contains most `CurrentUser` properties and methods with ### Table of Contents - //$stack-link-to:#currentuser & { lastActiveAt: Date; //$stack-link-to:#serveruserlastactiveat serverMetadata: Json; //$stack-link-to:#serveruserservermetadata + countryCode: string | null; //$stack-link-to:#serverusercountrycode + riskScores: { signUp: { bot: number; freeTrialAbuse: number } }; //$stack-link-to:#serveruserriskscores update(data): Promise; //$stack-link-to:#serveruserupdate @@ -1656,6 +1658,41 @@ code={`type ServerUser = + + + + The ISO 3166-1 alpha-2 country code detected at sign-up (e.g., `US`, `DE`, `JP`). Returns `null` if the country could not be determined. + + + + ```typescript + declare const countryCode: string | null; + ``` + + + + + + + + Risk scores calculated at sign-up for fraud protection. Contains: + - `signUp.bot`: Bot risk score from 0-100. Higher values indicate higher likelihood of automated sign-up attempts. + - `signUp.freeTrialAbuse`: Free trial abuse risk score from 0-100. Higher values indicate abuse patterns like disposable emails or repeated sign-ups. + + + + ```typescript + declare const riskScores: { + signUp: { + bot: number; + freeTrialAbuse: number; + }; + }; + ``` + + + +