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

# Clerk Authentication

> Configure Clerk so the Frostline agent can securely access your app during demos

## Overview

If your app uses **Clerk** for authentication, you need to configure a special sign-in flow so the Frostline agent can access your app during demos.

Frostline uses **ticket-based authentication** to securely bypass your standard Clerk login flow **only inside the demo environment**. This allows the agent to enter your app as a predefined user without interacting with login UI or exposing credentials.

This flow is built on top of Clerk’s official sign-in token mechanism. You can read more [here](https://clerk.com/docs/guides/development/custom-flows/authentication/embedded-email-links)

<Warning>The accept-token page must be available at `https://<your-domain>/accept-token`. Any deviation from this path may lead to unexpected authentication failures.</Warning>

***

## How it works

1. Frostline generates a **one-time Clerk sign-in ticket**
2. The agent navigates to `/accept-token?ticket=...`
3. Your app exchanges the ticket for a Clerk session
4. The user is signed in and redirected into your app

This flow:

* Uses Clerk’s supported authentication strategies
* Does not expose passwords or secrets
* Only runs inside the demo environment

***

<Steps>
  <Step title="Create the accept-token page">
    This page accepts the sign-in ticket from the query parameters, completes authentication with Clerk, and redirects the user into your app.

    <Tabs>
      <Tab title="Next.js (App Router)">
        Create the following file:

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

        import { useSignIn, useUser } from "@repo/auth/client";
        import { useRouter, useSearchParams } from "next/navigation";
        import { Suspense, useEffect, useState } from "react";

        function AcceptTokenContent() {
          const [loading, setLoading] = useState(false);
          const [error, setError] = useState<string | null>(null);

          const { signIn, setActive } = useSignIn();
          const { isSignedIn, user } = useUser();
          const searchParams = useSearchParams();
          const router = useRouter();

          const ticket = searchParams.get("ticket");

          useEffect(() => {
            if (!signIn || !setActive || !ticket || user || loading) return;

            const signInWithTicket = async () => {
              setLoading(true);
              try {
                const attempt = await signIn.create({
                  strategy: "ticket",
                  ticket,
                });

                if (attempt.status === "complete") {
                  await setActive({
                    session: attempt.createdSessionId,
                  });
                  router.push("/<your-app-home-page>"); // Redirect to your app's home page
                } else {
                  setError("Authentication failed.");
                }
              } catch (err) {
                console.error(err);
                setError("Authentication failed.");
              } finally {
                setLoading(false);
              }
            };

            signInWithTicket();
          }, [signIn, setActive, ticket, user, loading, router]);

          if (!ticket) return <div>No token provided.</div>;
          if (loading) return <div>Signing you in…</div>;
          if (error) return <div>{error}</div>;

          return null;
        }

        export default function Page() {
          return (
            <Suspense fallback={<div>Loading…</div>}>
              <AcceptTokenContent />
            </Suspense>
          );
        }
        ```
      </Tab>
    </Tabs>

    This page will:

    * Extract the `ticket` parameter from the URL
    * Authenticate the user using Clerk’s ticket strategy
    * Activate the session on success
    * Redirect the user into your app
  </Step>

  <Step title="Configure Clerk credentials">
    To generate sign-in tickets, Frostline needs access to Clerk credentials in the **demo environment**.

    ### Required credentials

    * **Clerk Secret Key**
    * **User ID**
      (The user the agent will authenticate as during demos)

    You can find:

    * Secret keys in **Clerk Dashboard → API Keys**
    * User IDs in **Clerk Dashboard → Users**

    ***

    ### Demo environment configuration

    Use **Clerk development instance keys** for your demo environment.

    Most Clerk projects automatically include:

    * A **development instance**
    * A **production instance**

    If your app has a deployment using **development Clerk keys**, that deployment is ideal for Frostline demos.

    Why this is recommended:

    * The agent impersonates a non-production user
    * No interaction with real customer data
    * Safer for demos, recordings, and sales calls

    ***

    #### Using production Clerk keys

    There is **no technical restriction** on using production Clerk keys.

    However:

    * The agent will authenticate as a real production user
    * It may interact with real customer data
    * This can interfere with analytics, audits, or live users

    If this behavior is acceptable for your use case, you may proceed — but we strongly recommend development instances when possible.

    ***

    ### Security guarantees

    * The agent **never sees** your Clerk credentials
    * Secrets are stored **encrypted**
    * Credentials are injected only into a secure sandbox
    * Tokens are short-lived and single-use

    This integration relies entirely on Clerk’s official authentication mechanisms and does not weaken your security model.
  </Step>
</Steps>
