Documentation
¶
Overview ¶
Package auth authenticates requests (SPEC §8): browser sessions via the built-in OIDC login (Okta, Entra ID, Google…), identity-aware proxies (Google IAP, AWS ALB OIDC, trusted headers), Backyard API tokens, static tokens and IdP-issued bearer JWTs (device flow). In mode "none" everyone is an anonymous guest identified by a cookie.
Index ¶
Constants ¶
const ( ModeNone = "none" ModeOIDC = "oidc" ModeIAP = "iap" ModeALB = "alb" ModeHeader = "header" )
Normalized auth modes.
const ( PathPrefix = "/__backyard/auth/" LoginPath = PathPrefix + "login" CallbackPath = PathPrefix + "callback" LogoutPath = PathPrefix + "logout" CLIPath = PathPrefix + "cli" )
Paths served by Handler.
const ( SessionCookie = "backyard_session" // OAuthCookie holds the login state when server.public_url is http. OAuthCookie = "backyard_oauth" // OAuthHostCookie holds the login state when server.public_url is https: // browsers accept a "__Host-" cookie only from the host itself (Secure, // Path=/, no Domain), so a site's page cannot plant one on the hub. OAuthHostCookie = "__Host-" + OAuthCookie AnonCookie = "backyard_anon" )
Cookie names.
const ( // IAPHeader carries the signed IAP assertion. IAPHeader = "X-Goog-IAP-JWT-Assertion" // IAPIssuer is the "iss" of IAP assertions. IAPIssuer = "https://cloud.google.com/iap" // DefaultIAPJWKSURL publishes IAP's ES256 signing keys. DefaultIAPJWKSURL = "https://www.gstatic.com/iap/verify/public_key-jwk" )
const ( // TokenIssuer is the "iss" claim of Backyard API tokens. TokenIssuer = "backyard" // TokenScope is the "scope" claim of Backyard API tokens. TokenScope = "api" // DefaultTokenTTL is used when NewTokens is given a non-positive TTL. DefaultTokenTTL = 720 * time.Hour )
const (
// ALBHeader carries the ALB-signed user claims.
ALBHeader = "X-Amzn-Oidc-Data"
)
Variables ¶
var ( // ErrUnauthenticated: no (valid) credentials were presented. ErrUnauthenticated = errors.New("auth: unauthenticated") // ErrForbidden: authenticated but not allowed (domain/group gate). ErrForbidden = errors.New("auth: forbidden") // ErrCookieConflict: the browser sent valid session (or guest) cookies // of different users, e.g. one planted by a site's page. It is always // wrapped together with ErrUnauthenticated. ErrCookieConflict = errors.New("auth: the browser sent sign-in cookies of different users") )
Functions ¶
This section is empty.
Types ¶
type Authenticator ¶
type Authenticator interface {
Authenticate(w http.ResponseWriter, r *http.Request) (*identity.User, error)
// LoginURL returns the URL a browser should be redirected to in order to
// log in and come back to returnTo, or "" when interactive login is not
// handled by Backyard (iap/alb/header/none).
LoginURL(returnTo string) string
// Handler serves /__backyard/auth/* on the hub host (login, callback,
// logout, cli). It expects the full request path.
Handler() http.Handler
// Mode returns the normalized auth mode.
Mode() string
}
Authenticator resolves the user behind a request.
Authenticate returns (user, nil) on success, (nil, ErrUnauthenticated) when the request carries no usable credentials, (nil, ErrForbidden) when the user is authenticated but rejected by allowed_domains/allowed_groups, or another error for infrastructure failures. Bearer tokens (API, static, IdP JWT) are accepted in every mode. In mode "none" Authenticate only fails when an invalid bearer token is presented, or when the browser sends valid guest cookies of different guests (ErrUnauthenticated, with ErrCookieConflict); otherwise it returns an anonymous user and, when w is non-nil, sets the backyard_anon cookie. On a cookie conflict Authenticate expires the cookies Backyard did not set itself when w is non-nil.
func New ¶
New builds the authenticator for cfg.Auth.Mode. For mode "oidc" it performs OIDC discovery against the issuer (ctx bounds that call).
HTTPClient defaults to a client with a 15 s timeout (a client without a timeout gets one). When auth.oidc.issuer is configured in a mode other than oidc (device flow behind a proxy), discovery for IdP bearer tokens is attempted here and, if the IdP is unreachable, retried lazily.
func NewBearer ¶
NewBearer builds a bearer-only authenticator for the standalone deploy gateway: it accepts Backyard API tokens, static tokens and (if cfg.Auth.OIDC.Issuer is set) IdP-issued JWTs — never cookies or proxy headers. Handler() serves nothing and LoginURL returns "".
IdP discovery is attempted here but never fails construction: when the IdP is unreachable it is retried lazily when the first IdP token arrives.
type Options ¶
type Options struct {
// Directory enriches users after claim mapping (optional).
Directory identity.Directory
// HTTPClient is used for OIDC discovery and JWKS/key fetches (default: a
// client with a 15 s timeout; a client without a timeout gets one).
HTTPClient *http.Client
// Logger (default slog.Default()).
Logger *slog.Logger
// Now overrides the clock (tests).
Now func() time.Time
}
Options are optional dependencies for authenticators.
type TokenClaims ¶
type TokenClaims struct {
Subject string `json:"sub"`
Email string `json:"email,omitempty"`
Name string `json:"name,omitempty"`
Groups []string `json:"groups,omitempty"`
Admin bool `json:"admin,omitempty"`
Scope string `json:"scope"`
}
TokenClaims are the claims of a Backyard API token (SPEC §8.3).
type Tokens ¶
type Tokens struct {
// contains filtered or unexported fields
}
Tokens mints and verifies Backyard API tokens (SPEC §8.3).
Tokens are HS256 JWTs keyed with keys.Derive(server.secret, keys.APIToken) carrying {iss:"backyard", sub, email, name, groups, admin, scope:"api", jti, iat, exp}. Rotating server.secret revokes every token. A Tokens value is immutable and safe for concurrent use.
func (*Tokens) Issue ¶
func (t *Tokens) Issue(u *identity.User, ttl time.Duration) (token string, expiresAt time.Time, err error)
Issue mints a token for u with scope "api". ttl <= 0 uses the default TTL.
The token always fits the size Verify accepts: an overlong name is shortened and, if needed, trailing groups are dropped (callers that care which groups survive put the important ones first).
func (*Tokens) Verify ¶
Verify validates a token and returns the user it represents.
Only HS256 is accepted (no "none", no asymmetric algorithms); iss must be "backyard", scope "api", and exp/iat are checked with 30 seconds of leeway. Errors wrap ErrUnauthenticated. The returned user carries Admin as recorded in the token; subjects starting with "anon:" are anonymous.