> ## Documentation Index
> Fetch the complete documentation index at: https://docs.crossmint.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Crossmint Auth (staging)

> Set up Crossmint Auth in staging with React, React Native, or Flutter

<Snippet file="auth-staging-note.mdx" />

## Prerequisites

* **Staging project:** Create a project in the Crossmint staging Console.
* **Client-side API key:** Create a key with the `users.create`, `users.read`, and `wallets.read` scopes. In staging, all scopes are included by default.
* **Server-side API key:** For the server examples, use a key with the `users.read` scope.

## When to Use Crossmint Auth

Use Crossmint Auth for staging, demos, and prototypes. It supports email OTP, social sign-in with Google, Apple, or X, Farcaster, and external wallets. React web includes a login modal. React Native and Flutter use headless flows.

## Setup

**React**

Install the React SDK:

<Snippet file="client-sdk-react-ui-installation-cmd.mdx" />

Add `CrossmintProvider` and `CrossmintAuthProvider` to your app. Use `useCrossmintAuth()` to sign in and out.

```tsx Providers.tsx theme={null}
"use client";

import {
    CrossmintProvider,
    CrossmintAuthProvider,
} from "@crossmint/client-sdk-react-ui";

export function Providers({ children }: { children: React.ReactNode }) {
    return (
        <CrossmintProvider apiKey="YOUR_CLIENT_API_KEY">
            <CrossmintAuthProvider>{children}</CrossmintAuthProvider>
        </CrossmintProvider>
    );
}
```

```tsx AuthButton.tsx theme={null}
"use client";

import { useCrossmintAuth } from "@crossmint/client-sdk-react-ui";

export function AuthButton() {
    const { login, logout, user } = useCrossmintAuth();

    return (
        <>
            {user == null ? (
                <button type="button" onClick={login}>Sign in</button>
            ) : (
                <button type="button" onClick={logout}>Sign out</button>
            )}
            <p>{user?.email}</p>
        </>
    );
}
```

**React Native**

Install the React Native SDK:

<Snippet file="client-sdk-react-native-ui-installation-cmd.mdx" />

The SDK uses `expo-secure-store`, `expo-web-browser`, and `expo-device`. OAuth also uses `expo-linking`, but the install command does not include it. Install it separately:

```bash theme={null}
npx expo install expo-linking
```

Set a `scheme` in your Expo config for production builds. Expo Go uses a different redirect URI, which the SDK adjusts automatically.

Add `CrossmintProvider` and `CrossmintAuthProvider` to your app:

```tsx Providers.tsx theme={null}
import {
    CrossmintProvider,
    CrossmintAuthProvider,
} from "@crossmint/client-sdk-react-native-ui";

export default function Providers({ children }: { children: React.ReactNode }) {
    return (
        <CrossmintProvider apiKey={process.env.EXPO_PUBLIC_CROSSMINT_API_KEY!}>
            <CrossmintAuthProvider>{children}</CrossmintAuthProvider>
        </CrossmintProvider>
    );
}
```

Use `useCrossmintAuth()` to start OAuth, handle its callback, and sign out:

```tsx AuthButton.tsx theme={null}
import React, { useEffect } from "react";
import { Text, TouchableOpacity } from "react-native";
import { useCrossmintAuth } from "@crossmint/client-sdk-react-native-ui";
import * as Linking from "expo-linking";

export function AuthButton() {
    const { loginWithOAuth, createAuthSession, logout } = useCrossmintAuth();
    const url = Linking.useURL();

    useEffect(() => {
        if (url != null) {
            createAuthSession(url);
        }
    }, [url, createAuthSession]);

    return (
        <>
            <TouchableOpacity onPress={() => loginWithOAuth("google")}>
                <Text>Sign in with Google</Text>
            </TouchableOpacity>
            <TouchableOpacity onPress={logout}>
                <Text>Sign out</Text>
            </TouchableOpacity>
        </>
    );
}
```

