Cookies
Better Auth Ruby uses Rack-compatible Set-Cookie headers. The main session cookie is signed or encrypted according to your session configuration.
Cookie Prefix
Set a custom prefix for Better Auth cookies:
auth = BetterAuth.auth(
secret: ENV.fetch("BETTER_AUTH_SECRET"),
advanced: {
cookie_prefix: "my-app"
}
)This changes names such as better-auth.session_token to my-app.session_token.
Secure deployments may use the secure cookie prefix automatically when secure cookies are enabled and the cookie attributes allow it.
Custom Cookies
Override individual cookie attributes with advanced.cookies.
auth = BetterAuth.auth(
secret: ENV.fetch("BETTER_AUTH_SECRET"),
advanced: {
cookies: {
session_token: {
name: "session",
attributes: {
http_only: true,
secure: true,
same_site: "lax",
path: "/"
}
}
}
}
)Endpoint and plugin code can also create request-local cookies:
BetterAuth::Endpoint.new(path: "/theme", method: "POST") do |ctx|
ctx.set_cookie("theme", "dark", same_site: "lax", path: "/")
ctx.json({status: true})
endCross Subdomain Cookies
Enable cross-subdomain cookies when the app and API share a parent domain.
auth = BetterAuth.auth(
base_url: "https://api.example.com/api/auth",
trusted_origins: ["https://app.example.com"],
advanced: {
cross_subdomain_cookies: {
enabled: true,
domain: ".example.com"
}
}
)The cookie domain must be a parent domain shared by both hosts.
Secure Cookies
Use secure cookies in production.
auth = BetterAuth.auth(
secret: ENV.fetch("BETTER_AUTH_SECRET"),
advanced: {
use_secure_cookies: true
}
)Secure cookies are sent with Secure, HttpOnly, and the configured SameSite behavior. Local development can keep use_secure_cookies false when serving over plain HTTP.
Safari, ITP, And Cross-Domain Setups
Safari's tracking protections can block third-party cookies when the auth server is on a separate site. Prefer one of these layouts:
- Put the app and auth server behind the same site, such as
app.example.comandapi.example.com, then use cross-subdomain cookies. - Proxy auth requests through the application origin, such as
/api/auth. - Use a shared parent domain and HTTPS everywhere.
Using A Reverse Proxy
Proxy /api/auth/* from the frontend origin to the Ruby auth server.
location /api/auth/ {
proxy_pass http://ruby-auth:3000/api/auth/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
}If your app trusts proxy headers for base URL inference, configure trusted proxy headers intentionally.
auth = BetterAuth.auth(
base_url: ->(request) { "https://#{request.host}/api/auth" },
advanced: {
trusted_proxy_headers: true
}
)Example With Netlify
Configure a Netlify rewrite from the frontend origin to the Ruby auth server:
[[redirects]]
from = "/api/auth/*"
to = "https://api.example.com/api/auth/:splat"
status = 200
force = trueExample With Vercel
Configure a Vercel rewrite:
{
"rewrites": [
{
"source": "/api/auth/:path*",
"destination": "https://api.example.com/api/auth/:path*"
}
]
}Using A Shared Parent Domain
For app.example.com and api.example.com, configure:
advanced: {
use_secure_cookies: true,
cross_subdomain_cookies: {
enabled: true,
domain: ".example.com"
}
}Keep callback URLs and trusted origins aligned with the public hostnames users actually visit.