Documentation
¶
Index ¶
- Constants
- Variables
- func CollectScoped(ctx context.Context) *ent.Scoped
- func HasScope(auth *TokenAuth, scope externalapi.ApiTokenScope) bool
- func RegistrationHash(value string) string
- func SameRegistrationBrowser(tokenHash, cookieValue string) bool
- func StampUser(claims *gptoken.Claims, u *ent.User)
- func TokenScoped(ctx context.Context) *ent.Scoped
- func VerifyClaims(email, browserHash string) map[string]string
- func VerifyClaimsBrowser(claims map[string]string) string
- func VerifyClaimsEmail(claims map[string]string) string
- func WithCollectAuth(ctx context.Context, auth *CollectAuth) context.Context
- func WithSiteAuth(ctx context.Context, auth *SiteAuth) context.Context
- func WithTokenAuth(ctx context.Context, auth *TokenAuth) context.Context
- type CollectAuth
- type CollectSecurityHandler
- type ExternalSecurityHandler
- type Method
- type Session
- type Sessions
- func (s *Sessions) Cleared() *http.Cookie
- func (s *Sessions) ClearedSigninFlow() *http.Cookie
- func (s *Sessions) Holder(raw string) (id, epoch int64, ok bool)
- func (s *Sessions) Issue(u *ent.User, sess Session) (*http.Cookie, error)
- func (s *Sessions) NewRegistrationBrowser(ttl time.Duration) (cookie *http.Cookie, hash string)
- func (s *Sessions) PasskeyCeremony(path, value string, ttl time.Duration) *http.Cookie
- func (s *Sessions) SessionOf(raw string) (Session, bool)
- func (s *Sessions) SigninFlow(value string, ttl time.Duration) *http.Cookie
- type SiteAuth
- type SiteSecurityHandler
- type TokenAuth
Constants ¶
const ( ClaimUserID = "uid" ClaimEpoch = "epoch" // ClaimProviderLogin is the Unix time, in seconds, of the Sign-in provider login the session // began with (ADR 0048). It is the stateless proof that stands in for the password of a User // who has none; only a provider login sets it, and a reissue keeps the original time. ClaimProviderLogin = "provider_login" // ClaimPasskeyCheck is the Unix time, in seconds, of the last fresh Passkey check of the // session: a Passkey login or a step-up check (ADR 0052). Like ClaimProviderLogin it is a // stateless proof for a User with no password, and a reissue keeps the original time. ClaimPasskeyCheck = "passkey_check" // ClaimMethod is how the session was obtained (a Method). A token without a known method // is refused: the User signs in again (ADR 0052). ClaimMethod = "method" )
The session token's claims beyond go-pkgz's own (ADR 0020). Both ride the token's user attributes as decimal strings: ClaimUserID is the User's id, the lookup key of every request; ClaimEpoch is the User's session_epoch at issuance.
const PasskeyCeremonyCookie = "PASSKEY"
PasskeyCeremonyCookie is the name of the cookie that carries a Passkey ceremony's challenge between `begin` and `finish` (ADR 0052).
const PasskeyCheckPath = "/site/me/passkeys/check"
PasskeyCheckPath is the prefix of the Passkey check operations that use the cookie.
const PasskeyLoginPath = "/site/auth/passkey"
PasskeyLoginPath is the prefix of the login operations that use the cookie.
const PasskeyRegistrationPath = "/site/me/passkeys/registration"
PasskeyRegistrationPath is the prefix of the registration operations that use the cookie; the browser sends it to nothing else.
const RegistrationCookie = "REG"
RegistrationCookie is the name of the cookie that makes a browser the Registration browser (ADR 0030): registration sets it, and the verification link trusts the password from the form only when it comes back with it.
const SessionCookie = "JWT"
SessionCookie is the name of the cookie that carries the session token; the /site contract's cookie security scheme reads it.
const SigninFlowCookie = "SIGNIN"
SigninFlowCookie is the name of the cookie that carries a provider sign-in's flow between `start` and `callback` (ADR 0048).
Variables ¶
ErrUnauthorized is returned by security handlers when a request is not authorized.
Functions ¶
func CollectScoped ¶
CollectScoped returns the Workspace-scoped client of the resolved collect key. It is nil on an unauthenticated context; the security handler runs before every collect operation, so handlers can rely on it.
func HasScope ¶
func HasScope(auth *TokenAuth, scope externalapi.ApiTokenScope) bool
func RegistrationHash ¶
RegistrationHash is the hash of a registration cookie's value, empty for no cookie.
func SameRegistrationBrowser ¶
SameRegistrationBrowser reports whether a request's registration cookie value is the one whose hash a verification token carries. A token minted without a hash (a link asked for from a browser that holds no cookie) matches no browser.
func StampUser ¶
StampUser writes the User's id and session epoch into the claims' user: the claims every session carries (Issue; the test harness mints its tokens with it).
func TokenScoped ¶
TokenScoped returns the Workspace-scoped client of the authenticated api token. It is nil on an unauthenticated context, so call it only after the handler's HasScope check (which fails for a nil TokenAuth). Handlers pass it to the domain modules; they never build a *ent.Scoped from an id themselves.
func VerifyClaims ¶
VerifyClaims builds the claims of a verification token: the address it is sent to and the hash of the registration cookie it trusts (empty for none).
func VerifyClaimsBrowser ¶
VerifyClaimsBrowser is the hash of the Registration browser a verification token was minted for, empty when none.
func VerifyClaimsEmail ¶
VerifyClaimsEmail is the address a verification token was sent to.
func WithCollectAuth ¶
func WithCollectAuth(ctx context.Context, auth *CollectAuth) context.Context
Types ¶
type CollectAuth ¶
type CollectAuth struct {
WorkspaceID int64
// Scoped is the client confined to WorkspaceID. This file is the collect
// API's construction point of it (ADR 0017); read it with CollectScoped.
Scoped *ent.Scoped
}
CollectAuth holds the workspace resolved from the per-workspace collect key.
func GetCollectAuth ¶
func GetCollectAuth(ctx context.Context) *CollectAuth
type CollectSecurityHandler ¶
type CollectSecurityHandler struct {
// contains filtered or unexported fields
}
CollectSecurityHandler implements collectapi.SecurityHandler: resolves the per-workspace collect write-key (x-collect-key) to its workspace.
func NewCollectSecurityHandler ¶
func NewCollectSecurityHandler(client *ent.Client) *CollectSecurityHandler
func (*CollectSecurityHandler) HandleApiKeyAuth ¶
func (h *CollectSecurityHandler) HandleApiKeyAuth(ctx context.Context, _ collectapi.OperationName, t collectapi.ApiKeyAuth) (context.Context, error)
HandleApiKeyAuth authenticates the collect key and applies the rate limits that need it (ADR 0025): a client address that spent its failed-authentication budget is refused before the key is looked at, a wrong key counts against it, and a success charges the Workspace's /collect budget. Rejections surface as *ratelimit.LimitedError.
type ExternalSecurityHandler ¶
type ExternalSecurityHandler struct {
// contains filtered or unexported fields
}
ExternalSecurityHandler implements externalapi.SecurityHandler (Bearer token auth).
func NewExternalSecurityHandler ¶
func NewExternalSecurityHandler(client *ent.Client, bus *events.Bus) *ExternalSecurityHandler
NewExternalSecurityHandler builds the Bearer-token handler. The bus opens the transactions of audited writes made under the token (ADR 0022).
func (*ExternalSecurityHandler) HandleBearerAuth ¶
func (h *ExternalSecurityHandler) HandleBearerAuth(ctx context.Context, op externalapi.OperationName, t externalapi.BearerAuth) (context.Context, error)
HandleBearerAuth authenticates the Bearer token and applies the rate limits that need it (ADR 0025): a client address that spent its failed-authentication budget is refused before the token is looked at, a failure counts against it, and a success charges the Workspace's shared /api and /mcp budget. Rejections surface as *ratelimit.LimitedError.
type Method ¶
type Method string
Method is how a session was obtained (ADR 0052). The Two-factor requirement reads it: a session is Strong when the person proved more than a password or a provider account.
const ( // MethodPassword is a login by email and password with no Second factor step. MethodPassword Method = "password" // MethodProvider is a login with a Sign-in provider (ADR 0048) with no Second factor step. MethodProvider Method = "provider" // MethodEmail is the session a verification link starts: it proves the mailbox only. MethodEmail Method = "email" // MethodSecondFactor is a login that passed a Second factor or Recovery code step. MethodSecondFactor Method = "second_factor" // MethodPasskey is a login with a Passkey, which verifies the person and replaces both steps. MethodPasskey Method = "passkey" )
type Session ¶
Session is what a session token records about how it began: its Method, the time of the Sign-in provider login it began with (zero otherwise) and the time of its last Passkey check (zero when it has none). The two times are the proofs that stand in for a password.
func (Session) WithoutPasskeys ¶
WithoutPasskeys is the session after the User's last Passkey is gone: a Passkey session falls back to the weakest method it began with, and its Passkey check no longer stands in for a password.
func (Session) WithoutSecondFactor ¶
WithoutSecondFactor is the session after its Second factor is gone: a session that was strong only because it passed a Second factor step falls back to the weakest method it began with.
type Sessions ¶
type Sessions struct {
// contains filtered or unexported fields
}
Sessions issues and clears the site session (ADR 0020): a JWT signed with the instance secret, carried in an HttpOnly, SameSite=Lax cookie that lives as long as the token (SPHERICON_SESSION_TTL, no refresh). It is the one place a session is minted; the login operations hand its cookie to the client.
func NewSessions ¶
func NewSessions(jwtSecret string, ttl time.Duration, secure bool, now func() time.Time, verifyWith ...string) *Sessions
NewSessions builds the issuer. secure sets the cookie's Secure attribute (the instance is served over HTTPS); now is the clock of the token's expiry, nil meaning time.Now. A session is signed with jwtSecret and verified against it and then against each of verifyWith, the secondary key of a JWT secret rotation.
func (*Sessions) Cleared ¶
Cleared is the cookie that ends the session on the client: empty and expired.
func (*Sessions) ClearedSigninFlow ¶
ClearedSigninFlow is the cookie that removes the flow from the browser.
func (*Sessions) Holder ¶
Holder reads a raw session token the request carries without requiring one (a public operation that keeps the acting session when there is one): it checks the signature and expiry and returns the User id and epoch the token was issued under. The caller compares the epoch with the User's; ok is false for a token that does not verify.
func (*Sessions) Issue ¶
Issue signs a session for u, stamped with its id, current session epoch and how it began, and returns the cookie that carries it. The provider login time rides the token, so a step that asks a passwordless User for proof can tell how recent the login was without a store.
func (*Sessions) NewRegistrationBrowser ¶
NewRegistrationBrowser draws the random value that marks one browser, returning the cookie that carries it (httpOnly, SameSite=Strict, scoped to the auth prefix, living for ttl) and the hash that goes into the verification token. The value itself never leaves the browser.
func (*Sessions) PasskeyCeremony ¶
PasskeyCeremony wraps the sealed ceremony in its cookie: httpOnly, SameSite=Strict (a ceremony begins and finishes in one page), living for ttl and sent only to path.
func (*Sessions) SessionOf ¶
SessionOf is how a raw session token began; ok is false for a token that does not verify, is expired or records no known method.
func (*Sessions) SigninFlow ¶
SigninFlow wraps the sealed flow in its cookie: httpOnly, living for ttl, and SameSite=Lax (not Strict like the Registration browser's): the provider sends the browser back with a cross-site top-level redirect, which Strict would withhold the cookie from.
type SiteAuth ¶
type SiteAuth struct {
UserID int64
Email string
// Session is how the session began: its Method and, for a Sign-in provider login (ADR 0048),
// the time of that login.
Session
}
SiteAuth holds the authenticated dashboard user resolved from the JWT cookie.
func GetSiteAuth ¶
type SiteSecurityHandler ¶
type SiteSecurityHandler struct {
// contains filtered or unexported fields
}
SiteSecurityHandler implements siteapi.SecurityHandler: validates the JWT cookie issued by go-pkgz/auth and resolves the dashboard user from it.
go-pkgz's Parse ignores an expired exp (its own middleware would refresh), so the expiry is enforced here against the injected clock; there is no refresh (ADR 0020). The User is looked up by the id the token carries, and the token's epoch must equal the User's session_epoch: a bump ends every earlier session.
func NewSiteSecurityHandler ¶
func NewSiteSecurityHandler(jwtSecret string, client *ent.Client, now func() time.Time, verifyWith ...string) *SiteSecurityHandler
NewSiteSecurityHandler builds the cookie handler. now is the clock the token's expiry is checked against; nil means time.Now. A token verifies against jwtSecret and then against each of verifyWith, the secondary key of a JWT secret rotation.
func (*SiteSecurityHandler) HandleApiKeyAuth ¶
func (h *SiteSecurityHandler) HandleApiKeyAuth(ctx context.Context, op siteapi.OperationName, t siteapi.ApiKeyAuth) (context.Context, error)
type TokenAuth ¶
type TokenAuth struct {
TokenID int64
WorkspaceID int64
Name string
Scopes []string
// Scoped is the client confined to WorkspaceID. This file is the external
// API's construction point of it (ADR 0017); read it with TokenScoped.
Scoped *ent.Scoped
}
TokenAuth holds the authenticated api-token context for external API requests.