**Flutter**

Install the Flutter SDK:

<Snippet file="client-sdk-flutter-installation-cmd.mdx" />

Initialize the client and restore the session when your app starts:

```dart crossmint.dart theme={null}
import 'package:crossmint_flutter/crossmint_client.dart';
import 'package:crossmint_flutter/crossmint_flutter_auth.dart';

final client = CrossmintClient(
  config: CrossmintClientConfig(
    apiKey: const String.fromEnvironment('CROSSMINT_API_KEY'),
    appScheme: 'myapp',
  ),
);

Future<void> initializeCrossmint() async {
  await client.initialize();
  await client.auth.restoreSession();
  final authRouter = CrossmintAuthCallbackRouter(auth: client.auth);
  await authRouter.start();
}
```

Register `myapp` as the OAuth callback scheme in Android and iOS.

Add this intent filter to the main activity in `android/app/src/main/AndroidManifest.xml`:

```xml android/app/src/main/AndroidManifest.xml theme={null}
<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="myapp" />
</intent-filter>
```

Add this URL scheme to `ios/Runner/Info.plist`:

```xml ios/Runner/Info.plist theme={null}
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>myapp</string>
        </array>
    </dict>
</array>
```

The client config above sets `appScheme` to `myapp`.

Call `loginWithOAuth` to sign in and `logout` to sign out:

```dart theme={null}
client.auth.loginWithOAuth(CrossmintOAuthProvider.google);
client.auth.logout();
```

For Swift and Kotlin, see the Crossmint Auth (OTP) tab in the [Swift](/wallets/quickstarts/swift.md) and [Kotlin](/wallets/quickstarts/kotlin.md) quickstarts.

## Check That It Works

Start the React app, sign in, and confirm that your email appears.

## Login Methods

Set `loginMethods` on `CrossmintAuthProvider` to choose which methods appear. Email and Google are enabled by default.

```tsx Providers.tsx theme={null}
import { CrossmintProvider, CrossmintAuthProvider } from "@crossmint/client-sdk-react-ui";

export default function Providers({ children }: { children: React.ReactNode }) {
    return (
        <CrossmintProvider apiKey={process.env.NEXT_PUBLIC_CROSSMINT_API_KEY ?? ""}>
            <CrossmintAuthProvider loginMethods={["email", "google", "farcaster", "twitter", "web3"]}>
                {children}
            </CrossmintAuthProvider>
        </CrossmintProvider>
    );
}
```

Supported methods include email OTP, social accounts, Farcaster, and external wallets. Use `"web3:evm-only"` or `"web3:solana-only"` to limit external wallet types.

## Customize the Login Modal

Set `authModalTitle`, `termsOfServiceText`, and `appearance` on `CrossmintAuthProvider` to customize the login modal.

```tsx theme={null}
import { CrossmintAuthProvider } from "@crossmint/client-sdk-react-ui";

<CrossmintAuthProvider
    authModalTitle="Sign in to My App"
    termsOfServiceText={
        <p>
            By continuing, you agree to our <a href="/terms">Terms of Service</a> and{" "}
            <a href="/privacy">Privacy Policy</a>
        </p>
    }
    appearance={{
        spacingUnit: "8px",
        borderRadius: "12px",
        colors: {
            inputBackground: "#fffdf9",
            buttonBackground: "#fffaf2",
            border: "#835911",
            background: "#FAF5EC",
            textPrimary: "#5f2c1b",
            textSecondary: "#835911",
            textLink: "#1400cb",
            danger: "#ff3333",
            accent: "#602C1B",
        },
    }}
>
    {children}
</CrossmintAuthProvider>
```

## Read the User Profile

Use `useCrossmintAuth().user` to read the signed-in user's profile:

```tsx theme={null}
import { useCrossmintAuth } from "@crossmint/client-sdk-react-ui";

export function UserProfile() {
    const { user } = useCrossmintAuth();
    return <p>{user?.email}</p>;
}
```

