# How to Use the Authentication Skill in Agent-Native: Configuration and Implementation Guide

> Learn to use the Agent-Native authentication skill for secure session management. This guide covers configuration and implementation for browser and programmatic clients.

- Repository: [Builder.io/agent-native](https://github.com/BuilderIO/agent-native)
- Tags: how-to-guide
- Published: 2026-06-28

---

**The authentication skill in Agent-Native wraps Better Auth to provide secure, unified session management for both browser users and programmatic MCP clients, exposing a standard `AuthSession` interface accessible via `useSession()` in React components and `getSession()` in server routes.**

Agent-Native is an open-source framework from BuilderIO that ships with a dedicated authentication skill designed to handle identity across multiple contexts. This skill eliminates the need to manually integrate authentication libraries by providing a pre-configured Better Auth wrapper that supports email/password, social providers, and custom third-party authentication systems.

## How the Authentication Skill is Wired Into the App

The authentication system initializes automatically when the Nitro server boots. The core server package exports `createAuthPlugin` and the shortcut `autoMountAuth` from [`packages/core/src/server/index.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/server/index.ts), which the generated server imports as its first initialization step.

```typescript
// packages/core/src/server/index.ts
export { createAuthPlugin, defaultAuthPlugin } from "./auth-plugin.js";

```

When the server starts, the plugin mounts Better Auth routes under `/_agent-native/auth/ba/*` and maintains legacy compatibility endpoints at `/session`, `/login`, `/register`, and `/logout`. This automatic mounting happens without requiring manual route registration in your application code.

## Authentication Modes

The skill supports three distinct authentication strategies that all resolve to the same `AuthSession` object:

- **Default (Better Auth)**: Email and password authentication with optional social providers (Google, GitHub). This mode displays an onboarding page on first visit and stores sessions via HTTP-only cookies.
- **Remote MCP OAuth**: OAuth 2.1 with PKCE for MCP-enabled hosts like Claude Code. Clients receive a `WWW-Authenticate` challenge from the MCP endpoint and complete the flow without prior tokens.
- **Custom (`getSession`)**: Bring-your-own-auth integration that accepts a custom callback to verify sessions from Clerk, Auth0, Firebase, or any other provider.

All three modes normalize identity data into a single `AuthSession` structure that downstream code can use for authorization decisions.

## Session Shape and Types

Every authentication method returns a standardized session object defined in the documentation. The interface lives in `packages/core/docs/content/authentication.mdx` and includes organization-scoping fields for multi-tenant applications.

```typescript
interface AuthSession {
  email: string;          // primary identifier
  userId?: string;        // Better Auth user ID
  token?: string;         // session JWT
  name?: string;          // display name from the provider
  image?: string;         // profile picture URL
  orgId?: string;         // active organization ID
  orgRole?: string;       // role within the active org
}

```

The `orgId` and `orgRole` fields enable built-in multi-tenant authorization without requiring separate database queries.

## Accessing the Session in the UI

Client-side components consume session data through the `useSession` hook exported from `@agent-native/core/client`. This hook subscribes to server-side session changes via the framework's real-time sync layer and automatically re-renders when authentication state changes.

```tsx
import { useSession } from "@agent-native/core/client";

export function MyComponent() {
  const { session, isLoading } = useSession();

  if (isLoading) return <p>Loading…</p>;
  if (!session) return <p>Not signed in</p>;

  return <p>Hello, {session.email}</p>;
}

```

The hook handles loading states and null sessions consistently across the application, eliminating the need for manual fetch logic or context providers.

## Server-Side Session Access

Server routes and API handlers use `getSession` imported from `@agent-native/core/server` to verify identity on the backend. This function parses the session cookie from the incoming request event and returns the validated `AuthSession` object or null.

```typescript
import { getSession } from "@agent-native/core/server";

export default defineEventHandler(async (event) => {
  const sess = await getSession(event);
  return { user: sess?.email ?? null };
});

```

According to the implementation in [`packages/core/src/server/auth.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/server/auth.ts), this helper manages cookie parsing, token verification, and caching to minimize repeated validation overhead.

## Sign-In Flow with Return URLs

Public pages that require authentication can redirect users to the standardized sign-in endpoint while preserving the current location. The skill provides `/_agent-native/sign-in` with a `return` query parameter that validates same-origin paths to prevent open-redirect vulnerabilities.

```tsx
import { Button } from "@/components/ui/button";

function SignInCta() {
  const onClick = () => {
    const ret = window.location.pathname + window.location.search;
    window.location.href = `/_agent-native/sign-in?return=${encodeURIComponent(ret)}`;
  };
  
  return <Button onClick={onClick}>Sign in</Button>;
}

```

After successful authentication, the user returns automatically to the original page.

## Cookie Realms and Session Isolation

Agent-Native automatically scopes session cookies based on the deployment configuration to ensure security across different hosting patterns:

| Deployment Shape | Cookie Realm Behavior |
|------------------|---------------------|
| Standalone app | `an_<slug>` (stable in production) |
| Workspace mode (`AGENT_NATIVE_WORKSPACE=1`) | Shared across all workspace apps |
| Same-database subdomains | Shared when `COOKIE_DOMAIN` environment variable is set |
| First-party hosted (`*.agent-native.com`) | Isolated per app by default |

This isolation prevents session leakage between applications while allowing intentional sharing in workspace or subdomain scenarios.

## Environment Variables for Configuration

The authentication skill recognizes several environment variables defined in `packages/core/docs/content/authentication.mdx` that control behavior without code changes:

- `BETTER_AUTH_SECRET`: Signing key for Better Auth (auto-generated if omitted)
- `AUTH_SKIP_EMAIL_VERIFICATION`: Set to `1` to disable verification in QA/preview environments
- `AUTH_DISABLED`: Set to `true` to run every request as a shared user (development only)
- `COOKIE_DOMAIN`: Enables shared cookies across subdomains
- `GOOGLE_SIGN_IN_CLIENT_ID` / `GOOGLE_SIGN_IN_CLIENT_SECRET`: Primary Google OAuth credentials
- `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`: GitHub OAuth credentials
- `ACCESS_TOKEN` / `ACCESS_TOKENS`: Static bearer tokens for MCP client authentication

Social provider credentials automatically enable the corresponding login buttons in the default Better Auth UI.

## Custom Authentication (Bring Your Own Auth)

To replace Better Auth with a custom provider, export a plugin that supplies a `getSession` callback. The implementation in [`packages/core/src/server/auth-plugin.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/server/auth-plugin.ts) accepts this callback and integrates it into the request lifecycle.

```typescript
// server/plugins/auth.ts
import { createAuthPlugin } from "@agent-native/core/server";

export default createAuthPlugin({
  getSession: async (event) => {
    const session = await myAuthProvider.verify(event);
    if (!session) return null;
    return { email: session.email };
  },
  publicPaths: ["/api/webhooks"],   // optional: routes that bypass auth
});

```

This pattern allows gradual migration from existing auth systems or integration with enterprise identity providers while retaining Agent-Native's session interface.

## Typical Template Usage

Every generated template includes a [`server/plugins/auth.ts`](https://github.com/BuilderIO/agent-native/blob/main/server/plugins/auth.ts) file that re-exports `createAuthPlugin` with default options. This file serves as the extension point for per-application customization.

```typescript
// templates/mail/server/plugins/auth.ts
import { createAuthPlugin } from "@agent-native/core/server";

export default createAuthPlugin({});

```

As implemented in the template files, this structure makes it trivial to customize authentication logic without modifying core framework code.

## Summary

- The **authentication skill** mounts automatically via `createAuthPlugin` in [`packages/core/src/server/index.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/server/index.ts), handling routes under `/_agent-native/auth/ba/*`.
- **Three authentication modes** (Better Auth, MCP OAuth, custom `getSession`) all resolve to a standard `AuthSession` interface with email, userId, and organization fields.
- Use **`useSession()`** in React components and **`getSession(event)`** in server handlers to access identity data.
- Configure social providers and security settings via **environment variables** like `GOOGLE_SIGN_IN_CLIENT_ID` and `COOKIE_DOMAIN`.
- Implement **custom authentication** by providing a `getSession` callback to `createAuthPlugin` in [`server/plugins/auth.ts`](https://github.com/BuilderIO/agent-native/blob/main/server/plugins/auth.ts).

## Frequently Asked Questions

### How do I access the current user session in a React component?

Import `useSession` from `@agent-native/core/client` and call it inside your component. The hook returns `{ session, isLoading }` where `session` contains the `AuthSession` object with the user's email, name, and organization details, or `null` if unauthenticated. This hook automatically subscribes to real-time session updates.

### Can I use a custom authentication provider instead of Better Auth?

Yes. Create a file at [`server/plugins/auth.ts`](https://github.com/BuilderIO/agent-native/blob/main/server/plugins/auth.ts) that imports `createAuthPlugin` from `@agent-native/core/server` and export the result with a custom `getSession` callback. This callback receives the request event and should return an `AuthSession` object or null, allowing integration with Clerk, Auth0, Firebase, or any other provider.

### What environment variables are required to enable Google or GitHub login?

Set `GOOGLE_SIGN_IN_CLIENT_ID` and `GOOGLE_SIGN_IN_CLIENT_SECRET` for Google authentication, or `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET` for GitHub. These credentials automatically enable the corresponding social login buttons in the default authentication UI. You should also set `BETTER_AUTH_SECRET` in production to ensure secure session signing.

### How does session isolation work across subdomains or workspaces?

Agent-Native automatically scopes cookies based on your deployment configuration. Standalone apps use an isolated cookie (`an_<slug>`), while enabling `AGENT_NATIVE_WORKSPACE=1` creates a shared session across workspace apps. For same-database subdomains, set the `COOKIE_DOMAIN` environment variable to enable shared authentication across your domain.