# How to Add a Custom Authentication Provider to NextAuth.js in prompts.chat

> Learn to add a custom authentication provider to NextAuth.js with this guide. Implement AuthPlugin, register it, and enable it in prompts.config.ts for seamless integration.

- Repository: [Fatih Kadir Akın/prompts.chat](https://github.com/f/prompts.chat)
- Tags: how-to-guide
- Published: 2026-04-02

---

**You add a custom authentication provider to NextAuth.js in prompts.chat by implementing the `AuthPlugin` interface, registering it via `registerAuthPlugin()` in the auth plugin index, and enabling it in the `auth.providers` array inside [`prompts.config.ts`](https://github.com/f/prompts.chat/blob/main/prompts.config.ts).**

The prompts.chat application employs a **plugin-based architecture** for authentication that wraps NextAuth.js. Rather than editing core authentication logic directly, you extend the system through the `AuthPlugin` interface defined in [`src/lib/plugins/types.ts`](https://github.com/f/prompts.chat/blob/main/src/lib/plugins/types.ts), enabling type-safe registration of OAuth providers, credentials providers, or custom authentication methods without touching the underlying NextAuth configuration.

## Understanding the Plugin Architecture

The authentication system in prompts.chat decouples provider definitions from the core application through three key components:

- **`AuthPlugin` interface** (`src/lib/plugins/types.ts#L7-L14`): Defines the contract every provider must implement, requiring an `id`, `name`, and a `getProvider()` function that returns a NextAuth provider configuration.
- **`PluginRegistry`** (`src/lib/plugins/registry.ts#L13-L16`): A global store that holds all registered auth plugins and retrieves them by their `id` during configuration.
- **`initializePlugins()`** (`src/lib/plugins/index.ts#L23-L31`): Bootstraps the system by calling `registerBuiltInAuthPlugins()` and then filtering the registry against the `providers` array defined in [`prompts.config.ts`](https://github.com/f/prompts.chat/blob/main/prompts.config.ts) to load only enabled plugins.

This architecture ensures that adding a new OAuth provider—such as Discord, Slack, or a custom SAML solution—requires only creating a new plugin file and updating the configuration registry.

## Step-by-Step: Add a Custom Authentication Provider

### Step 1: Create the Provider Plugin

Create a new file in `src/lib/plugins/auth/` that implements the `AuthPlugin` interface. The `getProvider()` method must return a valid NextAuth provider configuration.

The following example implements a Discord provider:

```typescript
// src/lib/plugins/auth/discord.ts
import Discord from "next-auth/providers/discord";
import type { AuthPlugin } from "../types";

export const discordPlugin: AuthPlugin = {
  id: "discord",
  name: "Discord",
  getProvider: () =>
    Discord({
      clientId: process.env.DISCORD_CLIENT_ID!,
      clientSecret: process.env.DISCORD_CLIENT_SECRET!,
      // Map Discord profile to the shape used by prompts.chat
      profile(profile) {
        return {
          id: profile.id,
          name: profile.username,
          email: profile.email,
          image: profile.avatar
            ? `https://cdn.discordapp.com/avatars/${profile.id}/${profile.avatar}.png`
            : null,
        };
      },
    }),
};

```

### Step 2: Register the Plugin

Import your new plugin into [`src/lib/plugins/auth/index.ts`](https://github.com/f/prompts.chat/blob/main/src/lib/plugins/auth/index.ts) and register it using `registerAuthPlugin()`:

```typescript
// src/lib/plugins/auth/index.ts
import { registerAuthPlugin } from "../registry";
import { credentialsPlugin } from "./credentials";
import { googlePlugin } from "./google";
import { azurePlugin } from "./azure";
import { githubPlugin } from "./github";
import { applePlugin } from "./apple";
import { discordPlugin } from "./discord";   // <-- new import

