auth

package
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Jul 16, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Index

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

func AuthorizeAction(ctx context.Context, ability string, resource any) error

AuthorizeAction checks the default gate and returns an error if denied.

func Can

func Can(ctx context.Context, ability string, resource any) bool

Can is a convenience function to check against the default gate.

func Cannot

func Cannot(ctx context.Context, ability string, resource any) bool

Cannot is the inverse of Can.

func DefineAbility

func DefineAbility(ability string, fn AbilityFunc)

DefineAbility shortcut to register on the default gate.

func DenyAll

func DenyAll() *bool

DenyAll short-circuits authorization to always deny.

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

func UserFrom[T any](c *http.Context) (T, error)

UserFrom is a typed helper that gets the authenticated user with a single call.

user, err := auth.UserFrom[*models.User](c)

func WithBearerToken

func WithBearerToken(ctx context.Context, token string) context.Context

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").

func WithUser

func WithUser(ctx context.Context, user User) context.Context

WithUser sets the user in the request context (used by guards after auth).

Types

type AbilityFunc

type AbilityFunc func(ctx context.Context, user User, resource any) bool

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

func NewAccessor(guard Guard, c *http.Context) *Accessor

NewAccessor creates an auth accessor for the given guard and request context.

func (*Accessor) Check

func (a *Accessor) Check() bool

func (*Accessor) Login

func (a *Accessor) Login(user any) error

func (*Accessor) Logout

func (a *Accessor) Logout() error

func (*Accessor) User

func (a *Accessor) User() (any, error)

type AfterFunc

type AfterFunc func(ctx context.Context, user User, ability string, result bool)

AfterFunc is called after every ability check with the result.

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

func (BasePolicy) Before(_ context.Context, _ User, _ string) *bool

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).

func (*BasicAuthGuard) Logout

func (g *BasicAuthGuard) Logout(_ context.Context) error

Logout is a no-op for basic auth (no server-side session).

func (*BasicAuthGuard) User

func (g *BasicAuthGuard) User(ctx context.Context) (User, error)

User extracts credentials from the Authorization header and validates them.

type BasicAuthValidator

type BasicAuthValidator func(ctx context.Context, username, password string) (User, error)

BasicAuthValidator validates username/password and returns the authenticated user or nil if invalid.

type BeforeFunc

type BeforeFunc func(ctx context.Context, user User, ability string) *bool

BeforeFunc is called before any ability check. Return *bool to short-circuit (true=allow, false=deny), or nil to continue.

type CanResetPassword

type CanResetPassword interface {
	User
	GetEmail() string
}

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.

func (*EmailVerifier) Verify

func (v *EmailVerifier) Verify(ctx context.Context, userID, token string) error

Verify checks the token and marks the user's email as verified.

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 DefaultGate

func DefaultGate() *Gate

DefaultGate returns the global gate instance.

func NewGate

func NewGate() *Gate

NewGate creates a new authorization gate.

func (*Gate) After

func (g *Gate) After(fn AfterFunc)

After registers a global after hook. Runs after every authorization check.

func (*Gate) Allows

func (g *Gate) Allows(ctx context.Context, user User, ability string, resource any) bool

Allows checks if the user is authorized for the given ability.

func (*Gate) Any

func (g *Gate) Any(ctx context.Context, user User, abilities []string, resource any) bool

Any returns true if the user can perform any of the given abilities.

func (*Gate) Authorize

func (g *Gate) Authorize(ctx context.Context, user User, ability string, resource any) error

Authorize checks authorization and returns an error if denied.

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) Denies

func (g *Gate) Denies(ctx context.Context, user User, ability string, resource any) bool

Denies is the inverse of Allows.

func (*Gate) ForUser

func (g *Gate) ForUser(user User) *UserGate

ForUser returns a UserGate scoped to the given user for convenience.

func (*Gate) None

func (g *Gate) None(ctx context.Context, user User, abilities []string, resource any) bool

None returns true if the user cannot perform any of the given abilities.

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

func NewJWTDriver(secret string) *JWTDriver

func (*JWTDriver) Generate

func (d *JWTDriver) Generate(claims map[string]any, expiresAt time.Time) (string, error)

func (*JWTDriver) Parse

func (d *JWTDriver) Parse(tokenStr string) (map[string]any, error)

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.

func (*PasetoDriver) Generate

func (d *PasetoDriver) Generate(claims map[string]any, expiresAt time.Time) (string, error)

func (*PasetoDriver) Parse

func (d *PasetoDriver) Parse(tokenStr string) (map[string]any, error)

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 (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

type PolicyFunc func(ctx context.Context, user User, action string, resource any) bool

PolicyFunc adapts a function to Policy.

func (PolicyFunc) Allow

func (f PolicyFunc) Allow(ctx context.Context, user User, action string, resource any) bool

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).

func (*SessionGuard) Logout

func (g *SessionGuard) Logout(ctx context.Context) error

Logout removes the user from session.

func (*SessionGuard) User

func (g *SessionGuard) User(ctx context.Context) (User, error)

User returns the user from session. With loader: loads from DB via session user_id. Without loader: uses in-memory map (legacy, keyed by session_id).

type StatelessGuard

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

func NewStatelessGuard

func NewStatelessGuard(driver TokenDriver, loader UserLoader) *StatelessGuard

func (*StatelessGuard) GenerateToken

func (g *StatelessGuard) GenerateToken(userID string, expiresIn time.Duration) (string, error)

GenerateToken creates a new token for the user using the configured driver.

func (*StatelessGuard) Login

func (g *StatelessGuard) Login(_ context.Context, _ User) error

func (*StatelessGuard) Logout

func (g *StatelessGuard) Logout(_ context.Context) error

func (*StatelessGuard) User

func (g *StatelessGuard) User(ctx context.Context) (User, error)

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

func (g *TokenGuard) RevokeToken(ctx context.Context, userID string, tokenID uint) error

RevokeToken deletes a token by ID for the given user.

func (*TokenGuard) User

func (g *TokenGuard) User(ctx context.Context) (User, error)

User extracts the Bearer token from the request context, looks it up in the database, and returns the associated user. Returns (nil, nil) if no token is present.

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

func UserFromContext(ctx context.Context) User

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.

func (*UserGate) Authorize

func (ug *UserGate) Authorize(ctx context.Context, ability string, resource any) error

Authorize checks authorization and returns an error if denied.

func (*UserGate) Can

func (ug *UserGate) Can(ctx context.Context, ability string, resource any) bool

Can checks if the user is authorized.

func (*UserGate) Cannot

func (ug *UserGate) Cannot(ctx context.Context, ability string, resource any) bool

Cannot checks if the user is NOT authorized.

type UserLoader

type UserLoader interface {
	LoadUser(ctx context.Context, id string) (User, error)
}

UserLoader loads a user by ID (e.g. from database).

type UserLoaderFunc

type UserLoaderFunc func(ctx context.Context, id string) (User, error)

UserLoaderFunc adapts a function to UserLoader.

func (UserLoaderFunc) LoadUser

func (f UserLoaderFunc) LoadUser(ctx context.Context, id string) (User, error)

Directories

Path Synopsis
Package socialite provides OAuth2-based social authentication (similar to Laravel Socialite).
Package socialite provides OAuth2-based social authentication (similar to Laravel Socialite).

Jump to

Keyboard shortcuts

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