Documentation
¶
Index ¶
- func AllowAll() *bool
- func AuthorizeAction(ctx context.Context, ability string, resource any) error
- func Can(ctx context.Context, ability string, resource any) bool
- func Cannot(ctx context.Context, ability string, resource any) bool
- func DefineAbility(ability string, fn AbilityFunc)
- func DenyAll() *bool
- func Init(containerKey ...string) router.Middleware
- func OptionalToken(guard *TokenGuard) router.Middleware
- func RequireAbility(ability string) router.Middleware
- func RequireAllAbilities(abilities ...string) router.Middleware
- func RequireAnyAbility(abilities ...string) router.Middleware
- func RequireAuth(guard Guard, redirectTo string) router.Middleware
- func RequireBasicAuth(guard *BasicAuthGuard) router.Middleware
- func RequireStatelessToken(guard *StatelessGuard) router.Middleware
- func RequireToken(guard *TokenGuard) router.Middleware
- func RequireVerifiedEmail(redirectTo string) router.Middleware
- func UserFrom[T any](c *http.Context) (T, error)
- func WithBearerToken(ctx context.Context, token string) context.Context
- func WithTokenRecord(ctx context.Context, pat *PersonalAccessToken) context.Context
- func WithUser(ctx context.Context, user User) context.Context
- type AbilityFunc
- type Accessor
- type AfterFunc
- type BasePolicy
- type BasicAuthGuard
- type BasicAuthValidator
- type BeforeFunc
- type CanResetPassword
- type EmailVerifier
- type EmailVerifierStore
- type Gate
- func (g *Gate) After(fn AfterFunc)
- func (g *Gate) Allows(ctx context.Context, user User, ability string, resource any) bool
- func (g *Gate) Any(ctx context.Context, user User, abilities []string, resource any) bool
- func (g *Gate) Authorize(ctx context.Context, user User, ability string, resource any) error
- func (g *Gate) Before(fn BeforeFunc)
- func (g *Gate) Define(ability string, fn AbilityFunc)
- func (g *Gate) Denies(ctx context.Context, user User, ability string, resource any) bool
- func (g *Gate) ForUser(user User) *UserGate
- func (g *Gate) None(ctx context.Context, user User, abilities []string, resource any) bool
- func (g *Gate) RegisterPolicy(name string, policy ResourcePolicy)
- type Guard
- type JWTDriver
- type MustVerifyEmail
- type NewAccessToken
- type PasetoDriver
- type PasswordResetBroker
- type PasswordResetter
- type PersonalAccessToken
- type Policy
- type PolicyFunc
- type ResourcePolicy
- type SessionGuard
- type StatelessGuard
- type TokenDriver
- type TokenGuard
- func (g *TokenGuard) CreateToken(ctx context.Context, userID, name, abilities string, expiresAt *time.Time) (*NewAccessToken, error)
- func (g *TokenGuard) ListTokens(ctx context.Context, userID string) ([]PersonalAccessToken, error)
- func (g *TokenGuard) Login(_ context.Context, _ User) error
- func (g *TokenGuard) Logout(_ context.Context) error
- func (g *TokenGuard) RevokeAllTokens(ctx context.Context, userID string) error
- func (g *TokenGuard) RevokeToken(ctx context.Context, userID string, tokenID uint) error
- func (g *TokenGuard) User(ctx context.Context) (User, error)
- type TokenStore
- type User
- type UserGate
- type UserLoader
- type UserLoaderFunc
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AllowAll ¶
func AllowAll() *bool
AllowAll short-circuits authorization to always allow (useful for admins).
func AuthorizeAction ¶
AuthorizeAction checks the default gate and returns an error if denied.
func DefineAbility ¶
func DefineAbility(ability string, fn AbilityFunc)
DefineAbility shortcut to register on the default gate.
func Init ¶
func Init(containerKey ...string) router.Middleware
Init returns middleware that resolves the auth guard from the container and sets c.Auth() for AdonisJS-style access. Use as a global middleware:
app.Router.Use(auth.Init("auth.guard"))
Then in any controller:
user, err := c.Auth().User() c.Auth().Login(user) c.Auth().Check()
Or with the typed generic helper:
user, err := auth.UserFrom[*models.User](c)
func OptionalToken ¶
func OptionalToken(guard *TokenGuard) router.Middleware
OptionalToken is like RequireToken but does not return 401 when no token is present. It simply passes through. Useful for endpoints that work for both authenticated and unauthenticated users.
func RequireAbility ¶
func RequireAbility(ability string) router.Middleware
RequireAbility returns middleware that checks if the current token has a specific ability (scope). Must be used after RequireToken.
Example:
api.Use(auth.RequireToken(tokenGuard))
api.Use(auth.RequireAbility("read:projects"))
func RequireAllAbilities ¶
func RequireAllAbilities(abilities ...string) router.Middleware
RequireAllAbilities returns middleware that passes only when the current token has EVERY one of the given abilities (AND semantics). Must be used after RequireToken. Mirrors Laravel Sanctum's `ability:a,b` middleware.
Example:
api.Use(auth.RequireAllAbilities("read:projects", "write:projects"))
func RequireAnyAbility ¶
func RequireAnyAbility(abilities ...string) router.Middleware
RequireAnyAbility returns middleware that passes when the current token has at least ONE of the given abilities (OR semantics). Must be used after RequireToken. Mirrors Laravel Sanctum's `abilities:a,b` middleware.
Example:
api.Use(auth.RequireAnyAbility("read:projects", "admin"))
func RequireAuth ¶
func RequireAuth(guard Guard, redirectTo string) router.Middleware
RequireAuth returns middleware that loads the user from the guard and sets it on the request context. If no user and redirectTo is non-empty, redirects; else returns 401.
func RequireBasicAuth ¶
func RequireBasicAuth(guard *BasicAuthGuard) router.Middleware
RequireBasicAuth returns middleware that enforces HTTP basic authentication. If credentials are invalid, a 401 response with WWW-Authenticate header is sent, prompting the browser to show its built-in login dialog.
func RequireStatelessToken ¶
func RequireStatelessToken(guard *StatelessGuard) router.Middleware
RequireStatelessToken returns middleware that reads the Authorization: Bearer <token> header, authenticates the request via the StatelessGuard, and stores the user on the request context.
func RequireToken ¶
func RequireToken(guard *TokenGuard) router.Middleware
RequireToken returns middleware that reads the Authorization: Bearer <token> header, authenticates the request via the TokenGuard, and stores both the user and the token record on the request context.
If no valid token is found, it returns 401 Unauthorized.
func RequireVerifiedEmail ¶
func RequireVerifiedEmail(redirectTo string) router.Middleware
RequireVerifiedEmail middleware rejects requests from unverified users. Must be used after RequireAuth middleware.
func UserFrom ¶
UserFrom is a typed helper that gets the authenticated user with a single call.
user, err := auth.UserFrom[*models.User](c)
func WithBearerToken ¶
WithBearerToken stores the plain-text bearer token in context.
func WithTokenRecord ¶
func WithTokenRecord(ctx context.Context, pat *PersonalAccessToken) context.Context
WithTokenRecord stores the PersonalAccessToken in context so handlers can check abilities via CurrentToken(ctx).HasAbility("scope").
Types ¶
type AbilityFunc ¶
AbilityFunc checks if a user can perform an ability on a resource.
type Accessor ¶
type Accessor struct {
// contains filtered or unexported fields
}
Accessor provides AdonisJS-style auth access bound to a single request. It implements http.Authenticator so controllers can write:
user, err := c.Auth().User()
c.Auth().Login(&user)
c.Auth().Logout()
if c.Auth().Check() { ... }
func NewAccessor ¶
NewAccessor creates an auth accessor for the given guard and request context.
type BasePolicy ¶
type BasePolicy struct{}
BasePolicy provides a default ResourceName from the struct and a Before hook that returns nil (no override).
func (BasePolicy) Before ¶
Before is called before any ability check. Return:
- (*bool)(true) to always allow
- (*bool)(false) to always deny
- nil to fall through to the specific ability check
func (BasePolicy) ResourceName ¶
func (BasePolicy) ResourceName() string
type BasicAuthGuard ¶
type BasicAuthGuard struct {
Realm string
Validate BasicAuthValidator
}
BasicAuthGuard implements the HTTP Basic authentication framework. The client sends credentials as a base64-encoded string in the Authorization header with each request.
Basic authentication is not recommended for production applications because credentials are sent with every request and the user experience is limited to the browser's built-in prompt. However, it can be useful during early development or for internal tools.
func NewBasicAuthGuard ¶
func NewBasicAuthGuard(realm string, validate BasicAuthValidator) *BasicAuthGuard
NewBasicAuthGuard creates a new basic auth guard.
guard := auth.NewBasicAuthGuard("Restricted", func(ctx context.Context, user, pass string) (auth.User, error) {
return myUserLoader(ctx, user, pass)
})
func (*BasicAuthGuard) Login ¶
func (g *BasicAuthGuard) Login(_ context.Context, _ User) error
Login is a no-op for basic auth (credentials are sent per-request).
type BasicAuthValidator ¶
BasicAuthValidator validates username/password and returns the authenticated user or nil if invalid.
type BeforeFunc ¶
BeforeFunc is called before any ability check. Return *bool to short-circuit (true=allow, false=deny), or nil to continue.
type CanResetPassword ¶
CanResetPassword should be implemented by the User model.
type EmailVerifier ¶
type EmailVerifier struct {
// contains filtered or unexported fields
}
EmailVerifier orchestrates the email-verification flow.
func NewEmailVerifier ¶
func NewEmailVerifier(secret string, ttl time.Duration, store EmailVerifierStore, mailer mail.Driver, fromAddr, verifyURL string) *EmailVerifier
NewEmailVerifier creates a verifier.
- secret: HMAC key (use APP_KEY).
- ttl: token validity (e.g. 24*time.Hour).
- verifyURL: your verification endpoint, e.g. "https://app.com/verify-email".
func (*EmailVerifier) Cleanup ¶
func (v *EmailVerifier) Cleanup()
Cleanup removes expired tokens. Call via scheduler.
func (*EmailVerifier) SendVerification ¶
func (v *EmailVerifier) SendVerification(ctx context.Context, user MustVerifyEmail) error
SendVerification generates a token and sends the verification email.
type EmailVerifierStore ¶
type EmailVerifierStore interface {
FindByID(ctx context.Context, id string) (MustVerifyEmail, error)
}
EmailVerifierStore looks up users for the verification flow.
type Gate ¶
type Gate struct {
// contains filtered or unexported fields
}
Gate is an authorization gate that manages policies and can check abilities. It is the central authorization registry (similar to Laravel's Gate facade).
func (*Gate) Before ¶
func (g *Gate) Before(fn BeforeFunc)
Before registers a global before hook. Runs before every authorization check.
func (*Gate) Define ¶
func (g *Gate) Define(ability string, fn AbilityFunc)
Define registers a named ability check.
gate.Define("edit-post", func(ctx context.Context, user auth.User, resource any) bool {
post := resource.(*Post)
return user.GetID() == post.AuthorID
})
func (*Gate) RegisterPolicy ¶
func (g *Gate) RegisterPolicy(name string, policy ResourcePolicy)
RegisterPolicy registers a resource policy.
gate.RegisterPolicy("post", &PostPolicy{})
type Guard ¶
type Guard interface {
User(ctx context.Context) (User, error)
Login(ctx context.Context, user User) error
Logout(ctx context.Context) error
}
Guard authenticates requests and returns the current user (plan: auth:web, auth:api).
type JWTDriver ¶
type JWTDriver struct {
// contains filtered or unexported fields
}
func NewJWTDriver ¶
type MustVerifyEmail ¶
type MustVerifyEmail interface {
User
GetEmail() string
HasVerifiedEmail() bool
MarkEmailAsVerified() error
}
MustVerifyEmail should be implemented by User models that require email verification.
type NewAccessToken ¶
type NewAccessToken struct {
PlainText string `json:"token"`
Token PersonalAccessToken `json:"access_token"`
}
NewAccessToken holds the plain-text token (shown once) plus the DB record.
type PasetoDriver ¶
type PasetoDriver struct {
// contains filtered or unexported fields
}
func NewPasetoDriver ¶
func NewPasetoDriver(keyStr string) *PasetoDriver
NewPasetoDriver builds a PASETO v4.local driver from keyStr. For strong security keyStr should be 32 random bytes encoded as 64 hex characters.
If keyStr is not valid hex, a raw 32-byte key is accepted as-is; any other input is hashed with SHA-256 to a deterministic 32-byte key. This guarantees a valid, input-derived key is always used — the previous implementation silently discarded the error and could fall back to a zero/garbage key, weakening every token without any signal.
type PasswordResetBroker ¶
type PasswordResetBroker struct {
// contains filtered or unexported fields
}
PasswordResetBroker orchestrates the password-reset flow.
func NewPasswordResetBroker ¶
func NewPasswordResetBroker(secret string, ttl time.Duration, resetter PasswordResetter, mailer mail.Driver, fromAddr, resetURL string) *PasswordResetBroker
NewPasswordResetBroker creates a broker.
- secret: HMAC key for token hashing (use APP_KEY).
- ttl: token validity duration (e.g. 60*time.Minute).
- resetURL: your frontend/reset endpoint, e.g. "https://app.com/reset-password".
func (*PasswordResetBroker) Cleanup ¶
func (b *PasswordResetBroker) Cleanup()
Cleanup removes expired tokens. Call via scheduler.
func (*PasswordResetBroker) Reset ¶
func (b *PasswordResetBroker) Reset(ctx context.Context, email, token, newPassword string) error
Reset verifies the token and resets the user's password.
func (*PasswordResetBroker) SendResetLink ¶
func (b *PasswordResetBroker) SendResetLink(ctx context.Context, email string) error
SendResetLink generates a token and sends the reset email.
type PasswordResetter ¶
type PasswordResetter interface {
// FindByEmail returns the user for the given email, or nil+error.
FindByEmail(ctx context.Context, email string) (CanResetPassword, error)
// ResetPassword hashes and stores the new password for the user.
ResetPassword(ctx context.Context, user CanResetPassword, newPassword string) error
}
PasswordResetter looks up a user by email (implemented by the app).
type PersonalAccessToken ¶
type PersonalAccessToken struct {
ID uint `gorm:"primaryKey" json:"id"`
UserID string `gorm:"index;not null" json:"user_id"`
Name string `gorm:"not null" json:"name"`
Token string `gorm:"uniqueIndex;size:64;not null" json:"-"` // SHA-256 hash
Abilities string `gorm:"type:text;default:'[\"*\"]'" json:"abilities"`
LastUsedAt *time.Time `json:"last_used_at"`
ExpiresAt *time.Time `json:"expires_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt lucid.DeletedAt `gorm:"index" json:"-"`
}
PersonalAccessToken represents an API token stored in the database. Tokens are stored as SHA-256 hashes; the plain-text token is only available once — at creation time.
func CurrentToken ¶
func CurrentToken(ctx context.Context) *PersonalAccessToken
CurrentToken returns the PersonalAccessToken from context, or nil.
func (*PersonalAccessToken) HasAbility ¶
func (t *PersonalAccessToken) HasAbility(ability string) bool
HasAbility checks if the token has a specific ability (Sanctum-style JSON array). Supports the wildcard "*" which grants all abilities.
func (*PersonalAccessToken) HasAllAbilities ¶
func (t *PersonalAccessToken) HasAllAbilities(abilities ...string) bool
HasAllAbilities returns true only if the token has every one of the given abilities. The wildcard "*" grants all. Mirrors Laravel Sanctum's `ability:a,b` route middleware (AND semantics).
func (*PersonalAccessToken) HasAnyAbility ¶
func (t *PersonalAccessToken) HasAnyAbility(abilities ...string) bool
HasAnyAbility returns true if the token has at least one of the given abilities. The wildcard "*" grants all. Mirrors Laravel Sanctum's `abilities:a,b` route middleware (OR semantics).
func (*PersonalAccessToken) IsExpired ¶
func (t *PersonalAccessToken) IsExpired() bool
IsExpired returns true if the token has passed its expiration time.
func (PersonalAccessToken) TableName ¶
func (PersonalAccessToken) TableName() string
TableName returns the database table name.
type Policy ¶
type Policy interface {
// Allow returns true if the user can perform the action on the resource.
Allow(ctx context.Context, user User, action string, resource any) bool
}
Policy checks if a user can perform an action (plan: userPolicy.Update(user)).
type PolicyFunc ¶
PolicyFunc adapts a function to Policy.
type ResourcePolicy ¶
type ResourcePolicy interface {
// ResourceName returns the name used for gate lookups (e.g. "post", "comment").
ResourceName() string
}
ResourcePolicy defines authorization methods for a specific resource type. Implement the methods you need; unimplemented methods default to false.
Example:
type PostPolicy struct{ auth.BasePolicy }
func (p *PostPolicy) View(ctx context.Context, user auth.User, post *Post) bool { return true }
func (p *PostPolicy) Update(ctx context.Context, user auth.User, post *Post) bool {
return user.GetID() == post.AuthorID
}
type SessionGuard ¶
type SessionGuard struct {
// contains filtered or unexported fields
}
SessionGuard uses the session store to persist user ID. Requires session.Middleware to run first. Use NewSessionGuardWithLoader for production (loads user from DB). NewSessionGuard keeps in-memory for backward compat.
func NewSessionGuard ¶
func NewSessionGuard() *SessionGuard
NewSessionGuard returns an in-memory session guard (backward compatible). Sessions lost on restart.
func NewSessionGuardWithLoader ¶
func NewSessionGuardWithLoader(loader UserLoader) *SessionGuard
NewSessionGuardWithLoader returns a guard that uses session store + user loader (persistent auth).
func (*SessionGuard) Login ¶
func (g *SessionGuard) Login(ctx context.Context, user User) error
Login stores user in session (or in-memory for legacy).
type StatelessGuard ¶
type StatelessGuard struct {
// contains filtered or unexported fields
}
func NewStatelessGuard ¶
func NewStatelessGuard(driver TokenDriver, loader UserLoader) *StatelessGuard
func (*StatelessGuard) GenerateToken ¶
GenerateToken creates a new token for the user using the configured driver.
type TokenDriver ¶
type TokenDriver interface {
Generate(claims map[string]any, expiresAt time.Time) (string, error)
Parse(token string) (map[string]any, error)
}
TokenDriver defines the interface for stateless token strategies.
type TokenGuard ¶
type TokenGuard struct {
// contains filtered or unexported fields
}
TokenGuard authenticates requests via Bearer tokens (personal access tokens). It reads the Authorization header and looks up the hashed token in the DB.
func NewTokenGuard ¶
func NewTokenGuard(db *lucid.DB, loader UserLoader) *TokenGuard
NewTokenGuard creates a new API token guard. db is the GORM database handle. loader loads a User by ID from the database.
func (*TokenGuard) CreateToken ¶
func (g *TokenGuard) CreateToken(ctx context.Context, userID, name, abilities string, expiresAt *time.Time) (*NewAccessToken, error)
CreateToken generates a new personal access token for the given user. The plain-text token is returned in NewAccessToken.PlainText and is only available at creation time — it is stored hashed in the database.
abilities is a JSON array string, e.g. `["read:projects","write:projects"]`. Pass `["*"]` or empty string for full access. expiresAt may be nil for non-expiring tokens.
func (*TokenGuard) ListTokens ¶
func (g *TokenGuard) ListTokens(ctx context.Context, userID string) ([]PersonalAccessToken, error)
ListTokens returns all active (non-expired) tokens for a user.
func (*TokenGuard) Login ¶
func (g *TokenGuard) Login(_ context.Context, _ User) error
Login is a no-op for token-based auth (tokens are created explicitly via CreateToken).
func (*TokenGuard) Logout ¶
func (g *TokenGuard) Logout(_ context.Context) error
Logout is a no-op for token-based auth (tokens are revoked explicitly).
func (*TokenGuard) RevokeAllTokens ¶
func (g *TokenGuard) RevokeAllTokens(ctx context.Context, userID string) error
RevokeAllTokens deletes all tokens for a user.
func (*TokenGuard) RevokeToken ¶
RevokeToken deletes a token by ID for the given user.
type TokenStore ¶
type TokenStore struct {
// contains filtered or unexported fields
}
TokenStore manages token creation, hashing, and verification. Tokens are stored hashed; only the plaintext is returned once at creation.
func NewTokenStore ¶
func NewTokenStore(secret string, ttl time.Duration) *TokenStore
NewTokenStore creates a token store with the given HMAC secret and token TTL.
func (*TokenStore) Cleanup ¶
func (s *TokenStore) Cleanup()
Cleanup removes all expired tokens. Call periodically (e.g. via scheduler).
func (*TokenStore) Create ¶
func (s *TokenStore) Create(userID string) (string, error)
Create generates a new token for the given user ID. Returns the plaintext token. The store keeps only the hash.
func (*TokenStore) Delete ¶
func (s *TokenStore) Delete(userID string)
Delete removes a stored token for the user.
func (*TokenStore) Exists ¶
func (s *TokenStore) Exists(userID string) bool
Exists checks if a non-expired token exists for the user.
func (*TokenStore) Verify ¶
func (s *TokenStore) Verify(userID, plaintext string) bool
Verify checks the plaintext token against the stored hash for the user. Returns true and deletes the token on success.
type User ¶
type User interface {
GetID() string
}
User is the authenticated user interface (apps implement this).
func UserFromContext ¶
UserFromContext returns the authenticated user from context, or nil.
type UserGate ¶
type UserGate struct {
// contains filtered or unexported fields
}
UserGate wraps a Gate for a specific user for convenient fluent checks.
type UserLoader ¶
UserLoader loads a user by ID (e.g. from database).