## Verify Sessions on Your Server

Install `@crossmint/server-sdk` and create `CrossmintAuth` with a server-side API key that has the `users.read` scope. Use `getSession` to validate or refresh a session. Use `verifyCrossmintJwt` to verify a JWT:

```typescript session-route.ts theme={null}
import express from "express";
import { createCrossmint, CrossmintAuth } from "@crossmint/server-sdk";

const app = express();
const crossmint = createCrossmint({
    apiKey: process.env.SERVER_CROSSMINT_API_KEY!,
});
const crossmintAuth = CrossmintAuth.from(crossmint);

app.get("/api/session", async (req, res) => {
    try {
        const { jwt: token, userId } = await crossmintAuth.getSession(req, res);
        await crossmintAuth.verifyCrossmintJwt(token);
        res.json({ userId });
    } catch {
        res.status(401).json({ error: "Unauthorized" });
    }
});

app.listen(3000);
```

See the [TypeScript SDK reference](/sdk-reference/auth/typescript/overview.md) for the full API.

## Protect Session Tokens

By default, client-side JavaScript can access Crossmint Auth tokens. You can set secure cookie options for the refresh token. The session JWT remains available to client-side JavaScript because the client SDK needs it for API calls.

Add refresh and logout routes to your server. The server stores the refresh token in an `httpOnly` cookie:

```typescript server.ts theme={null}
import express from "express";
import { createCrossmint, CrossmintAuth } from "@crossmint/server-sdk";

const app = express();
const crossmint = createCrossmint({
    apiKey: process.env.SERVER_CROSSMINT_API_KEY!,
});
const crossmintAuth = CrossmintAuth.from(crossmint, {
    cookieOptions: {
        httpOnly: true,
        secure: true,
    },
});

app.post("/api/auth/refresh", async (req, res) => {
    await crossmintAuth.handleCustomRefresh(req, res);
    res.end();
});

app.post("/api/auth/logout", async (req, res) => {
    await crossmintAuth.logout(req, res);
    res.end();
});

app.listen(3000);
```

Point `CrossmintAuthProvider` to these routes:

```tsx Providers.tsx theme={null}
import type { ReactNode } from "react";
import {
    CrossmintAuthProvider,
    CrossmintProvider,
} from "@crossmint/client-sdk-react-ui";

export function Providers({ children }: { children: ReactNode }) {
    return (
        <CrossmintProvider
            apiKey={process.env.NEXT_PUBLIC_CLIENT_CROSSMINT_API_KEY!}
        >
            <CrossmintAuthProvider
                refreshRoute="/api/auth/refresh"
                logoutRoute="/api/auth/logout"
            >
                {children}
            </CrossmintAuthProvider>
        </CrossmintProvider>
    );
}
```

## User Webhooks

Crossmint sends the `users.created` event when a user signs up with Crossmint Auth. The `id` field identifies the user. The `email` and `phoneNumber` fields appear when the user signs up with the matching method.

```json theme={null}
{
    "type": "users.created",
    "status": "success",
    "data": {
        "id": "123",
        "email": "test@test.com",
        "phoneNumber": "123456789"
    }
}
```

Return a quick 2xx response to confirm delivery.

## Move to Production

For production, connect your own auth provider with the [Bring Your Own Auth guide](/wallets/guides/bring-your-own-auth.md). Then configure [JWT Authentication](/introduction/platform/api-keys/jwt-authentication.md) in the Crossmint Console.

## Next Steps

> **[Use Your Own Auth Provider](/wallets/guides/bring-your-own-auth.md)**

> **[JWT Authentication](/introduction/platform/api-keys/jwt-authentication.md)**

> **[React Wallet Quickstart](/wallets/quickstarts/react.md)**

> **[Crossmint Auth TypeScript SDK](/sdk-reference/auth/typescript/overview.md)**