export function registerBuiltInAuthPlugins(): void {
  registerAuthPlugin(credentialsPlugin);
  registerAuthPlugin(googlePlugin);
  registerAuthPlugin(azurePlugin);
  registerAuthPlugin(githubPlugin);
  registerAuthPlugin(applePlugin);
  registerAuthPlugin(discordPlugin);      // <-- registration
}

```

The `registerAuthPlugin()` function adds your plugin to the global registry, making it available for activation.

### Step 3: Enable in Configuration

Add the provider's `id` to the `auth.providers` array in [`prompts.config.ts`](https://github.com/f/prompts.chat/blob/main/prompts.config.ts):

```typescript
// prompts.config.ts
export default defineConfig({
  // …
  auth: {
    providers: ["github", "google", "apple", "discord"], // <-- enable Discord
    allowRegistration: false,
  },
  // …
});

```

When the application initializes, `getConfiguredAuthPlugins()` reads this array and instantiates only the providers listed, keeping the NextAuth configuration lean and performant.

### Step 4: Use in Components (Optional)

Invoke the provider using NextAuth's `signIn` method with the plugin `id`:

```tsx
"use client";

import { useSession, signIn, signOut } from "next-auth/react";

export function AuthButtons() {
  const { data: session } = useSession();

  return (
    <div className="flex gap-2">
      {session ? (
        <button onClick={() => signOut()}>Sign out</button>
      ) : (
        <button onClick={() => signIn("discord")}>Sign in with Discord</button>
      )}
    </div>
  );
}

```

## Summary

- **Implement `AuthPlugin`**: Create a new file in `src/lib/plugins/auth/` that exports an object with `id`, `name`, and a `getProvider()` function returning a NextAuth provider.
- **Register globally**: Import and pass your plugin to `registerAuthPlugin()` inside [`src/lib/plugins/auth/index.ts`](https://github.com/f/prompts.chat/blob/main/src/lib/plugins/auth/index.ts).
- **Activate via config**: Add the plugin's `id` to the `auth.providers` array in [`prompts.config.ts`](https://github.com/f/prompts.chat/blob/main/prompts.config.ts).
- **Type-safe resolution**: The plugin system automatically resolves enabled providers at runtime without modifying core authentication code.

## Frequently Asked Questions

### What interface must a custom authentication provider implement?

Your provider must implement the `AuthPlugin` interface defined in [`src/lib/plugins/types.ts`](https://github.com/f/prompts.chat/blob/main/src/lib/plugins/types.ts). This requires three properties: a unique string `id`, a display `name`, and a `getProvider()` function that returns a NextAuth provider configuration object (such as an OAuth provider from `next-auth/providers`).

### Do I need to modify core files to add a new authentication provider?

No. You only need to create a new plugin file, import it into [`src/lib/plugins/auth/index.ts`](https://github.com/f/prompts.chat/blob/main/src/lib/plugins/auth/index.ts), and register it with `registerAuthPlugin()`. The core authentication initialization logic in [`src/lib/plugins/index.ts`](https://github.com/f/prompts.chat/blob/main/src/lib/plugins/index.ts) dynamically loads enabled providers from the registry without requiring changes to its source code.

### How does prompts.chat determine which providers are active?

During initialization, the `getConfiguredAuthPlugins()` function in [`src/lib/plugins/index.ts`](https://github.com/f/prompts.chat/blob/main/src/lib/plugins/index.ts) reads the `auth.providers` array from [`prompts.config.ts`](https://github.com/f/prompts.chat/blob/main/prompts.config.ts). It filters the global `PluginRegistry` to return only the plugins whose `id` values match the configuration array, ensuring only explicitly enabled providers are passed to NextAuth.

### Can I customize how OAuth profile data maps to the user model?

Yes. When defining your plugin's `getProvider()` function, include a `profile()` callback inside the provider configuration (as shown in the Discord example). This callback receives the raw OAuth profile and should return an object matching the user shape expected by prompts.chat, typically containing `id`, `name`, `email`, and `image` fields.