Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
aa6c473
Document Turnstile fraud protection and new sign-up rule conditions
promptless[bot] Mar 23, 2026
592ad1e
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 17, 2026
910646e
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 17, 2026
9f85689
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 17, 2026
abdccaa
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 18, 2026
0dab510
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 18, 2026
81bec2a
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 18, 2026
a5f516f
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 18, 2026
e811d40
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 18, 2026
7e4861c
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 18, 2026
d8eda3d
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 18, 2026
4277e58
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 18, 2026
17a6676
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 18, 2026
46ea0af
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 19, 2026
eed6935
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 19, 2026
c0c9faa
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 19, 2026
3c966ae
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 19, 2026
8479581
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 19, 2026
9c2e51a
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 19, 2026
c7b72b6
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 19, 2026
e5aef62
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 19, 2026
11f62de
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 19, 2026
f37e7f7
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 20, 2026
49e9e4f
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 20, 2026
6b0c3e9
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 20, 2026
1b7a5ea
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 20, 2026
a47bbde
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 21, 2026
12ca89a
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 21, 2026
4e576ab
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 21, 2026
3f3bd1e
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 21, 2026
73fdf38
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 22, 2026
9eec41c
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 23, 2026
c1abfee
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 23, 2026
21ca337
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 23, 2026
0abd502
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 24, 2026
29e1d93
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 24, 2026
4887d80
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 24, 2026
b3c0a61
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 24, 2026
3ece21f
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 24, 2026
4c38c8b
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 24, 2026
bb1d92e
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 24, 2026
6dc205e
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 27, 2026
8d6d068
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 27, 2026
e6d6102
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 27, 2026
9843dd4
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 27, 2026
3142013
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 28, 2026
bfbbc3d
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 28, 2026
91ea98e
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 28, 2026
a6eaa9a
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 28, 2026
a372402
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 28, 2026
17f8c4c
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 29, 2026
8f58373
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] Apr 29, 2026
452fb1e
Merge branch 'dev' into promptless/turnstile-fraud-protection
promptless[bot] May 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion docs/content/docs/(guides)/concepts/sign-up-rules.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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. |
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Citation: Added countryCode and riskScores conditions based on the new SignUpRuleContext type in apps/backend/src/lib/cel-evaluator.ts which now includes countryCode, riskScores.bot, and riskScores.free_trial_abuse fields for fraud protection rule evaluation.
View source

| `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:

Expand All @@ -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.

Expand Down Expand Up @@ -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.
Expand Down
22 changes: 21 additions & 1 deletion docs/content/docs/(guides)/others/self-host.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Self-host
lastModified: "2026-01-10"
lastModified: "2026-03-20"
---

<Info type="danger">
Expand Down Expand Up @@ -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)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Citation: Turnstile environment variables documented based on apps/backend/.env.development which shows the new Turnstile configuration options: NEXT_PUBLIC_STACK_BOT_CHALLENGE_SITE_KEY, NEXT_PUBLIC_STACK_BOT_CHALLENGE_INVISIBLE_SITE_KEY, STACK_TURNSTILE_SECRET_KEY, STACK_DISABLE_BOT_CHALLENGE, STACK_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE, and STACK_TRUSTED_PROXY.
View source


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. |
41 changes: 39 additions & 2 deletions docs/content/docs/sdk/types/user.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1609,14 +1609,16 @@ The `ServerUser` object contains most `CurrentUser` properties and methods with

### Table of Contents

<ClickableTableOfContents
<ClickableTableOfContents
title="ServerUser Table of Contents"
code={`type ServerUser =
code={`type ServerUser =
// Inherits most functionality from CurrentUser
& Omit<CurrentUser, "getAuthJson" | "signOut"> //$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<void>; //$stack-link-to:#serveruserupdate

Expand Down Expand Up @@ -1656,6 +1658,41 @@ code={`type ServerUser =
</MethodLayout>
</CollapsibleTypesSection>

<CollapsibleTypesSection type="serverUser" property="countryCode" defaultOpen={false}>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Citation: New countryCode and riskScores properties on ServerUser based on changes to apps/backend/src/app/api/latest/users/crud.tsx which adds country_code and risk_scores to the user CRUD response, derived from the new signUpCountryCode, signUpRiskScoreBot, and signUpRiskScoreFreeTrialAbuse database fields.
View source

<MethodLayout>
<MethodContent>
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.
</MethodContent>
<MethodAside title="Type Definition">

```typescript
declare const countryCode: string | null;
```
</MethodAside>
</MethodLayout>
</CollapsibleTypesSection>

<CollapsibleTypesSection type="serverUser" property="riskScores" defaultOpen={false}>
<MethodLayout>
<MethodContent>
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.
</MethodContent>
<MethodAside title="Type Definition">

```typescript
declare const riskScores: {
signUp: {
bot: number;
freeTrialAbuse: number;
};
};
```
</MethodAside>
</MethodLayout>
</CollapsibleTypesSection>

<CollapsibleTypesSection type="serverUser" property="update" signature="data" defaultOpen={false}>
<MethodLayout>
<MethodContent>
Expand Down
Loading