Skip to main content
Corsair only differs between modes in one place: the surfaces that need a public URL (OAuth callbacks, approval pages). Everything else (calling APIs, withTenant, hooks, the database layer, encryption) is identical.
  • Manual is the default. You host the connect, callback, and approval surfaces yourself. Fully featured, no external dependency.
  • Hub is an optional upgrade. Corsair hosts those surfaces for you. It stores none of your credentials. See Hub overview.
The picker is config on createCorsair: pass manual or hub.

What each mode asks you to build

SurfaceManual (you host it)Hub (Corsair hosts it)
OAuth callback URLOne per environment, registered with each providerOne callback for development and production
Connect pageYou build it (resolve the signed state, redirect to provider)Hosted by Hub
OAuth callback routeYou build it (oauthCallback exchanges the code)Hosted by Hub, result delivered to you
Approval UIYou build a review page and wire onApprovalRequiredHosted approve/deny page, link auto-generated
Missing-connection errorYou craft the message and build the connect pageYou call createLink() for a sign-in link; Hub hosts the connect page
Credential storageYour databaseYour database (Hub stores nothing in both modes)
The last row is the key one: credential storage never changes. Tokens live in your database under your KEK in both modes. Hub is a relay for the public-URL surfaces, not a vault.

Config side by side

corsair.ts
export const corsair = createCorsair({
    plugins: [github(), slack()],
    database: db,
    kek: process.env.CORSAIR_KEK!,
    manual: {
        baseUrl: `${appUrl}/connect`,
        redirectUri: `${appUrl}/api/oauth/callback`,
        approvalBaseUrl: `${appUrl}/approve`,
        onApprovalRequired: ({ approvalUrl }) =>
            `Approval required. Visit ${approvalUrl} then retry.`,
    },
});
You also build the connect page, the OAuth callback route, and the approval review page. See OAuth Process for the full implementation.
Both modes use the same createLink API to start a connect flow. Only where the returned connectUrl points changes. See Connect / OAuth.

The connect flow in each mode

In both lanes the tokens end up in the same place: your database. Hub removes the two pages you would otherwise build, nothing more.

Choosing a mode

Choose manual when you want full control of the connect and approval surfaces, need everything inside your own domain, or cannot add an external hop in the auth path. Choose hub when you would rather not build and host those surfaces, or when you want one provider callback to cover local development and production at once. You can also mix: connect through Hub while keeping approvals manual, or the reverse. The two surfaces are configured independently.

What’s next

Hub overview

What Hub is and the relay / no-storage model.

Environments

Development vs production keys and delivery.

OAuth Process

The full manual-mode implementation with security best practices.

Connect / OAuth

The unified createLink API and its error codes.

Permissions

Approval policies, modes, and the review flow.