Skip to content

plugin-auth: Add bearer() plugin support for cross-origin token-based auth #1172

@hotlong

Description

@hotlong

Problem

When the frontend (e.g. localhost:5173) connects to an API on a different origin (e.g. demo.objectstack.ai), session cookies are blocked by the browser due to third-party cookie restrictions. This means:

  • Users can sign in successfully
  • But refreshing the page loses the session (cookie not sent cross-origin)
  • Mobile clients (iOS/Android) also cannot use cookie-based auth

This is the standard behavior of modern browsers (Chrome, Safari, Firefox all block third-party cookies).

Solution

Add the better-auth bearer() server-side plugin to @objectstack/plugin-auth, so the server can:

  1. Accept Authorization: Bearer <token> headers (converts to session cookie internally)
  2. Expose the session token via set-auth-token response header (so the client can store it)

This is how Salesforce, Notion, Supabase, and all mobile apps handle auth — token-based, not cookie-based.

Required Changes

1. @objectstack/plugin-auth — Add bearer plugin

In buildPluginList(), always include the bearer() plugin from better-auth/plugins/bearer:

import { bearer } from 'better-auth/plugins/bearer';

buildPluginList() {
  const plugins = [
    bearer(), // Always enabled — supports cross-origin and mobile clients
  ];
  // ... existing organization, twoFactor, magicLink plugins
  return plugins;
}

2. CORS configuration

Ensure the server's CORS config includes:

  • Access-Control-Allow-Headers: Authorization
  • Access-Control-Expose-Headers: set-auth-token

The bearer plugin automatically adds set-auth-token to Access-Control-Expose-Headers on responses, but the server must also allow the Authorization request header in CORS preflight responses.

3. trustedOrigins configuration

For cross-origin deployments, AuthPlugin config should support specifying trusted origins:

new AuthPlugin({
  secret: '...',
  trustedOrigins: ['http://localhost:5173', 'https://console.example.com'],
})

Client Side (already implemented in object-ui)

The @object-ui/auth package has been updated in object-ui to:

  • Store session tokens in localStorage via TokenStorage
  • Inject Authorization: Bearer <token> on all requests via createBearerFetch
  • Capture rotated tokens from set-auth-token response header
  • Clear tokens on sign-out

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions