Documentation
¶
Index ¶
- Constants
- Variables
- func BearerFromHeader(h string) string
- func HashToken(token string) string
- func LoopbackRedirectAllowed(raw string) bool
- func NewBearerToken(prefix string) (string, string, error)
- func NewMCPAccessToken(userID, resource, secret string, ttl time.Duration) string
- func RandomURLToken() (string, error)
- func VerifyPKCES256(verifier, challenge string) bool
- type Authenticator
- type DBAuthenticator
- type LoginState
- type LoginStateStore
- type MCPAuthenticator
- type OIDC
- type OIDCConfig
- type OIDCSettings
- type OIDCUser
- type PostgresStateStore
- func (s *PostgresStateStore) CleanupExpired(ctx context.Context) error
- func (s *PostgresStateStore) PutCode(ctx context.Context, code string, st LoginState) error
- func (s *PostgresStateStore) PutState(ctx context.Context, id string, st LoginState) error
- func (s *PostgresStateStore) TakeCode(ctx context.Context, code string) (LoginState, bool, error)
- func (s *PostgresStateStore) TakeState(ctx context.Context, id string) (LoginState, bool, error)
- type Principal
- type PrincipalType
- type SessionCodec
- type StateStore
- func (s *StateStore) PutCode(ctx context.Context, code string, st LoginState) error
- func (s *StateStore) PutState(ctx context.Context, id string, st LoginState) error
- func (s *StateStore) TakeCode(ctx context.Context, code string) (LoginState, bool, error)
- func (s *StateStore) TakeState(ctx context.Context, id string) (LoginState, bool, error)
- type TokenResolver
- type UserResolver
Constants ¶
const ( GoogleGroupMembershipResolved = "resolved" )
const ( // MCPAccessTokenPrefix is a public token type marker, not a credential. //nolint:gosec // A fixed prefix lets the authenticator select the token verifier. MCPAccessTokenPrefix = "slashdocs_mcp_" ServiceAccountPrefix = "slashdocs_sa_" )
const GoogleIssuer = "https://accounts.google.com"
GoogleIssuer is the OIDC issuer for Google accounts. Deployments configured with the legacy GOOGLE_OAUTH_* variables resolve to it.
Variables ¶
var ErrNotFound = errors.New("not found")
ErrNotFound is the canonical "principal/record not found" sentinel. The repo layer's repo.ErrNotFound wraps this so that lower-level packages (e.g. this auth package, which must not import repo to avoid an import cycle) can still detect not-found results via errors.Is.
Functions ¶
func BearerFromHeader ¶
func LoopbackRedirectAllowed ¶
func NewMCPAccessToken ¶
func RandomURLToken ¶
func VerifyPKCES256 ¶
Types ¶
type Authenticator ¶
type DBAuthenticator ¶
type DBAuthenticator struct {
Resolver interface {
TokenResolver
UserResolver
}
SessionSecret string
}
func (DBAuthenticator) Authenticate ¶
func (a DBAuthenticator) Authenticate(r *http.Request) (*Principal, error)
type LoginState ¶
type LoginState struct {
Mode, Redirect, CLIRedirect, CodeChallenge string
ExpiresAt time.Time
User OIDCUser
UserID string
// MCP OAuth authorization codes reuse the same one-time, persisted code
// store as CLI login while carrying the audience and public-client binding
// required by OAuth 2.1.
OAuthClientID string
OAuthRedirectURI string
OAuthResource string
OAuthScope string
// WebBindingRequired marks web login states created after browser binding
// was introduced. Its zero value preserves callbacks for states created by
// older instances during a rolling deployment.
WebBindingRequired bool
}
func (LoginState) MarshalJSON ¶
func (s LoginState) MarshalJSON() ([]byte, error)
func (*LoginState) UnmarshalJSON ¶
func (s *LoginState) UnmarshalJSON(data []byte) error
type LoginStateStore ¶
type MCPAuthenticator ¶
type MCPAuthenticator struct {
Users UserResolver
ServiceTokens Authenticator
SessionSecret string
Resource string
}
MCPAuthenticator authenticates the remote MCP transport. Browser session cookies are deliberately not accepted: every MCP request must carry a bearer token so identity cannot leak between clients or transport sessions.
Human access tokens are expiring, audience-bound tokens minted by the MCP OAuth flow. Existing service-account keys remain available for unattended agents and are resolved through the normal API authenticator.
func (MCPAuthenticator) Authenticate ¶
func (a MCPAuthenticator) Authenticate(r *http.Request) (*Principal, error)
type OIDC ¶
type OIDC struct {
Config *oauth2.Config
Verifier *oidc.IDTokenVerifier
Issuer string
}
OIDC drives the OpenID Connect authorization-code flow for one provider. Tests may construct it directly with a fake Config; production code should go through NewOIDC, which discovers endpoints and wires JWKS verification.
func NewOIDC ¶
func NewOIDC(ctx context.Context, cfg OIDCConfig) (OIDC, error)
NewOIDC prepares an OIDC client. Google uses its stable OAuth endpoints and a lazy remote JWKS so existing deployments do not require network access at startup. Other providers are discovered from <issuer>/.well-known/openid-configuration.
func (OIDC) AuthCodeURL ¶
func (o OIDC) AuthCodeURL(state string, opts ...oauth2.AuthCodeOption) string
func (OIDC) ExchangeAndVerify ¶
func (o OIDC) ExchangeAndVerify(ctx context.Context, code string, opts ...oauth2.AuthCodeOption) (OIDCUser, error)
ExchangeAndVerify redeems an authorization code and verifies the returned ID token's signature, issuer, audience, and expiry.
type OIDCConfig ¶
type OIDCConfig struct {
// IssuerURL is the provider's public issuer; ID tokens are validated
// against it and browsers are sent to its authorization endpoint.
IssuerURL string
// InternalIssuerURL optionally names a second base URL where the server
// reaches the same provider (split horizon, e.g. a docker-compose network
// where the browser sees http://localhost:5556 but the server must dial
// http://dex:5556). Discovery, token exchange, and JWKS fetches use it;
// token `iss` claims keep being validated against IssuerURL.
InternalIssuerURL string
ClientID string
ClientSecret string
RedirectURL string
}
OIDCConfig configures the connection to one OpenID Connect provider.
type OIDCSettings ¶
type OIDCSettings struct {
IssuerURL string
InternalIssuerURL string
ClientID string
ClientSecret string
// ProviderName labels the login button ("Continue with <ProviderName>").
ProviderName string
}
OIDCSettings is the login provider configuration resolved from environment variables.
func ResolveOIDCSettings ¶
func ResolveOIDCSettings(getenv func(string) string) (OIDCSettings, error)
ResolveOIDCSettings resolves the generic SLASHDOCS_OIDC_* variables and the legacy GOOGLE_OAUTH_CLIENT_ID/GOOGLE_OAUTH_CLIENT_SECRET pair into one provider configuration. The Google pair keeps working as an alias for issuer https://accounts.google.com so existing deployments need no changes; mixing the two families is a configuration error. getenv is os.Getenv in production.
type OIDCUser ¶
type OIDCUser struct{ Sub, Email, Name, PictureURL string }
OIDCUser holds the identity claims extracted from a verified ID token.
type PostgresStateStore ¶
type PostgresStateStore struct {
// contains filtered or unexported fields
}
func NewPostgresStateStore ¶
func NewPostgresStateStore(db *pgxpool.Pool) *PostgresStateStore
func (*PostgresStateStore) CleanupExpired ¶
func (s *PostgresStateStore) CleanupExpired(ctx context.Context) error
func (*PostgresStateStore) PutCode ¶
func (s *PostgresStateStore) PutCode(ctx context.Context, code string, st LoginState) error
func (*PostgresStateStore) PutState ¶
func (s *PostgresStateStore) PutState(ctx context.Context, id string, st LoginState) error
func (*PostgresStateStore) TakeCode ¶
func (s *PostgresStateStore) TakeCode(ctx context.Context, code string) (LoginState, bool, error)
func (*PostgresStateStore) TakeState ¶
func (s *PostgresStateStore) TakeState(ctx context.Context, id string) (LoginState, bool, error)
type Principal ¶
type Principal struct {
Type PrincipalType `json:"type"`
ID string `json:"id"`
Email string `json:"email,omitempty"`
Name string `json:"name,omitempty"`
PictureURL string `json:"picture_url,omitempty"`
// GoogleGroupIDs and GoogleGroupMembershipState are authorization inputs,
// not principal profile data. Excluding them from JSON prevents a
// user's group graph (and resolution failures) from leaking through API
// responses that serialize the authenticated principal.
GoogleGroupIDs []string `json:"-"`
GoogleGroupMembershipState string `json:"-"`
}
type PrincipalType ¶
type PrincipalType string
const ( PrincipalUser PrincipalType = "user" PrincipalServiceAccount PrincipalType = "service_account" PrincipalGoogleGroup PrincipalType = "google_group" // PrincipalAnyone represents "everyone who can authenticate to this // server". On an org deployment the login gate scopes that set to the // org's members. It is stored as a grant with an empty principal id. PrincipalAnyone PrincipalType = "anyone" // PrincipalAnonymous represents an unauthenticated caller. A public // deployment gives it to a caller without credentials on the routes that // read a document, where only "anyone" grants apply to it. PrincipalAnonymous PrincipalType = "anonymous" )
type SessionCodec ¶
type SessionCodec struct{ Secret []byte }
func (SessionCodec) Sign ¶
func (s SessionCodec) Sign(userID string) string
func (SessionCodec) SignForAudience ¶
func (s SessionCodec) SignForAudience(userID, audience string, ttl time.Duration) string
func (SessionCodec) VerifyAudience ¶
func (s SessionCodec) VerifyAudience(v, audience string) (string, bool)
func (SessionCodec) VerifySession ¶
func (s SessionCodec) VerifySession(v string) (string, bool)
type StateStore ¶
type StateStore struct {
// contains filtered or unexported fields
}
func NewStateStore ¶
func NewStateStore() *StateStore
func (*StateStore) PutCode ¶
func (s *StateStore) PutCode(ctx context.Context, code string, st LoginState) error
func (*StateStore) PutState ¶
func (s *StateStore) PutState(ctx context.Context, id string, st LoginState) error
func (*StateStore) TakeCode ¶
func (s *StateStore) TakeCode(ctx context.Context, code string) (LoginState, bool, error)
func (*StateStore) TakeState ¶
func (s *StateStore) TakeState(ctx context.Context, id string) (LoginState, bool, error)