Documentation
¶
Index ¶
- Constants
- Variables
- func NewAuthManager(authenticators []security.Authenticator) security.AuthManager
- func NewAuthResource(params AuthResourceParams) api.Resource
- func NewConfigAPIKeyLoader(cfg *config.SecurityConfig) (security.APIKeyLoader, error)
- func NewConfigBasicAccountLoader(cfg *config.SecurityConfig) (security.BasicAccountLoader, error)
- func NewConfigIPWhitelistLoader(cfg *config.SecurityConfig) (security.IPWhitelistLoader, error)
- func NewJWTAuthenticator(jwt *security.JWT) security.Authenticator
- func NewJWTRefreshAuthenticator(jwt *security.JWT, userLoader security.UserLoader) security.Authenticator
- func NewOpaqueTokenAuthenticator(store security.SessionStore, policy security.SessionPolicy) security.Authenticator
- func NewPasswordAuthenticator(loader security.UserLoader, encoder password.Encoder, ...) security.Authenticator
- func NewRBACDataPermissionResolver(loader security.RolePermissionsLoader) security.DataPermissionResolver
- func NewRBACPermissionChecker(loader security.RolePermissionsLoader) security.PermissionChecker
- func NewSignatureAuthenticator(loader security.ExternalAppLoader, nonceStore security.NonceStore) security.Authenticator
- func NewTrustLoginMiddleware(params TrustLoginMiddlewareParams) (app.Middleware, error)
- type AuthResource
- func (a *AuthResource) GetUserInfo(ctx fiber.Ctx, principal *security.Principal, params api.Params) error
- func (a *AuthResource) Login(ctx fiber.Ctx, params LoginParams) error
- func (a *AuthResource) Logout(ctx fiber.Ctx) error
- func (a *AuthResource) Refresh(ctx fiber.Ctx, params RefreshParams) error
- func (a *AuthResource) ResolveChallenge(ctx fiber.Ctx, params ResolveChallengeParams) error
- type AuthResourceParams
- type AuthenticatorAuthManager
- type JWTRefreshAuthenticator
- type JWTTokenAuthenticator
- type JWTTokenGenerator
- type LoginParams
- type OpaqueTokenAuthenticator
- type OpaqueTokenGenerator
- type PasswordAuthenticator
- type RBACDataPermissionResolver
- type RBACPermissionChecker
- type RefreshParams
- type ResolveChallengeParams
- type SignatureAuthenticator
- type TrustCodeAuthenticator
- type TrustLoginMiddleware
- type TrustLoginMiddlewareParams
Constants ¶
const ( AccessTokenExpires = time.Minute * 30 RefreshTokenExpires = time.Hour * 24 * 7 )
const (
AuthTypeJWTToken = "jwt_token"
)
const (
AuthTypeOpaqueToken = "opaque_token"
)
const (
AuthTypePassword = "password"
)
const (
AuthTypeRefresh = "refresh"
)
const AuthTypeSignature = "signature"
AuthTypeSignature is the authentication type for signature-based authentication.
const AuthTypeTrustCode = "trust_code"
AuthTypeTrustCode is the login mechanism that redeems a trust-login code.
Variables ¶
var ( // ErrIPWhitelistNameBlank rejects a whitelist declared under a blank name. ErrIPWhitelistNameBlank = errors.New("ip whitelist name must not be blank") // ErrIPWhitelistEmpty rejects a whitelist with no usable entries, which // could never authenticate a request. ErrIPWhitelistEmpty = errors.New("ip whitelist must contain at least one IP or CIDR entry") // ErrIPWhitelistEntryInvalid rejects an entry that is neither an IP // address nor a CIDR range. ErrIPWhitelistEntryInvalid = errors.New("ip whitelist entry is neither an IP address nor a CIDR range") )
Configuration faults raised while building the config-backed IP whitelist loader; they surface as fx start-up errors, never through the API.
var ( // ErrAPIKeyNameBlank rejects an API key declared under a blank name. ErrAPIKeyNameBlank = errors.New("api key name must not be blank") // ErrAPIKeyValueBlank rejects an API key with a blank key value, which // could never authenticate a request. ErrAPIKeyValueBlank = errors.New("api key value must not be blank") // ErrBasicAccountUsernameBlank rejects a basic account declared under a // blank username. ErrBasicAccountUsernameBlank = errors.New("basic account username must not be blank") // ErrBasicAccountPasswordBlank rejects a basic account with a blank // password, which could never authenticate a request. ErrBasicAccountPasswordBlank = errors.New("basic account password must not be blank") )
Configuration faults raised while building the config-backed API key and basic account loaders; they surface as fx start-up errors, never through the API.
var ( // ErrTrustLoginExternalAppLoaderMissing rejects an enabled gateway with no // security.ExternalAppLoader, which supplies the per-app signing secret // every handoff is verified against. ErrTrustLoginExternalAppLoaderMissing = errors.New("vef.security.trust_login is enabled but no security.ExternalAppLoader is registered to supply app signing secrets") // ErrTrustLoginUserResolutionMissing rejects an enabled gateway that can // map no external identifier onto a local user: it needs either a // security.TrustUserResolver or a security.UserLoader. ErrTrustLoginUserResolutionMissing = errors.New( "vef.security.trust_login is enabled but neither a security.TrustUserResolver nor a security.UserLoader is registered to resolve external users", ) )
Configuration faults raised while building the trust-login gateway; they surface as fx start-up errors, never through the API.
var Module = fx.Module( "vef:security", fx.Decorate(func(cfg *config.SecurityConfig) *config.SecurityConfig { if cfg.TokenExpires <= 0 { cfg.TokenExpires = RefreshTokenExpires } if cfg.RefreshNotBefore <= 0 { cfg.RefreshNotBefore = AccessTokenExpires / 2 } if cfg.LoginRateLimit <= 0 { cfg.LoginRateLimit = 6 } if cfg.RefreshRateLimit <= 0 { cfg.RefreshRateLimit = 1 } return cfg }), fx.Decorate( fx.Annotate( func(loader security.RolePermissionsLoader, bus event.Bus) security.RolePermissionsLoader { if loader == nil { return nil } return security.NewCachedRolePermissionsLoader(loader, bus) }, fx.ParamTags(`optional:"true"`), ), ), fx.Provide( password.NewBcryptEncoder, newLoginGuard, fx.Annotate( newPasswordValidator, fx.ParamTags(``, ``, `optional:"true"`), ), newJWT, fx.Annotate( newTokenAuthenticators, fx.ParamTags(``, ``, `optional:"true"`), fx.ResultTags(`group:"vef:security:authenticators,flatten"`), ), NewJWTTokenGenerator, NewOpaqueTokenGenerator, fx.Annotate( security.NewSessionRevocationNotifier, fx.ParamTags(`group:"vef:security:session_revocation_listeners"`), ), newSessionStore, fx.Annotate( newNonceStore, fx.ParamTags(`optional:"true"`), ), fx.Annotate( newTrustCodeStore, fx.ParamTags(`optional:"true"`), ), newSessionPolicy, newTokenGenerator, security.NewJWTChallengeTokenStore, fx.Annotate( newTrustLoginAuthenticators, fx.ResultTags(`group:"vef:security:authenticators,flatten"`), ), fx.Annotate( NewTrustLoginMiddleware, fx.ResultTags(`group:"vef:app:middlewares"`), ), fx.Annotate( NewSignatureAuthenticator, fx.ParamTags(`optional:"true"`, `optional:"true"`), fx.ResultTags(`group:"vef:security:authenticators"`), ), fx.Annotate( NewPasswordAuthenticator, fx.ParamTags(`optional:"true"`, `optional:"true"`, `optional:"true"`), fx.ResultTags(`group:"vef:security:authenticators"`), ), fx.Annotate( NewAuthManager, fx.ParamTags(`group:"vef:security:authenticators"`), ), fx.Annotate( NewRBACPermissionChecker, fx.ParamTags(`optional:"true"`), ), fx.Annotate( NewRBACDataPermissionResolver, fx.ParamTags(`optional:"true"`), ), fx.Annotate( NewAuthResource, fx.ResultTags(`group:"vef:api:resources"`), ), ), )
Functions ¶
func NewAuthManager ¶
func NewAuthManager(authenticators []security.Authenticator) security.AuthManager
func NewAuthResource ¶
func NewAuthResource(params AuthResourceParams) api.Resource
NewAuthResource creates a new authentication resource with the provided auth manager and token generator.
func NewConfigAPIKeyLoader ¶ added in v0.39.0
func NewConfigAPIKeyLoader(cfg *config.SecurityConfig) (security.APIKeyLoader, error)
NewConfigAPIKeyLoader builds the framework's default security.APIKeyLoader from the static vef.security.api_keys configuration. Because the source is immutable deployment config, every entry is validated eagerly: a blank name or a blank key value fails construction (and therefore application start-up) instead of silently denying every request at runtime.
func NewConfigBasicAccountLoader ¶ added in v0.39.0
func NewConfigBasicAccountLoader(cfg *config.SecurityConfig) (security.BasicAccountLoader, error)
NewConfigBasicAccountLoader builds the framework's default security.BasicAccountLoader from the static vef.security.basic_accounts configuration. Because the source is immutable deployment config, every account is validated eagerly: a blank username or a blank password fails construction (and therefore application start-up) instead of silently denying every request at runtime.
func NewConfigIPWhitelistLoader ¶ added in v0.34.0
func NewConfigIPWhitelistLoader(cfg *config.SecurityConfig) (security.IPWhitelistLoader, error)
NewConfigIPWhitelistLoader builds the framework's default security.IPWhitelistLoader from the static vef.security.ip_whitelists configuration. Because the source is immutable deployment config, every whitelist is validated eagerly: a blank name, an empty whitelist, or an entry that is neither an IP address nor a CIDR range fails construction (and therefore application start-up) instead of silently denying every request at runtime.
func NewJWTAuthenticator ¶
func NewJWTAuthenticator(jwt *security.JWT) security.Authenticator
func NewJWTRefreshAuthenticator ¶
func NewJWTRefreshAuthenticator(jwt *security.JWT, userLoader security.UserLoader) security.Authenticator
func NewOpaqueTokenAuthenticator ¶ added in v0.38.0
func NewOpaqueTokenAuthenticator(store security.SessionStore, policy security.SessionPolicy) security.Authenticator
func NewPasswordAuthenticator ¶
func NewPasswordAuthenticator( loader security.UserLoader, encoder password.Encoder, decryptor security.PasswordDecryptor, ) security.Authenticator
func NewRBACDataPermissionResolver ¶
func NewRBACDataPermissionResolver(loader security.RolePermissionsLoader) security.DataPermissionResolver
NewRBACDataPermissionResolver creates a new RBAC data permission resolver.
func NewRBACPermissionChecker ¶
func NewRBACPermissionChecker(loader security.RolePermissionsLoader) security.PermissionChecker
func NewSignatureAuthenticator ¶
func NewSignatureAuthenticator( loader security.ExternalAppLoader, nonceStore security.NonceStore, ) security.Authenticator
NewSignatureAuthenticator creates a new signature authenticator.
A single long-lived Signature verifier is built here and reused across every request. This is what makes server-side replay protection actually work: the nonce store is shared process-wide rather than recreated per request (a fresh per-request in-memory store would always see every nonce as absent, turning replay detection into a no-op and leaking a GC goroutine on each call). The per-request app secret is supplied to VerifyWithSecret at verification time, so the verifier's own bound secret is never used.
func NewTrustLoginMiddleware ¶ added in v0.49.0
func NewTrustLoginMiddleware(params TrustLoginMiddlewareParams) (app.Middleware, error)
NewTrustLoginMiddleware creates the trust-login gateway. It returns nil while the feature is disabled, and fails the boot when it is enabled without the collaborators it cannot work without — an unauthenticatable gateway that answers 401 to every handoff is far harder to diagnose than a refused start.
Types ¶
type AuthResource ¶
AuthResource handles authentication-related API endpoints.
func (*AuthResource) GetUserInfo ¶
func (a *AuthResource) GetUserInfo(ctx fiber.Ctx, principal *security.Principal, params api.Params) error
GetUserInfo retrieves user information via UserInfoLoader. Requires a UserInfoLoader implementation to be provided.
func (*AuthResource) Login ¶
func (a *AuthResource) Login(ctx fiber.Ctx, params LoginParams) error
Login authenticates a user and returns a LoginResult. When challenge providers are configured and applicable, the result contains a challenge token and pending challenges instead of auth tokens.
func (*AuthResource) Logout ¶
func (a *AuthResource) Logout(ctx fiber.Ctx) error
Logout revokes the opaque session backing the presented token so it can no longer authenticate. Under the stateless JWT mechanism no session exists, so it is a no-op and clients must drop their stored tokens.
func (*AuthResource) Refresh ¶
func (a *AuthResource) Refresh(ctx fiber.Ctx, params RefreshParams) error
Refresh refreshes the access token using a valid refresh token. User data reload logic is handled by JwtRefreshAuthenticator.
func (*AuthResource) ResolveChallenge ¶
func (a *AuthResource) ResolveChallenge(ctx fiber.Ctx, params ResolveChallengeParams) error
ResolveChallenge validates a user's response to a login challenge. On success, either issues real auth tokens (all challenges resolved) or evaluates the next challenge sequentially.
A ChallengeProvider may reject a response by returning a typed result.Error (e.g. security.ErrOTPCodeInvalid) to control the client-facing code; a bare error is normalized to security.ErrChallengeResolveFailed (code security.ErrCodeChallengeResolveFailed).
type AuthResourceParams ¶
type AuthResourceParams struct {
fx.In
AuthManager security.AuthManager
TokenGenerator security.TokenGenerator
ChallengeTokenStore security.ChallengeTokenStore
UserInfoLoader security.UserInfoLoader `optional:"true"`
LoginGuard security.LoginGuard `optional:"true"`
SessionStore security.SessionStore
RevocationNotifier *security.SessionRevocationNotifier `optional:"true"`
ChallengeProviders []security.ChallengeProvider `group:"vef:security:challenge_providers"`
Bus event.Bus
SecurityConfig *config.SecurityConfig
}
AuthResourceParams holds the dependencies for AuthResource construction.
type AuthenticatorAuthManager ¶
type AuthenticatorAuthManager struct {
// contains filtered or unexported fields
}
func (*AuthenticatorAuthManager) Authenticate ¶
func (am *AuthenticatorAuthManager) Authenticate(ctx context.Context, authentication security.Authentication) (*security.Principal, error)
type JWTRefreshAuthenticator ¶
type JWTRefreshAuthenticator struct {
// contains filtered or unexported fields
}
func (*JWTRefreshAuthenticator) Authenticate ¶
func (j *JWTRefreshAuthenticator) Authenticate(ctx context.Context, authentication security.Authentication) (*security.Principal, error)
func (*JWTRefreshAuthenticator) Supports ¶
func (*JWTRefreshAuthenticator) Supports(authType string) bool
type JWTTokenAuthenticator ¶
type JWTTokenAuthenticator struct {
// contains filtered or unexported fields
}
func (*JWTTokenAuthenticator) Authenticate ¶
func (ja *JWTTokenAuthenticator) Authenticate(_ context.Context, authentication security.Authentication) (*security.Principal, error)
func (*JWTTokenAuthenticator) Supports ¶
func (*JWTTokenAuthenticator) Supports(authType string) bool
type JWTTokenGenerator ¶
type JWTTokenGenerator struct {
// contains filtered or unexported fields
}
func NewJWTTokenGenerator ¶
func NewJWTTokenGenerator(jwt *security.JWT, securityConfig *config.SecurityConfig) *JWTTokenGenerator
func (*JWTTokenGenerator) Generate ¶
func (g *JWTTokenGenerator) Generate(_ context.Context, principal *security.Principal, _ security.SessionMeta) (*security.AuthTokens, error)
type LoginParams ¶
type LoginParams struct {
api.P
Type string `json:"type" validate:"required" label_i18n:"auth_type"`
Principal string `json:"principal" validate:"required" label_i18n:"auth_principal"`
Credentials any `json:"credentials" validate:"required" label_i18n:"auth_credentials"`
}
LoginParams represents the request parameters for user login.
type OpaqueTokenAuthenticator ¶ added in v0.38.0
type OpaqueTokenAuthenticator struct {
// contains filtered or unexported fields
}
OpaqueTokenAuthenticator validates a stateful opaque token by resolving it to a server-side session, returning the session's principal snapshot. When sliding renewal is enabled it extends the session's idle timeout on each request, so an active session never expires mid-use.
func (*OpaqueTokenAuthenticator) Authenticate ¶ added in v0.38.0
func (a *OpaqueTokenAuthenticator) Authenticate(ctx context.Context, authentication security.Authentication) (*security.Principal, error)
func (*OpaqueTokenAuthenticator) Supports ¶ added in v0.38.0
func (*OpaqueTokenAuthenticator) Supports(authType string) bool
type OpaqueTokenGenerator ¶ added in v0.38.0
type OpaqueTokenGenerator struct {
// contains filtered or unexported fields
}
OpaqueTokenGenerator issues stateful opaque tokens: it opens a server-side session (enforcing the per-account concurrency policy) and returns a random token whose hash keys that session. It carries no refresh token, since the session renews itself on use.
func NewOpaqueTokenGenerator ¶ added in v0.38.0
func NewOpaqueTokenGenerator(store security.SessionStore, policy security.SessionPolicy, notifier *security.SessionRevocationNotifier) *OpaqueTokenGenerator
func (*OpaqueTokenGenerator) Generate ¶ added in v0.38.0
func (g *OpaqueTokenGenerator) Generate(ctx context.Context, principal *security.Principal, meta security.SessionMeta) (*security.AuthTokens, error)
type PasswordAuthenticator ¶
type PasswordAuthenticator struct {
// contains filtered or unexported fields
}
PasswordAuthenticator verifies username/password credentials against a UserLoader. When a PasswordDecryptor is configured, the transmitted credential is treated as transport-encrypted (e.g. RSA-encrypted by the client before transmission) and decrypted to plaintext before verification; the password Encoder stays a plain KDF used identically for storage and comparison, so registration and reset flows that hash a server-side plaintext are unaffected.
func (*PasswordAuthenticator) Authenticate ¶
func (p *PasswordAuthenticator) Authenticate(ctx context.Context, authentication security.Authentication) (*security.Principal, error)
func (*PasswordAuthenticator) Supports ¶
func (*PasswordAuthenticator) Supports(authType string) bool
type RBACDataPermissionResolver ¶
type RBACDataPermissionResolver struct {
// contains filtered or unexported fields
}
RBACDataPermissionResolver implements role-based data permission resolution.
func (*RBACDataPermissionResolver) ResolveDataScope ¶
func (r *RBACDataPermissionResolver) ResolveDataScope( ctx context.Context, principal *security.Principal, permission string, ) (security.DataScope, error)
ResolveDataScope resolves the applicable DataScope for the given principal and permission token. When a user has multiple roles with the same permission token but different data scopes, the scope with the highest priority wins. Returns nil if no matching permission is found.
type RBACPermissionChecker ¶
type RBACPermissionChecker struct {
// contains filtered or unexported fields
}
func (*RBACPermissionChecker) HasPermission ¶
func (c *RBACPermissionChecker) HasPermission( ctx context.Context, principal *security.Principal, permissionToken string, ) (bool, error)
HasPermission uses sequential role loading rather than parallel to optimize for common case (1-3 roles).
type RefreshParams ¶
type RefreshParams struct {
api.P
RefreshToken string `json:"refreshToken" validate:"required" label_i18n:"auth_refresh_token"`
}
RefreshParams represents the request parameters for token refresh operation.
type ResolveChallengeParams ¶
type ResolveChallengeParams struct {
api.P
ChallengeToken string `json:"challengeToken" validate:"required" label_i18n:"auth_challenge_token"`
Type string `json:"type" validate:"required" label_i18n:"auth_challenge_type"`
Response any `json:"response" validate:"required" label_i18n:"auth_challenge_response"`
}
ResolveChallengeParams represents the request for resolving a login challenge.
type SignatureAuthenticator ¶
type SignatureAuthenticator struct {
// contains filtered or unexported fields
}
SignatureAuthenticator validates HMAC-based signatures for external app authentication.
func (*SignatureAuthenticator) Authenticate ¶
func (a *SignatureAuthenticator) Authenticate(ctx context.Context, authentication security.Authentication) (*security.Principal, error)
func (*SignatureAuthenticator) Supports ¶
func (*SignatureAuthenticator) Supports(authType string) bool
type TrustCodeAuthenticator ¶ added in v0.49.0
type TrustCodeAuthenticator struct {
// contains filtered or unexported fields
}
TrustCodeAuthenticator redeems the one-time code the trust-login gateway handed to the browser, completing the second leg of the handoff.
It is an ordinary Authenticator on purpose: redeeming the code is the only thing specific to trust login, and routing it through security/auth.login means the handoff inherits the whole pipeline — brute-force guard, the full challenge chain (a forced password change or department selection still runs; the external system authenticated the user, it did not satisfy the application's own login policy), token issuance under the configured mechanism, session concurrency, and the login audit event.
The authentication identifier is the app ID that initiated the handoff, checked here against the one the gateway recorded — so what reaches the lockout counter and the audit trail is a value the framework verified, not one the client asserted.
func NewTrustCodeAuthenticator ¶ added in v0.49.0
func NewTrustCodeAuthenticator(store security.TrustCodeStore, cfg config.TrustLoginConfig) *TrustCodeAuthenticator
NewTrustCodeAuthenticator creates the trust-login code authenticator.
func (*TrustCodeAuthenticator) Authenticate ¶ added in v0.49.0
func (a *TrustCodeAuthenticator) Authenticate(ctx context.Context, authentication security.Authentication) (*security.Principal, error)
func (*TrustCodeAuthenticator) Supports ¶ added in v0.49.0
func (*TrustCodeAuthenticator) Supports(authType string) bool
type TrustLoginMiddleware ¶ added in v0.49.0
type TrustLoginMiddleware struct {
// contains filtered or unexported fields
}
TrustLoginMiddleware mounts the trust-login gateway: the browser-facing route an external system links to, carrying a signed user identifier, which trades the handoff for a one-time code the SPA then redeems through the ordinary login endpoint.
Two legs rather than one is what keeps the signed URL harmless. The signature never reaches the browser's own code, an invalid one is refused at the gateway where a person can still be shown why, and the URL that does land in browser history carries only a code that is single-use and expires in seconds.
func (*TrustLoginMiddleware) Apply ¶ added in v0.49.0
func (m *TrustLoginMiddleware) Apply(router fiber.Router)
func (*TrustLoginMiddleware) Name ¶ added in v0.49.0
func (*TrustLoginMiddleware) Name() string
func (*TrustLoginMiddleware) Order ¶ added in v0.49.0
func (*TrustLoginMiddleware) Order() int
Order places the gateway alongside the framework's other real routes, after the API engine and before the SPA fallback.
type TrustLoginMiddlewareParams ¶ added in v0.49.0
type TrustLoginMiddlewareParams struct {
fx.In
Apps security.ExternalAppLoader `optional:"true"`
Resolver security.TrustUserResolver `optional:"true"`
Users security.UserLoader `optional:"true"`
Codes security.TrustCodeStore
Nonces security.NonceStore `optional:"true"`
Security *config.SecurityConfig
}
TrustLoginMiddlewareParams contains dependencies for the trust-login gateway.
Source Files
¶
- auth_manager.go
- auth_resource.go
- config_api_key_loader.go
- config_basic_account_loader.go
- config_ip_whitelist_loader.go
- errors.go
- external_app.go
- jwt_refresh_authenticator.go
- jwt_token_authenticator.go
- jwt_token_generator.go
- module.go
- opaque_token_authenticator.go
- opaque_token_generator.go
- password_authenticator.go
- rbac_data_permission_resolver.go
- rbac_permission_checker.go
- signature_authenticator.go
- trust_code_authenticator.go
- trust_login_middleware.go