Better Auth Sinatra

Sinatra adapter for Better Auth Ruby. This package is a thin integration around the framework-agnostic better_auth Rack core.

Installation

gem "better_auth-sinatra"
bundle install

Setup

require "sinatra/base"
require "better_auth/sinatra"

class App < Sinatra::Base
  register BetterAuth::Sinatra

  better_auth at: "/api/auth" do |config|
    config.secret = ENV.fetch("BETTER_AUTH_SECRET")
    config.base_url = ENV.fetch("BETTER_AUTH_URL")
    config.database = ->(options) {
      BetterAuth::Adapters::Postgres.new(options, url: ENV.fetch("DATABASE_URL"))
    }
    config.email_and_password = {enabled: true}
    config.plugins = []
  end

  get "/dashboard" do
    require_authentication
    current_user.fetch("email")
  end
end

The extension mounts the core Rack app at /api/auth by default. The mount path cannot be /, because that would capture every Sinatra route before the app can handle it. The core app still owns routes such as /ok, /sign-up/email, /sign-in/email, and plugin endpoints.

better_auth at: sets the path prefix that Better Auth uses as its core base_path. The adapter supports two common Rack mount patterns:

  • Natural Sinatra nesting: mount the Sinatra app under a parent Rack::URLMap, for example at /api, and configure better_auth at: "/auth". Auth routes are available at /api/auth/*.
  • Shared auth mount: mount the Sinatra app itself at the same path as auth, for example /api/auth, and configure better_auth at: "/api/auth". The adapter reconstructs the logical path from Rack SCRIPT_NAME and PATH_INFO.

When using reverse proxies, Rack::URLMap, or another parent app, make sure the PATH_INFO visible to Sinatra still aligns with the configured auth prefix. SCRIPT_NAME handling depends on the Rack server and mount stack, so verify redirect URLs and cookie paths in integration tests when mounting below a sub-path.

Helpers

  • current_session
  • current_user
  • authenticated?
  • require_authentication

require_authentication halts with 401 when no Better Auth user is present. Requests that prefer JSON receive the same JSON error shape used by the core router.

Sinatra helpers resolve sessions through the core get-session API path, so Better Auth plugin hooks that affect session lookup, such as the bearer plugin, run for current_user and require_authentication. Helper session lookup may emit Better Auth Set-Cookie headers when stale cookies need to be cleared or session cookies need to be refreshed.

Rake Tasks

Load tasks from your app Rakefile:

require "better_auth/sinatra/tasks"

Available tasks:

rake better_auth:install
rake better_auth:generate:migration
rake better_auth:migrate
rake better_auth:routes

better_auth:install creates config/better_auth.rb. SQL migrations are generated under db/better_auth/migrate.

Database Notes

Sinatra does not include a Rails-style database layer or migration command. This adapter uses Better Auth core SQL adapters for migrations. Set BETTER_AUTH_DIALECT=postgres, mysql, or sqlite when generating SQL.

Generated SQL should keep one statement per line ending with ;. The migration runner handles simple single-line multi-statement files, but hand-edited SQL with semicolons inside string literals can confuse the splitter. DDL rollback behavior depends on the database, so back up production data before migrating.

ActiveRecord-backed Sinatra migrations are not supported yet. Apps that already use sinatra-activerecord can still configure Better Auth manually, but the v1 Rake tasks do not emit ActiveRecord migrations.

Development

cd packages/better_auth-sinatra
rbenv exec bundle exec rspec
RUBOCOP_CACHE_ROOT=/private/var/folders/7x/jrsz946d2w73n42fb1_ff5000000gn/T/rubocop_cache_sinatra rbenv exec bundle exec standardrb