Configuration
The core of gau
is the createAuth
function, which you use to configure your auth setup. This guide covers all the available options in detail.
Here’s a quick overview of a typical configuration:
import { DrizzleAdapter } from '@rttnd/gau/adapters/drizzle'import { createAuth } from '@rttnd/gau/core'import { GitHub } from '@rttnd/gau/oauth'import { db } from './db'import { Accounts, Users } from './db/schema'
export const auth = createAuth({ adapter: DrizzleAdapter(db, Users, Accounts), providers: [ GitHub({ clientId: process.env.GITHUB_CLIENT_ID, clientSecret: process.env.GITHUB_CLIENT_SECRET, }), ], jwt: { secret: process.env.AUTH_SECRET, },});
adapter
Section titled “adapter”Type:
Adapter
, Required: Yes
The adapter
is responsible for connecting gau
to your database and handling db operations.
See the adapters guide.
providers
Section titled “providers”Type:
OAuthProvider[]
, Required: Yes
This option takes an array of configured OAuth providers that your application will support.
Each provider typically needs a clientId
and clientSecret
.
import { GitHub, Google } from '@rttnd/gau/oauth'
// ...providers: [ GitHub({ clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET!, }), Google({ clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, }),],
You can pass additional provider-specific options using params
.
Check out the OAuth Providers section for a list of available providers and their specific configuration.
profiles
Section titled “profiles”Type:
{ [providerId: string]: { [profileName: string]: { scopes?: string[], redirectUri?: string, params?: Record<string,string> } & ProviderSpecificOverrides } }
Default:{}
Define server-controlled, per-provider profiles
to group auth provider configs.
A profile can:
- Override
scopes
used when building the provider authorization URL - Override the provider
redirectUri
(useful for desktop/mobile custom schemes) - Include provider-specific, strongly typed overrides (e.g.
tenant
,prompt
for Microsoft) - Add arbitrary authorization
params
(appended to the provider auth URL)
Profiles are selected by name at login/link time, either via the client helpers or a ?profile=
query parameter. If an unknown profile is requested, gau
returns 400
.
Example configuration:
import { createAuth } from '@rttnd/gau/core'import { GitHub } from '@rttnd/gau/oauth'
export const auth = createAuth({ providers: [ GitHub({ clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET! }), ], profiles: { github: { // Minimal sign-in with user identity basic: { scopes: ['read:user', 'user:email'] }, // Elevated permissions for repo automation maintainer: { scopes: ['read:user', 'user:email', 'repo', 'read:org'] }, }, },})
Select a profile when starting a flow:
- Client:
auth.signIn('github', { profile: 'maintainer' })
- URL:
GET /api/auth/login/github?profile=maintainer
Security notes:
- Profiles are defined on the server; the client can only choose by name. Unknown names are rejected.
- Use profiles to constrain allowed scope sets, this avoids exposing arbitrary scopes to the client.
- If you use a custom
redirectUri
for desktop/mobile flows, set it in the profile and configuretrustHosts
appropriately for your return hosts. - Avoid putting secrets into
params
— they become part of the URL. - Precedence for settings (when supported by a provider like Microsoft):
- profile override (typed) > query parameter (e.g.
?prompt=...
) > provider default
- profile override (typed) > query parameter (e.g.
Extra params
Section titled “Extra params”Some providers accept extra authorization parameters via the provider config:
GitHub({ clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET!, params: { allow_signup: 'false' },})
Profile params
are merged on top of provider params
for the selected profile.
basePath
Section titled “basePath”Type:
string
, Default:'/api/auth'
Defines the relative path for all authentication API endpoints. You typically don’t need to change this.
The resulting URL is {baseURL}/{basePath}/{provider}
.
If your frontend and backend are on different hosts, look for the baseURL
config in the framework specific guides.
session
Section titled “session”Type:
object
, Default:{}
This object allows you to configure session management.
session.strategy
Section titled “session.strategy”Type:
'auto' | 'cookie' | 'token'
, Default:'auto'
Determines how sessions are handled. See the Session Management guide for a detailed explanation of the different strategies.
These hooks let you customize the OAuth callback lifecycle, see Hooks.
Type:
object
, Default:{}
This object allows you to configure JSON Web Token settings for session management.
jwt.secret
Section titled “jwt.secret”Type:
string
, Required: Yes
The secret used for signing and verifying JWTs.
For HS256
, this can be a simple string. For the default and recommended ES256
, this must be a base64url-encoded PKCS#8 private key. You can generate a valid secret using the CLI:
npx gau secret
pnpm dlx gau secret
yarn dlx gau secret
bunx gau secret
nlx gau secret
jwt.algorithm
Section titled “jwt.algorithm”Type:
'ES256' | 'HS256'
, Default:'ES256'
The signing algorithm to use.
ES256
(ECDSA with P-256 and SHA-256) is the default and recommended algorithm. It uses asymmetric cryptography (a private key to sign, a public key to verify), which is generally more secure than symmetric algorithms like HS256
. HS256
is for backend-only setups, and it’s a bit faster.
jwt.privateKey
Section titled “jwt.privateKey”Type:
CryptoKey
, Required: No
The private key to use for signing JWTs, only with ES256
.
By default, this is derived from jwt.secret
.
jwt.ttl
Section titled “jwt.ttl”Type:
number
, Default:86400
(24 hours)
The default time-to-live for session JWTs, in seconds.
jwt.iss, jwt.aud, and jwt.sub
Section titled “jwt.iss, jwt.aud, and jwt.sub”Type:
string | string[]
Standard JWT claims for “issuer” (iss
) and “audience” (aud
). These are useful in multi-tenant applications or when your API needs to serve different clients. gau
allows you to set default values for them here, and will automatically validate these claims when verifying a token.
cookies
Section titled “cookies”Type:
cookie.SerializeOptions
, Default:{ path: '/', sameSite: 'lax', secure: true, httpOnly: true }
Allows you to customize the options for the session cookie.
You can override the defaults. For example:
cookies: { sameSite: 'strict',},
trustHosts
Section titled “trustHosts”Type:
'all' | string[]
, Default:[]
The trustHosts
option is a crucial security feature that serves two main purposes:
- CSRF Protection: It whitelists origins that are allowed to make
POST
requests (e.g., for signing out) to your auth endpoints. - Open Redirect Prevention: It validates the
redirectTo
URL parameter during a login flow, ensuring users are only redirected to trusted domains after authentication.
The Origin
header of incoming requests and the host of redirect URLs are checked against this list.
-
[]
(Default): Only requests and redirects from/to the same origin as the app are allowed. -
['app.example.com', 'tauri.localhost']
: For multi-domain setups or Tauri apps, you must add the allowed hostnames. -
'all'
: This is a convenient shortcut for development that disables these checks, but it is not recommended for production.
See the Security guide for more details.
Type:
boolean | CORSOptions
, Default:true
Configures Cross-Origin Resource Sharing (CORS) for all auth endpoints.
true
(default): Enables CORS, defaults:allowedOrigins: 'all'
(all origins allowed)allowCredentials: true
(credentials reflected, origin echoed — never*
)allowedHeaders: ['Content-Type', 'Authorization', 'Cookie']
allowedMethods: ['GET', 'POST', 'OPTIONS']
false
: Disables CORS completely (no CORS headers are added).CORSOptions
: Manually configure CORS headers.
Options:
allowedOrigins: 'all'
: Allow any origin. WhenallowCredentials: false
, the response usesAccess-Control-Allow-Origin: *
. When credentials are enabled, the requesting origin is echoed.allowedOrigins: 'trust'
: Reuses yourtrustHosts
list. IftrustHosts: 'all'
, every origin is allowed (origin echoed).allowedOrigins: string[]
: Provide an explicit allow-list. Items can be full origins (https://app.example.com
), bare hostnames (app.example.com
), host:port, or*
(which allows any origin but still echoes the caller instead of using*
).allowCredentials
: Toggles theAccess-Control-Allow-Credentials
header. Iffalse
andallowedOrigins === 'all'
, wildcard*
is used; otherwise origin is echoed without the credentials header.allowedHeaders
: Array of request headers you want to allow (sent as a comma‑separated list).allowedMethods
: HTTP methods allowed for preflight / actual requests.exposeHeaders
: Extra response headers accessible to the browser (setsAccess-Control-Expose-Headers
).maxAge
: Seconds browsers may cache the preflight response.
autoLink
Section titled “autoLink”Type:
'verifiedEmail' | 'always' | false
, Default:'verifiedEmail'
Controls how gau
does automatic account linking.
Read the Account Linking guide for a full explanation.
'verifiedEmail'
(Default): If an existing user signs in with a new OAuth provider,gau
will try very hard to get a verified email address from the provider, then it will automatically link the new account to that existing user. Otherwise, it will create a new user.'always'
: Links accounts if the email addresses match, regardless of whether the email is verified by the provider.false
: Disables automatic account linking. A new user will be created for each new OAuth provider sign-in, even if the email already exists.
allowDifferentEmails
Section titled “allowDifferentEmails”Type:
boolean
, Default:true
Controls whether a user can manually link a provider whose primary email differs from the user’s current primary email.
true
(default): Allow linking even if the emails differ.false
: Reject manual linking with a 400 error when the emails differ.
This is only enforced during manual linking; it does not affect the auto-link checks above.
updateUserInfoOnLink
Section titled “updateUserInfoOnLink”Type:
boolean
, Default:false
When enabled, during manual linking gau will update the user’s profile fields from the new provider (e.g. name
, image
).
If the provider’s email matches the user’s current email and is verified, gau will also set emailVerified: true
.
Type:
object
, Default:{}
This object allows you to configure role-based access control.
roles.defaultRole
Section titled “roles.defaultRole”Type:
string
, Default:'user'
The default role assigned to newly created users.
roles.resolveOnCreate
Section titled “roles.resolveOnCreate”Type:
(context: { providerId: string, profile: any, request: Request }) => string | undefined
, Required: No
A function to dynamically resolve the role for a new user at creation time. Return undefined
to fall back to defaultRole
.
roles.adminRoles
Section titled “roles.adminRoles”Type:
string[]
, Default:['admin']
An array of role names that are considered admin roles for helper predicates.
roles.adminUserIds
Section titled “roles.adminUserIds”Type:
string[]
, Default:[]
An array of user IDs that are always treated as admin for helper predicates.
For a full guide, see Role-Based Access Control.
linkOnly
Section titled “linkOnly”Type:
boolean
Default:false
When enabled the provider or the profile can only be used for linking to an existing user account, not for signing in or signing up.
- Provider level: pass
linkOnly: true
to the provider config. - Profile level: set
linkOnly: true
on a specific profile.
When a user completes an OAuth callback without an existing session for a link-only provider/profile, gau returns a 400 with a friendly message.