Documentation
¶
Index ¶
- Constants
- func AuthServerMetadataHandler(issuerURL string) http.HandlerFunc
- func DiscoveryHandler(issuerURL string) http.HandlerFunc
- func IsCIMD(clientID string) bool
- func JWKSHandler(keysFn func() map[string]*rsa.PublicKey) http.HandlerFunc
- func MintRegistrationToken(ctx context.Context, pool *pgxpool.Pool, maxUses int, ttl time.Duration) (string, error)
- func NewOAuth2Provider(storage *Storage, issuerURL string, activeKey func() *rsa.PrivateKey, ...) fosite.OAuth2Provider
- func NewSession(subject string) *openid.DefaultSession
- func SameOrigin(r *http.Request) bool
- func SetSigningKID(kid string)
- type AccountHandler
- type ActorResolver
- type AdminHandler
- type CIMDResolver
- type ConsentHandler
- func (ch *ConsentHandler) LoginPage(w http.ResponseWriter, r *http.Request)
- func (ch *ConsentHandler) LoginSubmit(w http.ResponseWriter, r *http.Request)
- func (ch *ConsentHandler) LogoutHandler(w http.ResponseWriter, r *http.Request)
- func (ch *ConsentHandler) RegisterPage(w http.ResponseWriter, r *http.Request)
- func (ch *ConsentHandler) RegisterSubmit(w http.ResponseWriter, r *http.Request)
- type DiscoveryDocument
- type Handler
- func (h *Handler) AuthorizeHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) IntrospectHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) RevokeHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) SetExchanger(ex *TokenExchanger)
- func (h *Handler) TokenHandler(w http.ResponseWriter, r *http.Request)
- func (h *Handler) UserinfoHandler(w http.ResponseWriter, r *http.Request)
- type JWK
- type JWKSResponse
- type LiveHandler
- type Registrar
- type Session
- type SessionManager
- func (sm *SessionManager) CSRFToken(s *Session) string
- func (sm *SessionManager) Create(ctx context.Context, userID string, r *http.Request) (*Session, error)
- func (sm *SessionManager) Delete(ctx context.Context, w http.ResponseWriter, r *http.Request) error
- func (sm *SessionManager) Get(ctx context.Context, r *http.Request) (*Session, error)
- func (sm *SessionManager) SetCookie(w http.ResponseWriter, session *Session)
- func (sm *SessionManager) ValidateCSRF(r *http.Request, s *Session) bool
- type Storage
- func (s *Storage) ClientAssertionJWTValid(ctx context.Context, jti string) error
- func (s *Storage) CreateAccessTokenSession(ctx context.Context, signature string, request fosite.Requester) error
- func (s *Storage) CreateAuthorizeCodeSession(ctx context.Context, code string, request fosite.Requester) error
- func (s *Storage) CreateOpenIDConnectSession(ctx context.Context, authorizeCode string, requester fosite.Requester) error
- func (s *Storage) CreatePKCERequestSession(ctx context.Context, signature string, requester fosite.Requester) error
- func (s *Storage) CreateRefreshTokenSession(ctx context.Context, signature string, accessSignature string, ...) error
- func (s *Storage) DeleteAccessTokenSession(ctx context.Context, signature string) error
- func (s *Storage) DeleteOpenIDConnectSession(ctx context.Context, authorizeCode string) error
- func (s *Storage) DeletePKCERequestSession(ctx context.Context, signature string) error
- func (s *Storage) DeleteRefreshTokenSession(ctx context.Context, signature string) error
- func (s *Storage) GetAccessTokenSession(ctx context.Context, signature string, session fosite.Session) (fosite.Requester, error)
- func (s *Storage) GetAuthorizeCodeSession(ctx context.Context, code string, session fosite.Session) (fosite.Requester, error)
- func (s *Storage) GetClient(ctx context.Context, id string) (fosite.Client, error)
- func (s *Storage) GetOpenIDConnectSession(ctx context.Context, authorizeCode string, requester fosite.Requester) (fosite.Requester, error)
- func (s *Storage) GetPKCERequestSession(ctx context.Context, signature string, session fosite.Session) (fosite.Requester, error)
- func (s *Storage) GetRefreshTokenSession(ctx context.Context, signature string, session fosite.Session) (fosite.Requester, error)
- func (s *Storage) InvalidateAuthorizeCodeSession(ctx context.Context, code string) error
- func (s *Storage) RevokeAccessToken(ctx context.Context, requestID string) error
- func (s *Storage) RevokeRefreshToken(ctx context.Context, requestID string) error
- func (s *Storage) RotateRefreshToken(ctx context.Context, requestID string, refreshTokenSignature string) error
- func (s *Storage) SetCIMDResolver(r *CIMDResolver)
- func (s *Storage) SetClientAssertionJWT(ctx context.Context, jti string, exp time.Time) error
- type SubjectResolver
- type TokenExchanger
Constants ¶
const ( TokenExchangeGrantType = "urn:ietf:params:oauth:grant-type:token-exchange" AccessTokenType = "urn:ietf:params:oauth:token-type:access_token" AgentTokenType = "urn:legant:params:oauth:token-type:agent-token" )
RFC 8693 + Legant token-type identifiers.
Variables ¶
This section is empty.
Functions ¶
func AuthServerMetadataHandler ¶
func AuthServerMetadataHandler(issuerURL string) http.HandlerFunc
AuthServerMetadataHandler serves RFC 8414 OAuth 2.0 Authorization Server Metadata.
func DiscoveryHandler ¶
func DiscoveryHandler(issuerURL string) http.HandlerFunc
DiscoveryHandler serves the OpenID Connect discovery document.
func JWKSHandler ¶
func JWKSHandler(keysFn func() map[string]*rsa.PublicKey) http.HandlerFunc
JWKSHandler serves the JSON Web Key Set. It is backed by a function returning the currently-trusted public keys indexed by kid, so the set reflects key rotation without a restart and publishes every key a verifier may need during an overlap window.
func MintRegistrationToken ¶
func MintRegistrationToken(ctx context.Context, pool *pgxpool.Pool, maxUses int, ttl time.Duration) (string, error)
MintRegistrationToken creates an initial access token, returning the plaintext (shown once). Used by the `legant dcr issue-token` command.
func NewOAuth2Provider ¶
func NewOAuth2Provider(storage *Storage, issuerURL string, activeKey func() *rsa.PrivateKey, systemSecret []byte) fosite.OAuth2Provider
NewOAuth2Provider builds the Fosite OAuth2/OIDC provider. activeKey returns the current signing private key on each call, so key rotation performed in-process is picked up without rebuilding the provider.
func NewSession ¶
func NewSession(subject string) *openid.DefaultSession
NewSession creates a new OpenID Connect session for the given subject, stamping the active signing key id into the token headers.
func SameOrigin ¶
SameOrigin reports whether a state-changing request's Origin/Referer matches its own host. It is a CSRF defense-in-depth on top of SameSite=Lax cookies: a cross-site form POST that does carry an Origin is rejected, closing the same-site/subdomain gap that Lax alone leaves open. A request with no Origin/Referer is allowed (and still protected by the Lax session cookie).
func SetSigningKID ¶
func SetSigningKID(kid string)
SetSigningKID records the active signing key id for stamping on issued tokens.
Types ¶
type AccountHandler ¶
type AccountHandler struct {
// contains filtered or unexported fields
}
AccountHandler serves the self-service delegation-management UI: a user views the delegations they have granted to agents and can revoke any of them (and the whole sub-agent chain it seeded).
func NewAccountHandler ¶
func NewAccountHandler(ch *chains.Service, sessions *SessionManager, tmpl *template.Template) *AccountHandler
func (*AccountHandler) Delegations ¶
func (h *AccountHandler) Delegations(w http.ResponseWriter, r *http.Request)
Delegations renders the list of the logged-in user's granted delegations.
func (*AccountHandler) Revoke ¶
func (h *AccountHandler) Revoke(w http.ResponseWriter, r *http.Request)
Revoke revokes one delegation (and its sub-agent chain) owned by the user.
type ActorResolver ¶
ActorResolver authenticates the acting agent from its presented token.
type AdminHandler ¶
type AdminHandler struct {
// contains filtered or unexported fields
}
AdminHandler serves superadmin dashboard pages — currently the tamper-evident audit/provenance viewer, the user-facing surface of Legant's most differentiated asset (who-acted-for-whom, provably).
func NewAdminHandler ¶
func NewAdminHandler(pool *pgxpool.Pool, sessions *SessionManager, tmpl *template.Template) *AdminHandler
func (*AdminHandler) Audit ¶
func (h *AdminHandler) Audit(w http.ResponseWriter, r *http.Request)
Audit renders the audit trail with provenance and a chain-verified badge.
type CIMDResolver ¶
type CIMDResolver struct {
// contains filtered or unexported fields
}
CIMDResolver fetches and validates Client ID Metadata Documents, where the client_id is itself an https URL pointing at the document. CIMD clients are always PUBLIC and rely on S256 PKCE — there is no client secret to leak.
func NewCIMDResolver ¶
func NewCIMDResolver(client *http.Client) *CIMDResolver
type ConsentHandler ¶
type ConsentHandler struct {
// contains filtered or unexported fields
}
func NewConsentHandler ¶
func NewConsentHandler(pool *pgxpool.Pool, sessionManager *SessionManager, templates *template.Template) *ConsentHandler
func (*ConsentHandler) LoginPage ¶
func (ch *ConsentHandler) LoginPage(w http.ResponseWriter, r *http.Request)
LoginPage renders the login form.
func (*ConsentHandler) LoginSubmit ¶
func (ch *ConsentHandler) LoginSubmit(w http.ResponseWriter, r *http.Request)
LoginSubmit handles the login form submission.
func (*ConsentHandler) LogoutHandler ¶
func (ch *ConsentHandler) LogoutHandler(w http.ResponseWriter, r *http.Request)
LogoutHandler handles POST /logout.
func (*ConsentHandler) RegisterPage ¶
func (ch *ConsentHandler) RegisterPage(w http.ResponseWriter, r *http.Request)
RegisterPage renders the registration form.
func (*ConsentHandler) RegisterSubmit ¶
func (ch *ConsentHandler) RegisterSubmit(w http.ResponseWriter, r *http.Request)
RegisterSubmit handles the registration form submission.
type DiscoveryDocument ¶
type DiscoveryDocument struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
UserinfoEndpoint string `json:"userinfo_endpoint"`
JwksURI string `json:"jwks_uri"`
RevocationEndpoint string `json:"revocation_endpoint"`
IntrospectionEndpoint string `json:"introspection_endpoint"`
RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
ScopesSupported []string `json:"scopes_supported"`
ResponseTypesSupported []string `json:"response_types_supported"`
ResponseModesSupported []string `json:"response_modes_supported"`
GrantTypesSupported []string `json:"grant_types_supported"`
SubjectTypesSupported []string `json:"subject_types_supported"`
IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported"`
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"`
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
ClaimsSupported []string `json:"claims_supported"`
}
func BuildMetadata ¶
func BuildMetadata(issuerURL string) DiscoveryDocument
BuildMetadata constructs the authorization-server metadata shared by the OIDC discovery document and the RFC 8414 endpoint. It advertises only what the server actually implements — notably scopes and claims that are genuinely issued, so clients are not told to expect email/profile claims that the server does not populate.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
func NewHandler ¶
func NewHandler(provider fosite.OAuth2Provider, sessionManager *SessionManager) *Handler
func (*Handler) AuthorizeHandler ¶
func (h *Handler) AuthorizeHandler(w http.ResponseWriter, r *http.Request)
AuthorizeHandler handles GET /oauth2/authorize It checks for an existing session and either shows the login page or proceeds with consent.
func (*Handler) IntrospectHandler ¶
func (h *Handler) IntrospectHandler(w http.ResponseWriter, r *http.Request)
IntrospectHandler handles POST /oauth2/introspect
func (*Handler) RevokeHandler ¶
func (h *Handler) RevokeHandler(w http.ResponseWriter, r *http.Request)
RevokeHandler handles POST /oauth2/revoke
func (*Handler) SetExchanger ¶
func (h *Handler) SetExchanger(ex *TokenExchanger)
SetExchanger enables the RFC 8693 token-exchange grant on the token endpoint and delegation-token introspection.
func (*Handler) TokenHandler ¶
func (h *Handler) TokenHandler(w http.ResponseWriter, r *http.Request)
TokenHandler handles POST /oauth2/token
func (*Handler) UserinfoHandler ¶
func (h *Handler) UserinfoHandler(w http.ResponseWriter, r *http.Request)
UserinfoHandler handles GET /oauth2/userinfo
type JWKSResponse ¶
type JWKSResponse struct {
Keys []JWK `json:"keys"`
}
type LiveHandler ¶
type LiveHandler struct {
// contains filtered or unexported fields
}
LiveHandler serves the superadmin real-time console: a dashboard shell, a JSON snapshot of the current authority graph, and an SSE stream of live activity events (mints, revocations, gateway decisions) fanned out from the hub.
func NewLiveHandler ¶
func (*LiveHandler) Dashboard ¶
func (h *LiveHandler) Dashboard(w http.ResponseWriter, r *http.Request)
Dashboard renders the live console shell.
func (*LiveHandler) Events ¶
func (h *LiveHandler) Events(w http.ResponseWriter, r *http.Request)
Events streams live activity as Server-Sent Events.
func (*LiveHandler) Ingest ¶
func (h *LiveHandler) Ingest(w http.ResponseWriter, r *http.Request)
Ingest accepts an allow/deny decision from a connected resource server (a `legant guard` hook) and publishes it to the live console. It is authenticated by a shared bearer token (not a user session), so an off-box guard with no Legant login can report. Disabled (404) unless a token is configured. The event goes through the cross-process publisher so every replica's console sees it.
func (*LiveHandler) Snapshot ¶
func (h *LiveHandler) Snapshot(w http.ResponseWriter, r *http.Request)
Snapshot returns the current active authority graph as JSON. The console fetches it on load and refreshes it when a mint or revoke arrives.
type Registrar ¶
type Registrar struct {
// contains filtered or unexported fields
}
Registrar implements RFC 7591 dynamic client registration, gated by an initial access token so the endpoint cannot be used to create clients anonymously.
type SessionManager ¶
type SessionManager struct {
// contains filtered or unexported fields
}
func NewSessionManager ¶
func (*SessionManager) CSRFToken ¶
func (sm *SessionManager) CSRFToken(s *Session) string
CSRFToken returns the synchronizer token bound to a session: an HMAC of the session id under the cookie secret. It is stable for the session's lifetime and requires no extra storage.
func (*SessionManager) Delete ¶
func (sm *SessionManager) Delete(ctx context.Context, w http.ResponseWriter, r *http.Request) error
func (*SessionManager) SetCookie ¶
func (sm *SessionManager) SetCookie(w http.ResponseWriter, session *Session)
func (*SessionManager) ValidateCSRF ¶
func (sm *SessionManager) ValidateCSRF(r *http.Request, s *Session) bool
ValidateCSRF reports whether a state-changing request carries the correct CSRF token for its session, taken from the X-CSRF-Token header (JSON/fetch clients) or a csrf_token form field (HTML forms). It only reads the form body for form-encoded requests, so it never consumes a JSON body the handler will parse.
type Storage ¶
type Storage struct {
// contains filtered or unexported fields
}
Storage implements all fosite storage interfaces needed for our OAuth2/OIDC flows: - fosite.Storage (ClientManager) - oauth2.CoreStorage (AuthorizeCodeStorage, AccessTokenStorage, RefreshTokenStorage) - oauth2.TokenRevocationStorage - pkce.PKCERequestStorage - openid.OpenIDConnectRequestStorage
func NewStorage ¶
func (*Storage) ClientAssertionJWTValid ¶
func (*Storage) CreateAccessTokenSession ¶
func (*Storage) CreateAuthorizeCodeSession ¶
func (*Storage) CreateOpenIDConnectSession ¶
func (*Storage) CreatePKCERequestSession ¶
func (*Storage) CreateRefreshTokenSession ¶
func (*Storage) DeleteAccessTokenSession ¶
func (*Storage) DeleteOpenIDConnectSession ¶
func (*Storage) DeletePKCERequestSession ¶
func (*Storage) DeleteRefreshTokenSession ¶
func (*Storage) GetAccessTokenSession ¶
func (*Storage) GetAuthorizeCodeSession ¶
func (*Storage) GetOpenIDConnectSession ¶
func (*Storage) GetPKCERequestSession ¶
func (*Storage) GetRefreshTokenSession ¶
func (*Storage) InvalidateAuthorizeCodeSession ¶
func (*Storage) RevokeAccessToken ¶
func (*Storage) RevokeRefreshToken ¶
func (*Storage) RotateRefreshToken ¶
func (*Storage) SetCIMDResolver ¶
func (s *Storage) SetCIMDResolver(r *CIMDResolver)
SetCIMDResolver enables resolving CIMD (https-URL) client ids by fetching the client metadata document instead of looking the client up in the database.
type SubjectResolver ¶
type SubjectResolver func(ctx context.Context, token string) (userID string, scopes []string, ok bool)
SubjectResolver validates the subject (user) token and returns the user id and the scopes that token was granted (the scope ceiling).
type TokenExchanger ¶
type TokenExchanger struct {
// contains filtered or unexported fields
}
TokenExchanger implements the RFC 8693 token-exchange grant: it turns a user's subject token plus an agent's actor token into a short-lived composite delegation JWT (sub = user, act = agent), bounded by the delegation's scopes, constraints, and expiry, recorded for revocation, and audited.
func NewTokenExchanger ¶
func NewTokenExchanger(issuer string, ttl time.Duration, keys *keystore.Keystore, ch *chains.Service, rev *revocation.Store, pool *pgxpool.Pool, pub *live.Publisher, actor ActorResolver, subject SubjectResolver) *TokenExchanger
func (*TokenExchanger) Handle ¶
func (x *TokenExchanger) Handle(w http.ResponseWriter, r *http.Request)
Handle processes a token-exchange request. The caller (TokenHandler) has already parsed the form and set no-store headers.
func (*TokenExchanger) IntrospectDelegation ¶
func (x *TokenExchanger) IntrospectDelegation(ctx context.Context, token string) (map[string]any, bool)
IntrospectDelegation answers RFC 7662 introspection for a composite delegation token: it verifies the signature (kid-aware) and consults the revocation store. Returns ok=false when the token is not one of ours (so the caller can fall back to Fosite introspection of normal access tokens).