Documentation
¶
Overview ¶
Package passport is an OAuth2 authorization server for Nimbus, modeled on Laravel Passport. It lets your app issue OAuth2 tokens to third-party (and first-party) clients, supporting the authorization_code (with PKCE), client_credentials, and refresh_token grants, plus token introspection and revocation.
app.Use(passport.NewPlugin(db, passport.Config{}))
Then protect resource routes with the access-token middleware:
srv := app.Container.MustMake("passport").(*passport.Server)
api := app.Router.Group("/api", passport.RequireAccessToken(srv))
api.Use(passport.RequireScope("read:profile"))
Layout:
passport.go – plugin + wiring config.go – Config server.go – OAuth2 core routes.go – authorize/token/introspect/revoke middleware.go – resource server models/ – clients, codes, tokens views/ – consent screen
Index ¶
- Constants
- Variables
- func AccessTokenFrom(ctx context.Context) *models.OAuthAccessToken
- func RequireAccessToken(s *Server) router.Middleware
- func RequireScope(scope string) router.Middleware
- func WithAccessToken(ctx context.Context, at *models.OAuthAccessToken) context.Context
- type AuthorizeRequest
- type Config
- type NewClientResult
- type Plugin
- func (p *Plugin) Boot(app *nimbus.App) error
- func (p *Plugin) DefaultConfig() map[string]any
- func (p *Plugin) Migrations() []database.Migration
- func (p *Plugin) Register(app *nimbus.App) error
- func (p *Plugin) RegisterRoutes(r *router.Router)
- func (p *Plugin) Server() *Server
- func (p *Plugin) ViewsFS() fs.FS
- type Server
- func (s *Server) ClientCredentials(ctx context.Context, clientID, clientSecret, scope string) (*TokenResponse, error)
- func (s *Server) CreateClient(ctx context.Context, name, ownerUserID string, ...) (*NewClientResult, error)
- func (s *Server) ExchangeAuthCode(ctx context.Context, ...) (*TokenResponse, error)
- func (s *Server) IssueAuthCode(ctx context.Context, req *AuthorizeRequest, userID string) (string, error)
- func (s *Server) Refresh(ctx context.Context, clientID, clientSecret, refreshToken, scope string) (*TokenResponse, error)
- func (s *Server) RevokeAccessToken(ctx context.Context, plain string) error
- func (s *Server) ValidateAccessToken(ctx context.Context, plain string) (*models.OAuthAccessToken, error)
- func (s *Server) ValidateAuthorize(ctx context.Context, ...) (*AuthorizeRequest, error)
- type TokenResponse
Constants ¶
const ( GrantAuthorizationCode = "authorization_code" GrantClientCredentials = "client_credentials" GrantRefreshToken = "refresh_token" )
Grant type constants (RFC 6749 + PKCE).
Variables ¶
var ( ErrInvalidClient = errors.New("invalid_client") ErrInvalidGrant = errors.New("invalid_grant") ErrInvalidScope = errors.New("invalid_scope") ErrUnsupportedGrant = errors.New("unsupported_grant_type") ErrInvalidRequest = errors.New("invalid_request") )
OAuth errors surfaced to callers and mapped to RFC 6749 error codes by routes.go.
Functions ¶
func AccessTokenFrom ¶
func AccessTokenFrom(ctx context.Context) *models.OAuthAccessToken
AccessTokenFrom returns the validated access token from a context, or nil.
func RequireAccessToken ¶
func RequireAccessToken(s *Server) router.Middleware
RequireAccessToken returns middleware that authenticates the request via an OAuth2 Bearer access token and stores the token record on the context. Returns 401 with a WWW-Authenticate header when the token is missing or invalid.
func RequireScope ¶
func RequireScope(scope string) router.Middleware
RequireScope returns middleware that enforces the current access token was granted a scope. Must be chained after RequireAccessToken. Returns 403 otherwise.
func WithAccessToken ¶
WithAccessToken stores the validated access token on a context.
Types ¶
type AuthorizeRequest ¶
type AuthorizeRequest struct {
Client *models.OAuthClient
RedirectURI string
Scopes []string
State string
CodeChallenge string
CodeChallengeMethod string
}
AuthorizeRequest captures a validated /oauth/authorize request.
type Config ¶
type Config struct {
// RoutePrefix is where the OAuth endpoints mount. Default "/oauth".
RoutePrefix string
// AccessTokenTTL is how long issued access tokens live. Default 1h.
AccessTokenTTL time.Duration
// RefreshTokenTTL is how long refresh tokens live. Default 30 days.
RefreshTokenTTL time.Duration
// AuthCodeTTL is how long an authorization code is valid. Default 10m.
AuthCodeTTL time.Duration
// ConsentView is the .nimbus template rendered on the consent screen.
// Default "oauth-authorize" (bundled). It receives: client_name, scopes
// ([]string), and the raw authorize query params for the approve form.
ConsentView string
// AllowPublicClientsWithoutPKCE, when true, lets public clients run the
// authorization_code grant without a code_challenge. The default (false)
// enforces PKCE for public clients, matching OAuth 2.1.
AllowPublicClientsWithoutPKCE bool
}
Config tunes the OAuth2 server. Zero values fall back to sane defaults.
type NewClientResult ¶
type NewClientResult struct {
PlainSecret string `json:"secret"`
Client models.OAuthClient `json:"client"`
}
NewClientResult carries the plaintext secret (shown once) plus the record.
type Plugin ¶
type Plugin struct {
nimbus.BasePlugin
// contains filtered or unexported fields
}
Plugin wires the OAuth2 server into Nimbus.
func (*Plugin) DefaultConfig ¶
func (*Plugin) Migrations ¶
Migrations creates the OAuth tables (clients, codes, access/refresh tokens).
func (*Plugin) RegisterRoutes ¶
RegisterRoutes mounts the OAuth2 endpoints under the configured prefix:
GET /oauth/authorize consent screen (user must be logged in) POST /oauth/authorize approve/deny → redirect back with ?code= POST /oauth/token exchange grant for tokens POST /oauth/introspect RFC 7662 token introspection (client-authenticated) POST /oauth/revoke RFC 7009 token revocation
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the OAuth2 authorization server. Resolve it from the container ("passport") or hold the plugin's instance.
func (*Server) ClientCredentials ¶
func (s *Server) ClientCredentials(ctx context.Context, clientID, clientSecret, scope string) (*TokenResponse, error)
ClientCredentials runs the client_credentials grant (machine-to-machine).
func (*Server) CreateClient ¶
func (s *Server) CreateClient(ctx context.Context, name, ownerUserID string, redirects, grants, scopes []string, confidential bool) (*NewClientResult, error)
CreateClient registers an OAuth client. For a confidential client a random secret is generated and returned once (stored hashed). Pass confidential=false for public clients (no secret; PKCE required on the auth-code grant).
func (*Server) ExchangeAuthCode ¶
func (s *Server) ExchangeAuthCode(ctx context.Context, clientID, clientSecret, code, redirectURI, codeVerifier string) (*TokenResponse, error)
ExchangeAuthCode runs the authorization_code grant: validates the code, client, redirect, and PKCE verifier, then issues access + refresh tokens.
func (*Server) IssueAuthCode ¶
func (s *Server) IssueAuthCode(ctx context.Context, req *AuthorizeRequest, userID string) (string, error)
IssueAuthCode persists a single-use authorization code for an approved request and returns the plaintext code to redirect back to the client.
func (*Server) Refresh ¶
func (s *Server) Refresh(ctx context.Context, clientID, clientSecret, refreshToken, scope string) (*TokenResponse, error)
Refresh runs the refresh_token grant, rotating the refresh token.
func (*Server) RevokeAccessToken ¶
RevokeAccessToken revokes a token by its plaintext value (RFC 7009).
func (*Server) ValidateAccessToken ¶
func (s *Server) ValidateAccessToken(ctx context.Context, plain string) (*models.OAuthAccessToken, error)
ValidateAccessToken resolves a plaintext bearer token to a live, non-revoked, non-expired access-token record. Returns ErrInvalidGrant otherwise.
func (*Server) ValidateAuthorize ¶
func (s *Server) ValidateAuthorize(ctx context.Context, clientID, responseType, redirectURI, scope, state, challenge, method string) (*AuthorizeRequest, error)
ValidateAuthorize checks an incoming authorization request: client exists, response_type=code, redirect is allowlisted, scopes are permitted, and PKCE is present when required. It does NOT issue a code (the user must approve first).
type TokenResponse ¶
type TokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"` // always "Bearer"
ExpiresIn int `json:"expires_in"` // seconds
RefreshToken string `json:"refresh_token,omitempty"`
Scope string `json:"scope,omitempty"`
}
TokenResponse is the RFC 6749 token endpoint success body.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package models holds the persisted Passport (OAuth2 server) tables: clients, authorization codes, access tokens, and refresh tokens.
|
Package models holds the persisted Passport (OAuth2 server) tables: clients, authorization codes, access tokens, and refresh tokens. |