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

# Authentication in Deployed Apps

> How Vybe authenticates users and injects identity context into your deployed apps

Every deployed Vybe app is protected by authentication. There are no public URLs — users must be authenticated members of your organization with appropriate access rights before they can reach your app.

This page explains how the authentication flow works and how you can use the current user's identity in your app code.

***

## The authentication flow

When someone visits a deployed app, Vybe handles authentication automatically:

<Steps>
  <Step title="User visits the app URL">
    The user navigates to your deployed app at `<app-slug>-<org-slug>.vybe.build`.
  </Step>

  <Step title="Vybe checks authentication">
    The Vybe middleware checks whether the user has an active session (a valid authentication cookie).
  </Step>

  <Step title="Redirect to login (if needed)">
    If the user is not authenticated, they are redirected to the Vybe login page. After signing in, they are sent back to the original app URL.
  </Step>

  <Step title="Access check">
    Once authenticated, Vybe verifies that the user has access to this specific app based on the app's [access level](/teams/app-access) and any user-level grants.
  </Step>

  <Step title="Token injection">
    If the user passes the access check, Vybe mints a short-lived Vybe User Token (VUT) and injects it — along with user identity headers — into the request before forwarding it to your app.
  </Step>

  <Step title="App receives the request">
    Your app receives the request with the user's identity context available in the request headers.
  </Step>
</Steps>

***

## Identifying the current user

When a request reaches your app, the current user's email is available in the request headers. You can use this to personalize the app experience, filter data, or implement user-specific logic.

### In an API route

```typescript theme={null}
// app/api/my-tasks/route.ts
import { sql } from '@/lib/db';

export async function GET(request: Request) {
  const userEmail = request.headers.get('x-vybe-user-email');

  const tasks = await sql`
    SELECT * FROM tasks WHERE assignee_email = ${userEmail}
  `;

  return Response.json(tasks);
}
```

### In a server component

```typescript theme={null}
// app/dashboard/page.tsx
import { headers } from 'next/headers';
import { sql } from '@/lib/db';

export default async function DashboardPage() {
  const headersList = await headers();
  const userEmail = headersList.get('x-vybe-user-email');

  const myProjects = await sql`
    SELECT * FROM projects WHERE owner_email = ${userEmail}
  `;

  return (
    <div>
      <h1>My Projects</h1>
      {myProjects.map((project) => (
        <div key={project.id}>{project.name}</div>
      ))}
    </div>
  );
}
```

<Tip>
  You do not need to build your own login page or session management. Vybe handles all of that for you. Just read the user identity from the request headers.
</Tip>

***

## Two-factor request authentication

When your app makes API calls to Vybe services (for example, to access integration data or run data queries), the request is authenticated with two credentials:

| Credential                    | Purpose             | How it is provided                                  |
| ----------------------------- | ------------------- | --------------------------------------------------- |
| **`VYBE_SERVER_SECRET`**      | Identifies the app  | Injected as an environment variable at deployment   |
| **`x-vybe-user-token`** (VUT) | Identifies the user | Injected as a request header by the Vybe middleware |

* **App-level resources** (like shared integration connections) require only the server secret.
* **User-level resources** (like a user's personal integration account) require both the server secret and the VUT.

This two-factor approach ensures that API calls are both app-authorized and user-authorized.

***

## How this differs from traditional auth

In a traditional web app, you would build a login page, manage sessions, store user credentials, and handle password resets. In Vybe, all of this is handled by the platform:

| Concern            | Traditional App                  | Vybe App                                              |
| ------------------ | -------------------------------- | ----------------------------------------------------- |
| Login page         | You build it                     | Vybe provides it                                      |
| Session management | You implement it                 | Vybe handles it                                       |
| User identity      | You query your database          | You read request headers                              |
| Access control     | You implement middleware         | Vybe enforces it before your app receives the request |
| Token management   | You generate and validate tokens | Vybe mints and validates the VUT automatically        |

<Note>
  Apps cannot be accessed publicly. All users must be authenticated members of your organization with appropriate access rights. There is no way to make a Vybe app publicly accessible.
</Note>

***

## Common patterns

### Personal dashboard

Build an app where each user sees only their own data:

```typescript theme={null}
export async function GET(request: Request) {
  const userEmail = request.headers.get('x-vybe-user-email');

  const myMetrics = await sql`
    SELECT * FROM metrics WHERE user_email = ${userEmail}
  `;

  return Response.json(myMetrics);
}
```

### Role-based content

Combine user identity with your own role data to show different content:

```typescript theme={null}
export async function GET(request: Request) {
  const userEmail = request.headers.get('x-vybe-user-email');

  const user = await sql`
    SELECT role FROM app_users WHERE email = ${userEmail}
  `;

  if (user[0]?.role === 'manager') {
    const teamData = await sql`SELECT * FROM team_metrics`;
    return Response.json(teamData);
  }

  const personalData = await sql`
    SELECT * FROM metrics WHERE user_email = ${userEmail}
  `;
  return Response.json(personalData);
}
```

***

## What is next

* Learn about secrets and encryption: [Secrets & Encryption](/security/secrets-and-encryption)
* Control who can access your apps: [App Access Levels](/teams/app-access)
