Plugins

OAuth Proxy

Keep OAuth client secrets on the server during SPA and preview-deploy flows.

OAuth proxy lets a browser app start a provider sign-in without ever holding the client secret. Kernia stores the provider config, signs the state, exchanges the authorization code server-side, and issues the session. It also rewrites redirect URLs so a single registered callback works across preview deployments.

Installation

Add the plugin to your server

Pass oauth_proxy() to your Kernia config. The optional SPA helper flow takes a providers map and a redirect_uri that exactly matches what you registered at the provider.

auth.py
import os

from kernia import KerniaOptions
from kernia.auth import init
from kernia.plugins.oauth_proxy import OAuthProxyOptions, oauth_proxy

from .db import adapter
from .providers import google_provider

auth = init(KerniaOptions(
    database=adapter,
    secret=os.environ["KERNIA_SECRET"],
    base_url=os.environ["KERNIA_BASE_URL"],
    plugins=[
        oauth_proxy(OAuthProxyOptions(
            providers={"google": google_provider},
            redirect_uri="https://api.example.com/api/auth/oauth-proxy/callback",
        )),
    ],
))

Add the client plugin

auth-client.ts
import { createAuthClient } from "better-auth/client";
import { oAuthProxyClient } from "better-auth/client/plugins";

export const authClient = createAuthClient({
  baseURL: "/api/auth",
  plugins: [oAuthProxyClient()],
});

Usage

Once installed, OAuth proxy works transparently behind your normal social sign-in calls: the client requests an authorization URL, Kernia returns it with signed state, and the secret-bearing code exchange happens server-side.

await authClient.signIn.social({
  provider: "google",
  callbackURL: "/dashboard",
});

The browser is redirected to the provider and back through /api/auth/oauth-proxy/callback, where Kernia validates the signed state, exchanges the code, creates the user and session, and redirects to your app.

Options

Set on OAuthProxyOptions:

OptionTypeDefaultDescription
providersdict[str, OAuthProvider]NoneProviders exposed through the SPA helper flow.
redirect_uristrNoneCallback URL registered at the provider. Must match exactly.
success_callback_urlstrNoneDefault app URL to return to after sign-in.
trusted_providerstuple[str, ...]()Providers allowed to skip extra origin checks.
disable_sign_upboolFalseReject proxy sign-ins for users with no existing account.
max_ageint600Max age (seconds) of an encrypted passthrough payload.
secretstrNoneDedicated encryption secret for proxy payloads. Falls back to the global secret.

Schema

No new tables. Provider accounts are written to the core account table.

The redirect_uri must be registered at the provider character-for-character. A trailing slash or scheme mismatch is the most common cause of failed callbacks.