security

package
v3.13.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 24, 2026 License: MIT Imports: 34 Imported by: 0

Documentation

Overview

Package security provides access-control rules, authentication integration points, and security wiring.

Index

Constants

View Source
const (
	KernelFirewallListenerPriority = 50

	KernelAccessControlListenerPriority = 20
)
View Source
const (

	/* DefaultHmacHeaderName is the request header the internal-auth envelope is carried on unless a source/signer overrides it. */
	DefaultHmacHeaderName = "X-Melody-Internal-Auth"
)
View Source
const DefaultSwitchUserHeaderName = "X-Switch-User"

DefaultSwitchUserHeaderName is the request header that names the user to impersonate unless a source overrides it.

View Source
const DefaultTotpCodeHeaderName = "X-2FA-Code"

DefaultTotpCodeHeaderName is the request header the TOTP code is read from unless overridden.

View Source
const DefaultTotpRecoveryHeaderName = "X-2FA-Recovery-Code"

DefaultTotpRecoveryHeaderName is the request header a single-use recovery code is read from unless overridden. It is deliberately distinct from the TOTP code header so the two never collide — a TOTP code is 6 to 8 digits, a recovery code is the xxxxx-xxxxx form.

View Source
const HmacVerifyBodyBeforeNonceAttribute = "security.hmac.verifyBodyBeforeNonce"

HmacVerifyBodyBeforeNonceAttribute is the request attribute (settable per route or, on demand, through SetHmacVerifyBodyBeforeNonce) that overrides the source's VerifyBodyBeforeNonce default for a single request. Its value must be a bool.

View Source
const (
	ServiceFirewallManager = "service.security.firewall_manager"
)

Variables

This section is empty.

Functions

func ActorFromToken added in v3.9.0

func ActorFromToken(token securitycontract.Token) (securitycontract.Actor, bool)

ActorFromToken reads the originating actor from a token when the token carries one, returning (nil, false) for a nil token, a token that is not ActorAware, or an ActorAware token with no actor set.

func ActorToData added in v3.9.0

ActorToData converts an Actor into its serializable ActorData carrier, or returns nil for a nil actor. An impersonator carried by the actor (ActorImpersonating) is encoded too, so it round-trips across a service boundary. The impersonator chain is bounded by maxActorImpersonationDepth and truncated at the bound, so a cyclic Actor (an in-process caller can make Impersonator() return an actor already in the chain) cannot recurse until the goroutine stack overflows. This mirrors the token store's bounded clone.

func FirewallManagerFromContainer

func FirewallManagerFromContainer(serviceContainer containercontract.Container) securitycontract.FirewallManager

func FirewallManagerFromResolver added in v3.7.0

func FirewallManagerFromResolver(resolver containercontract.Resolver) securitycontract.FirewallManager

func FirewallManagerMustFromContainer

func FirewallManagerMustFromContainer(serviceContainer containercontract.Container) securitycontract.FirewallManager

func FirewallManagerMustFromResolver added in v3.7.0

func FirewallManagerMustFromResolver(resolver containercontract.Resolver) securitycontract.FirewallManager

func ImpersonatorFromToken added in v3.9.0

func ImpersonatorFromToken(token securitycontract.Token) (securitycontract.Token, bool)

ImpersonatorFromToken reads the impersonating (admin) principal behind a token, returning (nil, false) for a nil token, a token that is not Impersonating, or one not currently impersonating.

func IsGranted

func IsGranted(runtimeInstance runtimecontract.Runtime, role string) bool

func PendingUserFromToken added in v3.9.0

func PendingUserFromToken(token securitycontract.Token) (string, bool)

