Bearer
Authenticate Kernia sessions from an Authorization header instead of a cookie.
The bearer plugin lets non-browser clients — mobile apps, CLIs, service-to-service
calls — authenticate with an Authorization: Bearer <token> header. The token is
the same value Kernia would otherwise set in the better-auth.session_token
cookie, so no extra session store is involved.
Installation
Add the plugin to your server
Add bearer() to your Kernia config. Keep signature enforcement on so only
HMAC-signed tokens are accepted.
import os
from kernia import KerniaOptions
from kernia.auth import init
from kernia.plugins.bearer import bearer
from .db import adapter
auth = init(KerniaOptions(
database=adapter,
secret=os.environ["KERNIA_SECRET"],
base_url=os.environ["KERNIA_BASE_URL"],
plugins=[bearer(require_signature=True)],
))Capture and send the token
Bearer needs no client plugin. After any sign-in, read the token from the
set-auth-token response header and store it, then tell the client to send it
on every request.
import { createAuthClient } from "better-auth/client";
export const authClient = createAuthClient({
baseURL: "/api/auth",
fetchOptions: {
auth: {
type: "Bearer",
token: () => localStorage.getItem("bearer_token") ?? "",
},
},
});Usage
Store the token after sign-in
Kernia mirrors the freshly issued session token back as a set-auth-token
response header (and exposes it via CORS). Grab it in onSuccess:
await authClient.signIn.email(
{ email: "user@example.com", password: "password" },
{
onSuccess: (ctx) => {
const token = ctx.response.headers.get("set-auth-token");
if (token) localStorage.setItem("bearer_token", token);
},
},
);Send the token per request
With the global fetchOptions.auth config above, every call carries the header
automatically. To override for a single request:
await authClient.listSessions({
fetchOptions: {
headers: { Authorization: `Bearer ${token}` },
},
});Options
| Option | Type | Default | Description |
|---|---|---|---|
require_signature | bool | False | When True, only HMAC-signed tokens (<token>.<sig>) are accepted; raw session tokens are rejected. Recommended for production. |
Schema
No tables or fields are added. The plugin resolves the existing core session
table from the header.
A cookie session always takes precedence: if a request carries both a session cookie and a bearer header, the cookie wins and the header is ignored.