Documentation
¶
Overview ¶
Package warden is a pure-Go (no cgo) model of the engine of Ruby's Warden Rack authentication middleware, faithful to the observable behaviour of the `warden` gem (as bundled with MRI-4.0.5-era Rack apps).
Warden is not an authentication *system*; it is the plumbing that lets a Rack app run pluggable authentication strategies, cache the authenticated user per scope in the session, and hand control to a failure application when authentication is required but not satisfied. This package models that plumbing — the deterministic, interpreter-independent control flow — while leaving the Ruby-defined pieces behind seams:
- Manager is the Rack middleware. It wraps a downstream App, injects a Proxy as env["warden"], runs the app inside a catch for the throw :warden control-flow signal, and dispatches to the failure app / redirect / custom response when authentication was thrown.
- Proxy is the env["warden"] object: Authenticate / AuthenticateBang, Authenticated, User / SetUser, Logout, WinningStrategy, Message. It is scope-aware ("default" plus any custom scope).
- The strategy bodies (valid? + authenticate!) are Ruby, so they live behind the injectable StrategyRun seam, which returns a StrategyResult (success / failure / redirect / custom / pass, and whether it halted the chain).
- The session is a Rack concern, so serialize_into_session / serialize_from_session go through the SessionStore seam; a faithful default, SerializerStore, stores the user key under "warden.user.<scope>.key" in env["rack.session"].
The Rack environment and response tuple are reused from the sibling module github.com/go-ruby-rack/rack: an environment is a rack.Env (a string-keyed map) and an app returns a *rack.Response — the SPEC [status, headers, body] tuple.
throw :warden is modeled as a panic of *Throw recovered by Manager.Call; NotAuthenticated models the error a binding raises when authentication is required but no failure app is configured (the gem's "No Failure App" raise).
The package is the Warden backend for go-embedded-ruby, but is a standalone, reusable module — a sibling of go-ruby-rack, go-ruby-regexp and go-ruby-erb.
Index ¶
- Constants
- func SessionKeyFor(scope string) string
- type App
- type AuthOptions
- type Manager
- type NotAuthenticated
- type Option
- func WithDefaultScope(scope string) Option
- func WithDefaultStrategies(names ...string) Option
- func WithFailureApp(app App) Option
- func WithIntercept401() Option
- func WithScopeStrategies(scope string, names ...string) Option
- func WithSessionStore(store SessionStore) Option
- func WithStrategyRun(run StrategyRun) Option
- type Proxy
- func (p *Proxy) Authenticate(opts ...AuthOptions) any
- func (p *Proxy) AuthenticateBang(opts ...AuthOptions) any
- func (p *Proxy) Authenticated(scope ...string) bool
- func (p *Proxy) Logout(scopes ...string)
- func (p *Proxy) Message() string
- func (p *Proxy) Result(scope ...string) Result
- func (p *Proxy) SetUser(user any, scope string, store bool) any
- func (p *Proxy) Unauthenticated(scope ...string) bool
- func (p *Proxy) User(scope ...string) any
- func (p *Proxy) WinningStrategy() string
- type Result
- type SerializerStore
- type SessionStore
- type StrategyResult
- type StrategyRun
- type Throw
- type ThrowOptions
Constants ¶
const DefaultScope = "default"
DefaultScope is Warden's default authentication scope (:default).
const DefaultSessionEnvKey = "rack.session"
DefaultSessionEnvKey is the Rack env key under which the session hash lives, matching Rack's "rack.session".
const EnvKey = "warden"
EnvKey is the Rack env key under which the Proxy is injected, matching the gem's env['warden'].
Variables ¶
This section is empty.
Functions ¶
func SessionKeyFor ¶
SessionKeyFor returns the session key under which Warden stores the serialized user for a scope, matching the gem's "warden.user.#{scope}.key".
Types ¶
type App ¶
App is a Rack application: it maps a rack.Env to the SPEC [status, headers, body] tuple, returned as a *rack.Response. Both the downstream app wrapped by a Manager and the failure app are Apps.
type AuthOptions ¶
type AuthOptions struct {
// Scope is the authentication scope; empty means the manager's default scope.
Scope string
// Strategies overrides the strategy labels tried for this call; empty means
// the scope's configured strategies.
Strategies []string
}
AuthOptions tunes a single Authenticate / AuthenticateBang call, mirroring the scope: and strategy-list arguments the gem accepts.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager is the Warden Rack middleware. It wraps a downstream App, injects a Proxy as env["warden"], runs the app inside a catch for the throw :warden signal, and on a throw dispatches to the failure app / redirect / custom response.
func New ¶
New builds a Manager wrapping app, applying the given options. Without a SessionStore option it defaults to a NewSerializerStore; without a WithDefaultScope the scope is DefaultScope.
type NotAuthenticated ¶
NotAuthenticated models Warden::NotAuthenticated — the error a binding raises when authentication was required (a throw :warden reached the failure stage) but no failure app is configured. It mirrors the gem's "No Failure App" raise. Manager.Call panics with a *NotAuthenticated in that case.
type Option ¶
type Option func(*Manager)
Option configures a Manager at construction, mirroring the settings a Warden::Config exposes (default scope, per-scope strategies, failure app).
func WithDefaultScope ¶
WithDefaultScope overrides the default scope (default: DefaultScope).
func WithDefaultStrategies ¶
WithDefaultStrategies sets the strategy labels tried for scopes without an explicit list, in order.
func WithFailureApp ¶
WithFailureApp sets the failure application invoked when authentication is thrown and no strategy produced a redirect/custom response.
func WithIntercept401 ¶
func WithIntercept401() Option
WithIntercept401 makes the manager treat a downstream 401 response as an authentication failure and run the failure handling, like Warden's intercept_401.
func WithScopeStrategies ¶
WithScopeStrategies sets the strategy labels tried for a specific scope.
func WithSessionStore ¶
func WithSessionStore(store SessionStore) Option
WithSessionStore sets the SessionStore seam (defaults to a NewSerializerStore).
func WithStrategyRun ¶
func WithStrategyRun(run StrategyRun) Option
WithStrategyRun sets the StrategyRun seam used to run strategies.
type Proxy ¶
type Proxy struct {
// contains filtered or unexported fields
}
Proxy is the env["warden"] object: the per-request, scope-aware authentication handle. It caches the user per scope, runs strategies, and records the winning strategy, result and message.
func FromEnv ¶
FromEnv returns the Proxy injected into a Rack env by a Manager, or nil when none is present. Downstream apps use it to reach env["warden"].
func (*Proxy) Authenticate ¶
func (p *Proxy) Authenticate(opts ...AuthOptions) any
Authenticate runs the strategies for a scope and returns the authenticated user, or nil on failure. It never throws.
func (*Proxy) AuthenticateBang ¶
func (p *Proxy) AuthenticateBang(opts ...AuthOptions) any
AuthenticateBang runs the strategies for a scope and returns the user, or panics with a *Throw (the throw :warden signal) on failure — the authenticate! method.
func (*Proxy) Authenticated ¶
Authenticated reports whether a user is set for a scope (authenticated?), loading it from the session if needed.
func (*Proxy) Logout ¶
Logout logs out the given scopes, deleting each from the session. With no scopes it logs out every loaded scope and resets the session.
func (*Proxy) SetUser ¶
SetUser sets the user for a scope. When store is true it is also serialized into the session (set_user with store: true); pass false to skip persistence (store: false).
func (*Proxy) Unauthenticated ¶
Unauthenticated is the negation of Proxy.Authenticated.
func (*Proxy) User ¶
User returns the user for a scope, loading it from the session on first access, or nil when none is set.
func (*Proxy) WinningStrategy ¶
WinningStrategy returns the label of the last strategy that ran, or empty when none ran.
type Result ¶
type Result string
Result is the outcome kind a strategy produces, mirroring the result symbols of Warden::Strategies::Base (:success, :failure, :redirect, :custom, or none).
const ( // ResultNone is produced by pass — no decision, try the next strategy. ResultNone Result = "" // ResultSuccess is produced by success!(user) — halts with a user. ResultSuccess Result = "success" // ResultFailure is produced by fail!/fail — a failed attempt. ResultFailure Result = "failure" // ResultRedirect is produced by redirect! — halts with a redirect response. ResultRedirect Result = "redirect" // ResultCustom is produced by custom!(response) — halts with a raw response. ResultCustom Result = "custom" )
type SerializerStore ¶
type SerializerStore struct {
// Serialize maps a user to the value stored in the session.
Serialize func(user any) any
// Deserialize maps a stored value back to a user; present reports whether it
// still resolves.
Deserialize func(key any) (user any, present bool)
// SessionEnvKey overrides [DefaultSessionEnvKey] when non-empty.
SessionEnvKey string
}
SerializerStore is the faithful default SessionStore. It stores the serialized user key under SessionKeyFor in the Rack session hash held at SessionEnvKey in the env. Serialize maps a user to a storable key and Deserialize maps a stored key back to a user (returning present=false when the key no longer resolves) — exactly the SessionSerializer#serialize / #deserialize seam of the gem. NewSerializerStore wires identity functions, suitable when the user object is itself directly storable.
func NewSerializerStore ¶
func NewSerializerStore() *SerializerStore
NewSerializerStore returns a SerializerStore with identity serialize / deserialize functions, storing the user object itself in the session.
func (*SerializerStore) Delete ¶
func (s *SerializerStore) Delete(env rack.Env, scope string)
Delete implements SessionStore.
func (*SerializerStore) Reset ¶
func (s *SerializerStore) Reset(env rack.Env)
Reset implements SessionStore.
func (*SerializerStore) SerializeFromSession ¶
SerializeFromSession implements SessionStore.
func (*SerializerStore) SerializeIntoSession ¶
func (s *SerializerStore) SerializeIntoSession(env rack.Env, scope string, user any)
SerializeIntoSession implements SessionStore.
type SessionStore ¶
type SessionStore interface {
// SerializeIntoSession stores the serialized key for user under scope
// (serialize_into_session).
SerializeIntoSession(env rack.Env, scope string, user any)
// SerializeFromSession returns the user stored for scope and whether one is
// present (serialize_from_session).
SerializeFromSession(env rack.Env, scope string) (user any, present bool)
// Delete removes the stored user for scope (logout of a single scope).
Delete(env rack.Env, scope string)
// Reset clears the whole session (logout of every scope / reset_session!).
Reset(env rack.Env)
}
SessionStore is the seam through which the Proxy persists the authenticated user across requests — the serialize_into_session / serialize_from_session pair. It is a seam because the session and the (de)serialization of a user to a storable key are host concerns.
type StrategyResult ¶
type StrategyResult struct {
// Valid reports the strategy's valid? predicate. When false the strategy is
// skipped and the rest of the fields are ignored.
Valid bool
// Result is the outcome kind. ResultNone (from pass) or a non-halting
// ResultFailure (from fail, without a bang) let the runner continue.
Result Result
// User is the authenticated user, set on ResultSuccess.
User any
// Message is the failure / status message (fail!/fail/redirect!).
Message string
// Halted reports whether the strategy halted the chain. success!, fail!,
// redirect! and custom! halt; pass and the non-bang fail do not.
Halted bool
// Response is the raw Rack response carried by redirect! / custom!.
Response *rack.Response
}
StrategyResult is the outcome of running one strategy — the observable state of a Warden::Strategies::Base after its valid? check and authenticate! body.
type StrategyRun ¶
type StrategyRun func(name string, env rack.Env) StrategyResult
StrategyRun is the injectable seam that runs a single registered strategy by label against the Rack env and returns its StrategyResult. It stands in for Warden::Strategies[label].new(env,scope) followed by valid? and authenticate!, whose bodies are Ruby. A binding wires this to the host's strategy registry.
type Throw ¶
type Throw struct {
Options ThrowOptions
}
Throw is the Go analogue of Ruby's throw :warden. Proxy.AuthenticateBang panics with a *Throw when authentication fails; Manager.Call recovers it.
type ThrowOptions ¶
type ThrowOptions struct {
// Scope is the authentication scope that failed ("default" or a custom one).
Scope string
// Action names the failure action; it becomes PATH_INFO ("/unauthenticated"
// by default) when the failure app runs.
Action string
// Message is the winning strategy's failure message, if any.
Message string
// Result is the winning strategy's result (failure / redirect / custom), or
// empty when no strategy halted.
Result Result
// Strategy is the label of the winning (last-run) strategy, if any.
Strategy string
}
ThrowOptions carries the payload of Warden's throw(:warden, opts) — the control-flow signal raised when AuthenticateBang (authenticate!) fails. A binding maps a Ruby throw :warden to a panic of *Throw; Manager.Call recovers it and turns it into a failure response.