PendingUserFromToken reports the user awaiting a second factor, returning (\"\", false) for a nil token or one that is not a two-factor challenge.

func RegisterKernelAccessControlListener

func RegisterKernelAccessControlListener(kernelInstance kernelcontract.Kernel, registry *FirewallRegistry)

func RegisterKernelSecurityResolutionListener

func RegisterKernelSecurityResolutionListener(kernelInstance kernelcontract.Kernel, registry *FirewallRegistry)

func SecurityContextSetOnRuntime

func SecurityContextSetOnRuntime(runtimeInstance runtimecontract.Runtime, securityContext *SecurityContext)

func SetHmacVerifyBodyBeforeNonce added in v3.9.0

func SetHmacVerifyBodyBeforeNonce(request httpcontract.Request, value bool)

SetHmacVerifyBodyBeforeNonce overrides, for the given request only, whether the HMAC source verifies the body before consuming the nonce. An application calls it on demand (for example in a route-scoped middleware that runs before the firewall) to flip the configured default for chosen routes or calls; setting the HmacVerifyBodyBeforeNonceAttribute route attribute has the same effect.

Types

type AccessControl

type AccessControl struct {
	// contains filtered or unexported fields
}

func NewAccessControl

func NewAccessControl(rules ...AccessControlRule) *AccessControl

func (*AccessControl) Match

func (instance *AccessControl) Match(path string) ([]string, bool)

func (*AccessControl) Rules

func (instance *AccessControl) Rules() []AccessControlRule

type AccessControlRule

type AccessControlRule struct {
	// contains filtered or unexported fields
}

func NewAccessControlExactRule

func NewAccessControlExactRule(path string, attributes ...string) AccessControlRule

func NewAccessControlRegexRule

func NewAccessControlRegexRule(pattern string, attributes ...string) AccessControlRule

func NewAccessControlRule

func NewAccessControlRule(pathPrefix string, attributes ...string) AccessControlRule

func NewAccessControlRuleWithSegmentPrefix

func NewAccessControlRuleWithSegmentPrefix(pathPrefix string, attributes ...string) AccessControlRule

type AccessDecisionManager

type AccessDecisionManager struct {
	// contains filtered or unexported fields
}

func NewAccessDecisionManagerWithVoters

func NewAccessDecisionManagerWithVoters(strategy securitycontract.DecisionStrategy, voters []securitycontract.Voter) *AccessDecisionManager

func (*AccessDecisionManager) DecideAll

func (instance *AccessDecisionManager) DecideAll(token securitycontract.Token, attributes []string, subject any) error

func (*AccessDecisionManager) DecideAny

func (instance *AccessDecisionManager) DecideAny(token securitycontract.Token, attributes []string, subject any) error

func (*AccessDecisionManager) Strategy

func (*AccessDecisionManager) Voters

func (instance *AccessDecisionManager) Voters() []securitycontract.Voter

type Actor added in v3.9.0

type Actor struct {
	// contains filtered or unexported fields
}

func NewActor added in v3.9.0

func NewActor(
	identifier string,
	actorType string,
	roles []string,
	attributes map[string]string,
) *Actor

func NewActorFromData added in v3.9.0

func NewActorFromData(data *securitycontract.ActorData) *Actor

NewActorFromData rebuilds a concrete Actor from its serializable ActorData carrier, or returns nil when the carrier is absent. A nested Impersonator is rebuilt too, so an impersonation propagated across a service boundary stays readable. The impersonator chain is bounded by maxActorImpersonationDepth and truncated at the bound, so a pathologically deep or cyclic ActorData — an in-process caller can point Impersonator back into the chain through the exported field — cannot recurse until the goroutine stack overflows (a fatal error no deferred recover() can catch). This mirrors the token store's bounded clone.

func NewActorWithImpersonator added in v3.9.0

func NewActorWithImpersonator(
	identifier string,
	actorType string,
	roles []string,
	attributes map[string]string,
	impersonator securitycontract.Actor,
) *Actor

NewActorWithImpersonator builds an Actor that an impersonator is acting behind, so the accountable admin (and its roles) travels with the originating actor. A nil impersonator is equivalent to NewActor.

func (*Actor) Attributes added in v3.9.0

func (instance *Actor) Attributes() map[string]string

func (*Actor) Identifier added in v3.9.0

func (instance *Actor) Identifier() string

func (*Actor) Impersonator added in v3.9.0

func (instance *Actor) Impersonator() (securitycontract.Actor, bool)

Impersonator reports the admin acting behind this actor, returning (nil, false) when the actor is not an impersonation.

func (*Actor) Roles added in v3.9.0

func (instance *Actor) Roles() []string

func (*Actor) Type added in v3.9.0

func (instance *Actor) Type() string

type AnonymousToken

type AnonymousToken struct {
}

func NewAnonymousToken

func NewAnonymousToken() *AnonymousToken

func (*AnonymousToken) Attributes added in v3.7.0

func (instance *AnonymousToken) Attributes() map[string]any

func (*AnonymousToken) IsAuthenticated

func (instance *AnonymousToken) IsAuthenticated() bool

func (*AnonymousToken) Roles

func (instance *AnonymousToken) Roles() []string

func (*AnonymousToken) Scope added in v3.7.0

func (instance *AnonymousToken) Scope() map[string]any

func (*AnonymousToken) UserIdentifier

func (instance *AnonymousToken) UserIdentifier() string

type ApiKeyHeaderAuthenticator

type ApiKeyHeaderAuthenticator struct {
	// contains filtered or unexported fields
}

func NewApiKeyHeaderAuthenticator

func NewApiKeyHeaderAuthenticator(headerName string, expectedValue string, userId string, roles []string) *ApiKeyHeaderAuthenticator

func (*ApiKeyHeaderAuthenticator) Authenticate

func (instance *ApiKeyHeaderAuthenticator) Authenticate(request httpcontract.Request) (securitycontract.Token, error)

func (*ApiKeyHeaderAuthenticator) Supports

func (instance *ApiKeyHeaderAuthenticator) Supports(request httpcontract.Request) bool

type ApiKeyHeaderRule

type ApiKeyHeaderRule struct {
	// contains filtered or unexported fields
}

func NewApiKeyHeaderRule

func NewApiKeyHeaderRule(matcher securitycontract.Matcher, headerName string, expectedValue string) *ApiKeyHeaderRule

func (*ApiKeyHeaderRule) Applies

func (instance *ApiKeyHeaderRule) Applies(request httpcontract.Request) bool

func (*ApiKeyHeaderRule) Check

func (instance *ApiKeyHeaderRule) Check(request httpcontract.Request) error

type AuthenticatedToken

type AuthenticatedToken struct {
	// contains filtered or unexported fields
}

func NewAuthenticatedToken

func NewAuthenticatedToken(userIdentifier string, roles []string) *AuthenticatedToken

func NewAuthenticatedTokenFromClaims added in v3.7.0

func NewAuthenticatedTokenFromClaims(claims securitycontract.Claims) *AuthenticatedToken

func NewAuthenticatedTokenWithActor added in v3.9.0

func NewAuthenticatedTokenWithActor(
	userIdentifier string,
	roles []string,
	actor securitycontract.Actor,
) *AuthenticatedToken

NewAuthenticatedTokenWithActor builds a token whose authenticated principal is userIdentifier/roles and which additionally carries an originating actor readable through OnBehalfOf. A nil actor is equivalent to NewAuthenticatedToken.

func (*AuthenticatedToken) Attributes added in v3.7.0

func (instance *AuthenticatedToken) Attributes() map[string]any

func (*AuthenticatedToken) IsAuthenticated

func (instance *AuthenticatedToken) IsAuthenticated() bool

func (*AuthenticatedToken) OnBehalfOf added in v3.9.0

func (instance *AuthenticatedToken) OnBehalfOf() (securitycontract.Actor, bool)

func (*AuthenticatedToken) Roles

func (instance *AuthenticatedToken) Roles() []string

func (*AuthenticatedToken) Scope added in v3.7.0

func (instance *AuthenticatedToken) Scope() map[string]any

func (*AuthenticatedToken) UserIdentifier

func (instance *AuthenticatedToken) UserIdentifier() string

type AuthenticatorManager

type AuthenticatorManager struct {
	// contains filtered or unexported fields
}

func NewAuthenticatorManager

func NewAuthenticatorManager(authenticators ...securitycontract.Authenticator) *AuthenticatorManager

func (*AuthenticatorManager) Authenticate

func (instance *AuthenticatorManager) Authenticate(request httpcontract.Request) (securitycontract.Token, bool, error)

type AuthenticatorTokenSource

type AuthenticatorTokenSource struct {
	// contains filtered or unexported fields
}

func NewAuthenticatorTokenSource

func NewAuthenticatorTokenSource(manager *AuthenticatorManager) *AuthenticatorTokenSource

func (*AuthenticatorTokenSource) Name

func (instance *AuthenticatorTokenSource) Name() string

func (*AuthenticatorTokenSource) Resolve

func (instance *AuthenticatorTokenSource) Resolve(runtimeInstance runtimecontract.Runtime, request httpcontract.Request) (securitycontract.Token, error)

type AuthorizationDeniedEvent

type AuthorizationDeniedEvent struct {
	// contains filtered or unexported fields
}

func NewAuthorizationDeniedEvent

func NewAuthorizationDeniedEvent(request httpcontract.Request, attributes []string, err error) *AuthorizationDeniedEvent

func (*AuthorizationDeniedEvent) Attributes

func (instance *AuthorizationDeniedEvent) Attributes() []string

func (*AuthorizationDeniedEvent) Err

func (instance *AuthorizationDeniedEvent) Err() error

func (*AuthorizationDeniedEvent) Request

func (instance *AuthorizationDeniedEvent) Request() httpcontract.Request

type AuthorizationGrantedEvent

type AuthorizationGrantedEvent struct {
	// contains filtered or unexported fields
}

func NewAuthorizationGrantedEvent

func NewAuthorizationGrantedEvent(request httpcontract.Request, attributes []string) *AuthorizationGrantedEvent

func (*AuthorizationGrantedEvent) Attributes

func (instance *AuthorizationGrantedEvent) Attributes() []string

func (*AuthorizationGrantedEvent) Request

func (instance *AuthorizationGrantedEvent) Request() httpcontract.Request

type BearerTokenSource added in v3.7.0

type BearerTokenSource struct {
	// contains filtered or unexported fields
}

func NewBearerTokenSource added in v3.7.0

func NewBearerTokenSource(validator securitycontract.TokenValidator) *BearerTokenSource

func NewBearerTokenSourceWithEnricher added in v3.7.0

func NewBearerTokenSourceWithEnricher(
	validator securitycontract.TokenValidator,
	enricher securitycontract.TokenEnricher,
) *BearerTokenSource

func (*BearerTokenSource) Name added in v3.7.0

func (instance *BearerTokenSource) Name() string

func (*BearerTokenSource) Resolve added in v3.7.0

func (instance *BearerTokenSource) Resolve(
	runtimeInstance runtimecontract.Runtime,
	request httpcontract.Request,
) (securitycontract.Token, error)

type CompiledConfiguration

type CompiledConfiguration struct {
	// contains filtered or unexported fields
}

func NewCompiledConfiguration

func NewCompiledConfiguration(firewalls []*CompiledFirewall, globalAccessControl *AccessControl) *CompiledConfiguration

func (*CompiledConfiguration) Firewalls

func (instance *CompiledConfiguration) Firewalls() []*CompiledFirewall

func (*CompiledConfiguration) GlobalAccessControl

func (instance *CompiledConfiguration) GlobalAccessControl() *AccessControl

type CompiledFirewall

type CompiledFirewall struct {
	// contains filtered or unexported fields
}

func NewCompiledFirewall

func NewCompiledFirewall(
	name string,
	matcher securitycontract.Matcher,
	matcherDescription string,
	rules []securitycontract.Rule,
	tokenSource securitycontract.TokenSource,
	accessControl *AccessControl,
	accessDecisionManager securitycontract.AccessDecisionManager,
	roleHierarchy *RoleHierarchy,
	entryPoint securitycontract.EntryPoint,
	accessDeniedHandler securitycontract.AccessDeniedHandler,
	loginPath string,
	logoutPath string,
	loginHandler securitycontract.LoginHandler,
	logoutHandler securitycontract.LogoutHandler,
	roleHierarchySource Source,
	accessDecisionManagerSource Source,
	accessControlSource Source,
	entryPointSource Source,
	accessDeniedHandlerSource Source,
) *CompiledFirewall

func (*CompiledFirewall) AccessControl

func (instance *CompiledFirewall) AccessControl() *AccessControl

func (*CompiledFirewall) AccessDecisionManager

func (instance *CompiledFirewall) AccessDecisionManager() securitycontract.AccessDecisionManager

func (*CompiledFirewall) AccessDeniedHandler

func (instance *CompiledFirewall) AccessDeniedHandler() securitycontract.AccessDeniedHandler

func (*CompiledFirewall) EntryPoint

func (instance *CompiledFirewall) EntryPoint() securitycontract.EntryPoint

func (*CompiledFirewall) Login

func (*CompiledFirewall) LoginPath

func (instance *CompiledFirewall) LoginPath() string

func (*CompiledFirewall) Logout

func (*CompiledFirewall) LogoutPath

func (instance *CompiledFirewall) LogoutPath() string

func (*CompiledFirewall) Matcher

func (instance *CompiledFirewall) Matcher() securitycontract.Matcher

func (*CompiledFirewall) MatcherDescription

func (instance *CompiledFirewall) MatcherDescription() string

func (*CompiledFirewall) Name

func (instance *CompiledFirewall) Name() string

func (*CompiledFirewall) RoleHierarchy

func (instance *CompiledFirewall) RoleHierarchy() *RoleHierarchy

func (*CompiledFirewall) Rules

func (instance *CompiledFirewall) Rules() []securitycontract.Rule

func (*CompiledFirewall) Sources

func (instance *CompiledFirewall) Sources() (Source, Source, Source, Source, Source)

func (*CompiledFirewall) TokenSource

func (instance *CompiledFirewall) TokenSource() securitycontract.TokenSource

type Firewall

type Firewall struct {
	// contains filtered or unexported fields
}

func NewFirewall

func NewFirewall(rules ...securitycontract.Rule) *Firewall

func (*Firewall) Check

func (instance *Firewall) Check(request httpcontract.Request) error

type FirewallManager

type FirewallManager struct {
	// contains filtered or unexported fields
}

func NewFirewallManager

func NewFirewallManager(compiledConfiguration *CompiledConfiguration) *FirewallManager

func (*FirewallManager) Firewall

func (instance *FirewallManager) Firewall(name string) (securitycontract.Firewall, error)

type FirewallRegistry

type FirewallRegistry struct {
	// contains filtered or unexported fields
}

func NewFirewallRegistry

func NewFirewallRegistry(compiledConfiguration *CompiledConfiguration) *FirewallRegistry

func (*FirewallRegistry) GlobalAccessControl

func (instance *FirewallRegistry) GlobalAccessControl() *AccessControl

func (*FirewallRegistry) Match

func (instance *FirewallRegistry) Match(request httpcontract.Request) (*CompiledFirewall, bool)

type HmacAppRegistry added in v3.9.0

type HmacAppRegistry interface {
	RolesForApp(app string) ([]string, bool)
}

HmacAppRegistry maps a calling application name (as carried by the envelope) to the roles its service principal is granted once the envelope is verified. An app absent from the registry is rejected, so only known callers obtain a token.

type HmacEnvelopeSigner added in v3.9.0

type HmacEnvelopeSigner struct {
	// contains filtered or unexported fields
}

func NewHmacEnvelopeSigner added in v3.9.0

func NewHmacEnvelopeSigner(config HmacEnvelopeSignerConfig) *HmacEnvelopeSigner

func (*HmacEnvelopeSigner) HeaderName added in v3.9.0

func (instance *HmacEnvelopeSigner) HeaderName() string

func (*HmacEnvelopeSigner) Sign added in v3.9.0

func (instance *HmacEnvelopeSigner) Sign(
	method string,
	path string,
	body []byte,
	actor securitycontract.Actor,
) (string, error)

Sign builds the internal-auth header value binding the call to method, path, query string and the given body, optionally propagating an originating actor. The path argument may carry a query string (everything after the first '?'); it is signed separately and matched against the request's raw query at the callee. The returned string is written to HeaderName() on the outgoing request.

type HmacEnvelopeSignerConfig added in v3.9.0

type HmacEnvelopeSignerConfig struct {
	/* App is the calling application's own name, recorded in the envelope and matched against the callee's app registry. */
	App string

	Secrets HmacSecretProvider

	/* HeaderName overrides the header the envelope is written to; defaults to DefaultHmacHeaderName. */
	HeaderName string

	/* Ttl is how long a signed envelope stays valid; defaults to defaultHmacSignerTtl. */
	Ttl time.Duration

	/* Audience, when set, names the callee service this envelope is minted for and is signed into the envelope; the callee's HmacTokenSource rejects it unless its configured ServiceIdentity matches, so an envelope captured en route to one service cannot be replayed against another that trusts the same caller. Optional and opt-in: leave it empty and the callee's audience check (which is itself only active when it configures a ServiceIdentity) is not engaged, preserving the previous behavior. */
	Audience string
}

HmacEnvelopeSignerConfig configures the client side of the internal-auth scheme — the helper a calling service uses to sign an outgoing request so the callee's HmacTokenSource accepts it. Both products share this signer so the canonical envelope form stays identical on both ends.

type HmacKey added in v3.9.0

type HmacKey struct {
	App    string
	Secret []byte
}

HmacKey is one entry in a static secret provider: the secret bytes for a key id and the application that key id belongs to. A key id is owned by exactly one app; an app may own several key ids (rotation overlap), all naming the same app.

type HmacSecretProvider added in v3.9.0

type HmacSecretProvider interface {
	CurrentKeyId() string

	Secret(keyId string) ([]byte, bool)

	AppForKeyId(keyId string) (string, bool)
}

HmacSecretProvider resolves the shared secret for the internal-auth HMAC source. CurrentKeyId names the key a signer should use now; Secret looks up the secret for a key id presented on an incoming envelope; AppForKeyId names the single application a key id is issued to, so the verifier can refuse an envelope whose claimed app does not own the key that signed it. Keeping several keys resolvable at once is what makes rotation seamless: roll a new current key while the previous key stays resolvable until every caller has moved, then drop it. This mirrors the encrypt KeyProvider shape.

type HmacTokenSource added in v3.9.0

type HmacTokenSource struct {
	// contains filtered or unexported fields
}

func NewHmacTokenSource added in v3.9.0

func NewHmacTokenSource(config HmacTokenSourceConfig) *HmacTokenSource

func (*HmacTokenSource) Name added in v3.9.0

func (instance *HmacTokenSource) Name() string

func (*HmacTokenSource) Resolve added in v3.9.0

func (instance *HmacTokenSource) Resolve(
	runtimeInstance runtimecontract.Runtime,
	request httpcontract.Request,
) (securitycontract.Token, error)

type HmacTokenSourceConfig added in v3.9.0

type HmacTokenSourceConfig struct {
	Secrets    HmacSecretProvider
	Apps       HmacAppRegistry
	NonceGuard securitycontract.NonceGuard
	HeaderName string
	Leeway     time.Duration

	/* MaxFutureExpiry caps how far in the future an envelope's ExpiresAt may sit (measured from the verifier's clock). The nonce guard remembers each nonce until its envelope expires, so without a cap a holder of a valid secret could issue far-future-expiry envelopes and pin unbounded memory in an in-process guard. Zero leaves the horizon unbounded (the previous behaviour) for callers that deliberately mint long-lived envelopes; set it (for example a few minutes above the signer's Ttl) on multi-instance deployments. */
	MaxFutureExpiry time.Duration

	/* ServiceIdentity, when set, is this service's own name and turns on audience enforcement: the verifier rejects any envelope whose signed Audience does not equal it, so a shared caller's envelope captured en route to a different service cannot be replayed here. Opt-in and backward compatible — leaving it empty skips the audience check entirely, so envelopes minted before signers set an Audience keep verifying. Once set, callers must sign with a matching HmacEnvelopeSignerConfig.Audience or their envelopes are rejected. */
	ServiceIdentity string

	/* VerifyBodyBeforeNonce selects the default order of the body and nonce checks. When false (the default) the nonce is consumed before the body is read, so a captured valid envelope can force at most one body buffering — but an on-path party who replays the header with a mutated body burns the nonce and fails the legitimate request as a replay. When true the body hash is verified first, so a body mismatch is rejected without consuming the nonce, at the cost of letting a captured envelope force body buffering until it expires. A per-request override (route attribute HmacVerifyBodyBeforeNonceAttribute, or SetHmacVerifyBodyBeforeNonce) takes precedence for routes/calls that need the opposite trade-off. */
	VerifyBodyBeforeNonce bool
}

HmacTokenSourceConfig configures the verifying side of the internal-auth scheme. Secrets resolves the shared key (supporting rotation through multiple resolvable key ids); Apps maps a verified caller to the roles its service principal receives; NonceGuard rejects replayed envelopes (defaults to an in-process guard — supply a shared one for multi-instance deployments); Leeway tolerates clock skew on the issued/expiry checks; MaxFutureExpiry bounds how far ahead an envelope's expiry may sit.

type ImpersonationRoleMode added in v3.9.0

type ImpersonationRoleMode int

ImpersonationRoleMode selects whose roles an impersonation token authorizes and propagates with. The visible principal, scope and attributes are always the impersonated user's (you act in their context); only the effective role set differs.

const (
	/* RoleModeImpersonated (the default, zero value) takes on the impersonated user's roles, so the admin experiences exactly the target's rights and full context. */
	RoleModeImpersonated ImpersonationRoleMode = iota

	/* RoleModeImpersonator keeps the admin's own roles while acting in the impersonated user's context, so the admin retains their own rights when viewing as the target. */
	RoleModeImpersonator
)

type ImpersonationToken added in v3.9.0

type ImpersonationToken struct {
	// contains filtered or unexported fields
}

func NewImpersonationToken added in v3.9.0

func NewImpersonationToken(
	impersonated securitycontract.Token,
	impersonator securitycontract.Token,
) *ImpersonationToken

NewImpersonationToken builds a token whose visible principal is the impersonated user (it drives Identifier/Roles/Scope/Attributes/IsAuthenticated) while the impersonator (the admin who switched) stays readable through the Impersonating interface so both identities can be audited. It uses RoleModeImpersonated; use NewImpersonationTokenWithRoleMode to keep the admin's own roles.

func NewImpersonationTokenWithRoleMode added in v3.9.0

func NewImpersonationTokenWithRoleMode(
	impersonated securitycontract.Token,
	impersonator securitycontract.Token,
	roleMode ImpersonationRoleMode,
) *ImpersonationToken

NewImpersonationTokenWithRoleMode is NewImpersonationToken with an explicit role mode: RoleModeImpersonated takes on the target's roles, RoleModeImpersonator keeps the admin's own. The impersonator stays readable (and propagates between services through the originating actor) in either mode.

func (*ImpersonationToken) Attributes added in v3.9.0

func (instance *ImpersonationToken) Attributes() map[string]any

func (*ImpersonationToken) Impersonator added in v3.9.0

func (instance *ImpersonationToken) Impersonator() (securitycontract.Token, bool)

func (*ImpersonationToken) IsAuthenticated added in v3.9.0

func (instance *ImpersonationToken) IsAuthenticated() bool

func (*ImpersonationToken) OnBehalfOf added in v3.9.0

func (instance *ImpersonationToken) OnBehalfOf() (securitycontract.Actor, bool)

OnBehalfOf is the originating actor that propagates the impersonation across services: the impersonated user (identified, carrying the effective roles of the active role mode) acting behind the impersonator (the accountable admin, with the admin's own identity and roles). Encoding both — rather than only the impersonated identity — keeps the admin auditable downstream and lets the impersonator's roles travel the whole flow.

func (*ImpersonationToken) Roles added in v3.9.0

func (instance *ImpersonationToken) Roles() []string

func (*ImpersonationToken) Scope added in v3.9.0

func (instance *ImpersonationToken) Scope() map[string]any

func (*ImpersonationToken) UserIdentifier added in v3.9.0

func (instance *ImpersonationToken) UserIdentifier() string

type ImpersonationTokenSource added in v3.9.0

type ImpersonationTokenSource struct {
	// contains filtered or unexported fields
}

func NewImpersonationTokenSource added in v3.9.0

func NewImpersonationTokenSource(config ImpersonationTokenSourceConfig) *ImpersonationTokenSource

func (*ImpersonationTokenSource) Name added in v3.9.0

func (instance *ImpersonationTokenSource) Name() string

func (*ImpersonationTokenSource) Resolve added in v3.9.0

func (instance *ImpersonationTokenSource) Resolve(
	runtimeInstance runtimecontract.Runtime,
	request httpcontract.Request,
) (securitycontract.Token, error)

type ImpersonationTokenSourceConfig added in v3.9.0

type ImpersonationTokenSourceConfig struct {
	Inner securitycontract.TokenSource

	Users securitycontract.ImpersonatedUserResolver

	/* HeaderName overrides the switch-user header; defaults to DefaultSwitchUserHeaderName. */
	HeaderName string

	/* SwitchRole is the role the admin must hold to be allowed to switch; defaults to contract.RoleAllowedToSwitch. */
	SwitchRole string

	/* RoleMode selects whose roles the impersonation token authorizes with: RoleModeImpersonated (the default) takes on the target's roles for their full context, RoleModeImpersonator keeps the admin's own rights. The impersonator stays auditable and propagates between services in either mode. */
	RoleMode ImpersonationRoleMode

	/* RoleHierarchy, when set, expands the admin's roles through the role hierarchy before the switch-role check, matching how the access-decision path authorizes (an admin granted the switch role transitively — e.g. via a super-admin role that implies it — is then allowed to switch). Optional: a nil hierarchy checks the raw token roles, so the default behavior is unchanged. */
	RoleHierarchy *RoleHierarchy
}

ImpersonationTokenSourceConfig configures the switch-user decorator. Inner resolves the real (admin) token first; when the switch header is present, the admin is authenticated and holds SwitchRole, Users resolves the target identity and the result impersonates it. Any missing precondition leaves the admin's own token untouched.

type InMemoryTokenStore added in v3.7.0

type InMemoryTokenStore struct {
	// contains filtered or unexported fields
}

func NewInMemoryTokenStore added in v3.7.0

func NewInMemoryTokenStore() *InMemoryTokenStore

func NewInMemoryTokenStoreWithClock added in v3.7.0

func NewInMemoryTokenStoreWithClock(clockInstance clockcontract.Clock) *InMemoryTokenStore

func (*InMemoryTokenStore) Delete added in v3.7.0

func (instance *InMemoryTokenStore) Delete(tokenString string)

func (*InMemoryTokenStore) DeleteByUser added in v3.7.0

func (instance *InMemoryTokenStore) DeleteByUser(userIdentifier string) int

func (*InMemoryTokenStore) Lookup added in v3.7.0

func (instance *InMemoryTokenStore) Lookup(
	runtimeInstance runtimecontract.Runtime,
	tokenString string,
) (securitycontract.Claims, bool, error)

func (*InMemoryTokenStore) PurgeExpired added in v3.7.0

func (instance *InMemoryTokenStore) PurgeExpired() int

func (*InMemoryTokenStore) Put added in v3.7.0

func (instance *InMemoryTokenStore) Put(tokenString string, claims securitycontract.Claims)

func (*InMemoryTokenStore) PutWithTtl added in v3.7.0

func (instance *InMemoryTokenStore) PutWithTtl(tokenString string, claims securitycontract.Claims, ttl time.Duration)

type JsonAccessDeniedHandler added in v3.7.0

type JsonAccessDeniedHandler struct {
}

func NewJsonAccessDeniedHandler added in v3.7.0

func NewJsonAccessDeniedHandler() *JsonAccessDeniedHandler

func (*JsonAccessDeniedHandler) Handle added in v3.7.0

func (instance *JsonAccessDeniedHandler) Handle(
	runtimeInstance runtimecontract.Runtime,
	request httpcontract.Request,
	decisionErr error,
) (httpcontract.Response, error)

type JsonEntryPoint added in v3.7.0

type JsonEntryPoint struct {
}

func NewJsonEntryPoint added in v3.7.0

func NewJsonEntryPoint() *JsonEntryPoint

func (*JsonEntryPoint) Start added in v3.7.0

func (instance *JsonEntryPoint) Start(
	runtimeInstance runtimecontract.Runtime,
	request httpcontract.Request,
) (httpcontract.Response, error)

type JwtConfig added in v3.7.0

type JwtConfig struct {
	Secret               []byte
	SubjectClaim         string
	RolesClaim           string
	ScopeClaim           string
	Leeway               time.Duration
	AllowWithoutExpiry   bool
	RejectFutureIssuedAt bool
	Issuer               string
	Audience             string
}

type JwtTokenValidator added in v3.7.0

type JwtTokenValidator struct {
	// contains filtered or unexported fields
}

func NewJwtTokenValidator added in v3.7.0

func NewJwtTokenValidator(config JwtConfig) *JwtTokenValidator

func (*JwtTokenValidator) Validate added in v3.7.0

func (instance *JwtTokenValidator) Validate(
	runtimeInstance runtimecontract.Runtime,
	tokenString string,
) (securitycontract.Claims, error)

type LoginFailureEvent

type LoginFailureEvent struct {
	// contains filtered or unexported fields
}

func NewLoginFailureEvent

func NewLoginFailureEvent(
	request httpcontract.Request,
	err error,
) *LoginFailureEvent

func (*LoginFailureEvent) Error

func (instance *LoginFailureEvent) Error() error

func (*LoginFailureEvent) Request

func (instance *LoginFailureEvent) Request() httpcontract.Request

type LoginSuccessEvent

type LoginSuccessEvent struct {
	// contains filtered or unexported fields
}

func NewLoginSuccessEvent

func NewLoginSuccessEvent(
	request httpcontract.Request,
	token securitycontract.Token,
) *LoginSuccessEvent

func (*LoginSuccessEvent) Request

func (instance *LoginSuccessEvent) Request() httpcontract.Request

func (*LoginSuccessEvent) Token

func (instance *LoginSuccessEvent) Token() securitycontract.Token

type LogoutFailureEvent

type LogoutFailureEvent struct {
	// contains filtered or unexported fields
}

func NewLogoutFailureEvent

func NewLogoutFailureEvent(request httpcontract.Request, err error) *LogoutFailureEvent

func (*LogoutFailureEvent) Error

func (instance *LogoutFailureEvent) Error() error

func (*LogoutFailureEvent) Request

func (instance *LogoutFailureEvent) Request() httpcontract.Request

type LogoutSuccessEvent

type LogoutSuccessEvent struct {
	// contains filtered or unexported fields
}

func NewLogoutSuccessEvent

func NewLogoutSuccessEvent(request httpcontract.Request) *LogoutSuccessEvent

func (*LogoutSuccessEvent) Request

func (instance *LogoutSuccessEvent) Request() httpcontract.Request

type MatchedAccessControlRule

type MatchedAccessControlRule struct {
	// contains filtered or unexported fields
}

func NewMatchedAccessControlRule

func NewMatchedAccessControlRule(
	pathPrefix string,
	attributes []string,
	source Source,
	ruleIndex int,
	firewall string,
) *MatchedAccessControlRule

func (*MatchedAccessControlRule) Attributes

func (instance *MatchedAccessControlRule) Attributes() []string

func (*MatchedAccessControlRule) Firewall

func (instance *MatchedAccessControlRule) Firewall() string

func (*MatchedAccessControlRule) PathPrefix

func (instance *MatchedAccessControlRule) PathPrefix() string

func (*MatchedAccessControlRule) RuleIndex

func (instance *MatchedAccessControlRule) RuleIndex() int

func (*MatchedAccessControlRule) Source

func (instance *MatchedAccessControlRule) Source() Source

type MemoryNonceGuard added in v3.9.0

type MemoryNonceGuard struct {
	// contains filtered or unexported fields
}

func NewMemoryNonceGuard added in v3.9.0

func NewMemoryNonceGuard() *MemoryNonceGuard

MemoryNonceGuard is an in-process NonceGuard backed by a map of nonce expiries. It is suitable for single-instance deployments, tests and local development; a multi-instance deployment must use a shared guard (for example the Redis-backed guard in integrations/rueidis) so a nonce replayed against a different instance is still detected.

func (*MemoryNonceGuard) Remember added in v3.9.0

func (instance *MemoryNonceGuard) Remember(
	_ runtimecontract.Runtime,
	nonce string,
	ttl time.Duration,
) (bool, error)

type OpaqueTokenValidator added in v3.7.0

type OpaqueTokenValidator struct {
	// contains filtered or unexported fields
}

func NewOpaqueTokenValidator added in v3.7.0

func NewOpaqueTokenValidator(store securitycontract.TokenStore) *OpaqueTokenValidator

func (*OpaqueTokenValidator) Validate added in v3.7.0

func (instance *OpaqueTokenValidator) Validate(
	runtimeInstance runtimecontract.Runtime,
	tokenString string,
) (securitycontract.Claims, error)

type PathPrefixMatcher

type PathPrefixMatcher struct {
	// contains filtered or unexported fields
}

func NewPathPrefixMatcher

func NewPathPrefixMatcher(prefix string) *PathPrefixMatcher

func (*PathPrefixMatcher) Matches

func (instance *PathPrefixMatcher) Matches(request httpcontract.Request) bool

type ResolverTokenSource

type ResolverTokenSource struct {
	// contains filtered or unexported fields
}

func NewResolverTokenSource

func NewResolverTokenSource(resolver securitycontract.TokenResolver) *ResolverTokenSource

func (*ResolverTokenSource) Name

func (instance *ResolverTokenSource) Name() string

func (*ResolverTokenSource) Resolve

func (instance *ResolverTokenSource) Resolve(runtimeInstance runtimecontract.Runtime, request httpcontract.Request) (securitycontract.Token, error)

type RoleHierarchy

type RoleHierarchy struct {
	// contains filtered or unexported fields
}

func NewRoleHierarchy

func NewRoleHierarchy(inheritedRolesByRole map[string][]string) *RoleHierarchy

func (*RoleHierarchy) ExpandRoles

func (instance *RoleHierarchy) ExpandRoles(roles []string) []string

type RoleHierarchyVoter

type RoleHierarchyVoter struct {
	// contains filtered or unexported fields
}

func NewRoleHierarchyVoter

func NewRoleHierarchyVoter(roleHierarchy *RoleHierarchy, delegate *RoleVoter) *RoleHierarchyVoter

func (*RoleHierarchyVoter) Supports

func (instance *RoleHierarchyVoter) Supports(attribute string, subject any) bool

func (*RoleHierarchyVoter) Vote

func (instance *RoleHierarchyVoter) Vote(token securitycontract.Token, attribute string, subject any) securitycontract.VoteResult

type RoleVoter

type RoleVoter struct {
}

func NewRoleVoter

func NewRoleVoter() *RoleVoter

func (*RoleVoter) Supports

func (instance *RoleVoter) Supports(attribute string, subject any) bool

func (*RoleVoter) Vote

func (instance *RoleVoter) Vote(token securitycontract.Token, attribute string, subject any) securitycontract.VoteResult

type SecurityContext

type SecurityContext struct {
	// contains filtered or unexported fields
}

func NewSecurityContext

func NewSecurityContext(
	firewall *CompiledFirewall,
	token securitycontract.Token,
) *SecurityContext

func SecurityContextFromRuntime

func SecurityContextFromRuntime(runtimeInstance runtimecontract.Runtime) (*SecurityContext, bool)

func (*SecurityContext) AccessControlSource

func (instance *SecurityContext) AccessControlSource() Source

func (*SecurityContext) AccessDecisionManagerSource

func (instance *SecurityContext) AccessDecisionManagerSource() Source

func (*SecurityContext) AccessDeniedHandlerSource

func (instance *SecurityContext) AccessDeniedHandlerSource() Source

func (*SecurityContext) EntryPointSource

func (instance *SecurityContext) EntryPointSource() Source

func (*SecurityContext) Firewall

func (instance *SecurityContext) Firewall() *CompiledFirewall

func (*SecurityContext) IsGranted

func (instance *SecurityContext) IsGranted(role string) bool

func (*SecurityContext) MatchedFirewallMatcher

func (instance *SecurityContext) MatchedFirewallMatcher() string

func (*SecurityContext) MatchedRule

func (instance *SecurityContext) MatchedRule() *MatchedAccessControlRule

func (*SecurityContext) RoleHierarchySource

func (instance *SecurityContext) RoleHierarchySource() Source

func (*SecurityContext) SetMatchedRule

func (instance *SecurityContext) SetMatchedRule(matchedRule *MatchedAccessControlRule)

func (*SecurityContext) Token

func (instance *SecurityContext) Token() securitycontract.Token

type Source

type Source string
const (
	SourceNone     Source = "none"
	SourceGlobal   Source = "global"
	SourceFirewall Source = "firewall"
	SourceMerged   Source = "merged"
)

type StaticHmacAppRegistry added in v3.9.0

type StaticHmacAppRegistry struct {
	// contains filtered or unexported fields
}

func NewStaticHmacAppRegistry added in v3.9.0

func NewStaticHmacAppRegistry(rolesByApp map[string][]string) *StaticHmacAppRegistry

func (*StaticHmacAppRegistry) RolesForApp added in v3.9.0

func (instance *StaticHmacAppRegistry) RolesForApp(app string) ([]string, bool)

type StaticHmacSecretProvider added in v3.9.0

type StaticHmacSecretProvider struct {
	// contains filtered or unexported fields
}

func NewStaticHmacSecretProvider added in v3.9.0

func NewStaticHmacSecretProvider(currentKeyId string, keysByKeyId map[string]HmacKey) *StaticHmacSecretProvider

func (*StaticHmacSecretProvider) AppForKeyId added in v3.9.0

func (instance *StaticHmacSecretProvider) AppForKeyId(keyId string) (string, bool)

func (*StaticHmacSecretProvider) CurrentKeyId added in v3.9.0

func (instance *StaticHmacSecretProvider) CurrentKeyId() string

func (*StaticHmacSecretProvider) Secret added in v3.9.0

func (instance *StaticHmacSecretProvider) Secret(keyId string) ([]byte, bool)

type Token

type Token struct {
	// contains filtered or unexported fields
}

func NewToken

func NewToken(user securitycontract.Token) *Token

func (*Token) Attributes added in v3.7.0

func (instance *Token) Attributes() map[string]any

func (*Token) Impersonator added in v3.9.0

func (instance *Token) Impersonator() (securitycontract.Token, bool)

Impersonator delegates to the wrapped token so the impersonating principal stays readable through the wrapper, returning (nil, false) when the wrapped token is not an impersonation.

func (*Token) IsAuthenticated

func (instance *Token) IsAuthenticated() bool

func (*Token) OnBehalfOf added in v3.9.0

func (instance *Token) OnBehalfOf() (securitycontract.Actor, bool)

OnBehalfOf delegates to the wrapped token so the originating actor stays readable through the wrapper, returning (nil, false) when the wrapped token does not carry one.

func (*Token) Roles

func (instance *Token) Roles() []string

func (*Token) Scope added in v3.7.0

func (instance *Token) Scope() map[string]any

func (*Token) User

func (instance *Token) User() securitycontract.Token

func (*Token) UserIdentifier

func (instance *Token) UserIdentifier() string

type TotpSecondFactorAuthenticator added in v3.9.0

type TotpSecondFactorAuthenticator struct {
	// contains filtered or unexported fields
}

func NewTotpSecondFactorAuthenticator added in v3.9.0

func NewTotpSecondFactorAuthenticator(config TotpSecondFactorAuthenticatorConfig) *TotpSecondFactorAuthenticator

func (*TotpSecondFactorAuthenticator) Authenticate added in v3.9.0

func (*TotpSecondFactorAuthenticator) Supports added in v3.9.0

func (instance *TotpSecondFactorAuthenticator) Supports(request httpcontract.Request) bool

type TotpSecondFactorAuthenticatorConfig added in v3.9.0

type TotpSecondFactorAuthenticatorConfig struct {
	Primary securitycontract.Authenticator

	Enrollments securitycontract.TwoFactorEnrollmentStore

	/* CodeHeaderName overrides the header the TOTP code is read from; defaults to DefaultTotpCodeHeaderName. */
	CodeHeaderName string

	/* RecoveryHeaderName overrides the header a single-use recovery code is read from; defaults to DefaultTotpRecoveryHeaderName. It only takes effect when Enrollments also implements TwoFactorRecoveryStore. */
	RecoveryHeaderName string

	Totp totp.Config

	/* ReplayGuard enforces single use of an accepted code within its validity window (the same NonceGuard contract the HMAC source uses). Optional: defaults to an in-process guard, so supply a shared one for multi-instance deployments. */
	ReplayGuard securitycontract.NonceGuard
}
TotpSecondFactorAuthenticatorConfig composes a primary authenticator with a TOTP second factor into a single Authenticator, so it slots into the existing AuthenticatorManager without changing the manager's first-match flow. When the primary credential is accepted and the user has a TOTP enrollment, a valid code header is additionally required; otherwise the result is a non-authenticated TwoFactorPendingToken the application uses to prompt for a code.

The ReplayGuard blocks reuse of an *accepted* code within its validity window, but this authenticator intentionally does NOT rate-limit *failed* code attempts: an unthrottled stream of distinct wrong guesses against a 6-digit code (with skew, a handful of codes are valid at any instant) can brute-force the second factor once the primary credential is known. The same caveat covers recovery codes — their larger space makes guessing far less feasible, but nothing here throttles wrong recovery guesses either. Throttling and per-user lockout are the application's responsibility and MUST front this authenticator — enforce them at the transport/middleware layer (an attempt counter with exponential backoff or a temporary lockout keyed on the authenticating user), the same layer that should already rate-limit primary-credential attempts.

When the configured Enrollments store also implements TwoFactorRecoveryStore, a single-use recovery code supplied on RecoveryHeaderName is accepted as an alternative to a TOTP code: the store atomically verifies and consumes it, so each recovery code authenticates at most once. A store that does not implement that interface simply makes recovery codes unavailable.

type TwoFactorPendingToken added in v3.9.0

type TwoFactorPendingToken struct {
	// contains filtered or unexported fields
}

func NewTwoFactorPendingToken added in v3.9.0

func NewTwoFactorPendingToken(pending securitycontract.Token) *TwoFactorPendingToken

NewTwoFactorPendingToken wraps the principal whose primary credential was accepted but who still owes a second factor. The resulting token reports IsAuthenticated()=false and an empty identifier/roles, so authorization treats the request as unauthenticated, while the pending principal stays readable through the TwoFactorPending interface so the application can prompt for a code.

func (*TwoFactorPendingToken) Attributes added in v3.9.0

func (instance *TwoFactorPendingToken) Attributes() map[string]any

func (*TwoFactorPendingToken) IsAuthenticated added in v3.9.0

func (instance *TwoFactorPendingToken) IsAuthenticated() bool

func (*TwoFactorPendingToken) PendingUserIdentifier added in v3.9.0

func (instance *TwoFactorPendingToken) PendingUserIdentifier() string

func (*TwoFactorPendingToken) Roles added in v3.9.0

func (instance *TwoFactorPendingToken) Roles() []string

func (*TwoFactorPendingToken) Scope added in v3.9.0

func (instance *TwoFactorPendingToken) Scope() map[string]any

func (*TwoFactorPendingToken) UserIdentifier added in v3.9.0

func (instance *TwoFactorPendingToken) UserIdentifier() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL