---
title: "Restricted Users"
description: "Understand and handle users with limited access"
sidebarTitle: "Restricted Users"
---

Restricted users are signed-in users whose account exists, but has not been granted normal application access yet. Stack marks these users with `user.isRestricted === true` and provides a `user.restrictedReason` explaining why.

By default, Hexclave treats restricted users like unauthenticated users in most SDK calls. This prevents accounts that still need verification, review, or conversion from accidentally getting access to protected product flows.

## When users are restricted

Users can be restricted for a few reasons:

- **Email not verified**: the project requires email verification before full access.
- **Anonymous user**: anonymous users can interact with the app, but are always restricted until converted.
- **Restricted by administrator**: the user was restricted manually or by a [sign-up rule](/guides/apps/authentication/sign-up-rules).

You can inspect the reason from the SDK:

```ts my-app.ts
import { hexclaveServerApp } from "../src/stack/server";

const user = await hexclaveServerApp.getUser({ includeRestricted: true });

if (user?.isRestricted) {
  console.log(user.restrictedReason?.type);
}
```

The current `restrictedReason.type` values are:

| Type | Meaning |
| --- | --- |
| `email_not_verified` | The user still needs to verify their email address. |
| `anonymous` | The user is an anonymous user. |
| `restricted_by_administrator` | The user was restricted manually or by a sign-up rule. |

## Loading restricted users

Most calls exclude restricted users unless you explicitly opt in. Use `includeRestricted: true` when you are building onboarding, email verification, account review, or anonymous-user conversion flows.

<CodeGroup dropdown>
```ts my-app.ts
import { hexclaveServerApp } from "../src/stack/server";

const user = await hexclaveServerApp.getUser({ includeRestricted: true });

if (user?.isRestricted) {
  console.log("Needs onboarding:", user.restrictedReason?.type);
}
```

```tsx my-react-component.tsx
"use client";
import { hexclaveClientApp } from "../src/stack/client";

export default function OnboardingGate() {
  const user = hexclaveClientApp.useUser({ includeRestricted: true });

  if (!user) {
    return <a href="/handler/sign-in">Sign in</a>;
  }

  if (user.isRestricted) {
    return <RestrictedUserMessage reason={user.restrictedReason?.type} />;
  }

  return <div>Welcome back, {user.displayName ?? user.primaryEmail}</div>;
}
```
</CodeGroup>

<Info>
  Anonymous users are restricted by definition. Passing `{ or: "anonymous" }` automatically includes restricted users, and cannot be combined with `{ includeRestricted: false }`.
</Info>

## Handling restricted users

Treat restricted users as a separate state from both "signed out" and "fully signed in". A good default is to show a page that tells the user what they need to do next.

```tsx restricted-user-message.tsx
function RestrictedUserMessage({ reason }: { reason: string | undefined }) {
  if (reason === "email_not_verified") {
    return <div>Please verify your email address to continue.</div>;
  }

  if (reason === "anonymous") {
    return <a href="/handler/sign-up">Create an account to save your progress.</a>;
  }

  return <div>Your account is waiting for review.</div>;
}
```

For API routes or backend actions, keep using the default behavior unless the endpoint is specifically meant to serve restricted users. This helps prevent partially onboarded accounts from reaching product APIs.

## Restricted users in JWTs

Restricted users receive tokens with `is_restricted` and `restricted_reason` claims. If your backend verifies Hexclave JWTs directly, make sure you reject restricted users unless the endpoint intentionally supports them.

When fetching Hexclave's JWKS, restricted-user signing keys are excluded by default. Include them only for services that intentionally accept restricted users:

```txt jwks-url.txt
/.well-known/jwks.json?include_restricted=true
```

If you also accept anonymous users, use `include_anonymous=true`; anonymous keys imply restricted-user keys.

## Admin and sign-up review

Sign-up rules can restrict a user instead of rejecting the sign-up outright. This is useful when you want the account to exist, but need manual review before granting access.

For more details on creating rules that restrict users, see [Sign-up Rules](/guides/apps/authentication/sign-up-rules).
