Documentation
¶
Index ¶
- Constants
- Variables
- func AccessTokenSubjectTokenType() string
- func PassportIssuedTokenType() string
- type ActorClaim
- type Authenticator
- func (a *Authenticator) Authorization(w http.ResponseWriter, r *http.Request)
- func (a *Authenticator) Callback(w http.ResponseWriter, r *http.Request)
- func (a *Authenticator) ExchangePassport(ctx context.Context, options *openapi.TokenRequestOptions) (*openapi.Token, error)
- func (a *Authenticator) GetUserinfo(ctx context.Context, r *http.Request, token string) (*openapi.Userinfo, *Claims, error)
- func (a *Authenticator) GetUserinfoFromBearer(ctx context.Context, r *http.Request, token string) (*openapi.Userinfo, *Claims, string, error)
- func (a *Authenticator) InvalidateToken(ctx context.Context, token string)
- func (a *Authenticator) Issue(ctx context.Context, info *IssueInfo) (*Tokens, error)
- func (a *Authenticator) Login(w http.ResponseWriter, r *http.Request)
- func (a *Authenticator) Token(w http.ResponseWriter, r *http.Request) (*openapi.Token, error)
- func (a *Authenticator) TokenAuthorizationCode(w http.ResponseWriter, r *http.Request) (*openapi.Token, error)
- func (a *Authenticator) TokenClientCredentials(w http.ResponseWriter, r *http.Request) (*openapi.Token, error)
- func (a *Authenticator) TokenExchange(_ http.ResponseWriter, r *http.Request) (*openapi.Token, error)
- func (a *Authenticator) TokenRefreshToken(w http.ResponseWriter, r *http.Request) (*openapi.Token, error)
- func (a *Authenticator) Verify(ctx context.Context, info *VerifyInfo) (*Claims, error)
- type Claims
- type Code
- type Error
- type FederatedClaims
- type IssueInfo
- type LoginStateClaims
- type Options
- type PassportClaims
- type RefreshTokenClaims
- type Scope
- type ServiceAccountClaims
- type ServiceClaims
- type State
- type TokenType
- type Tokens
- type VerifyInfo
Constants ¶
const ( // PassportTTL is the lifetime of a passport token. Sized to cover the // worst-case operational lifetime of a request that uses it: three // downstream hops at 15s per-hop API timeout plus 15s grace for clock // skew and tail latency. PassportTTL = 60 * time.Second // PassportType distinguishes passport tokens from access tokens. PassportType = "passport" // PassportIssuer is the issuer claim value for passport tokens. PassportIssuer = "uni-identity" // PassportSourceUNI indicates the source token was a UNI access token. // It aliases constants.UNISentinel so all existing references continue to compile. PassportSourceUNI = constants.UNISentinel )
const (
SessionCookie = "unikorn-identity-session"
)
Variables ¶
var ( ErrUnsupportedProviderType = goerrors.New("unhandled provider type") ErrReference = goerrors.New("resource reference error") ErrUserNotDomainMapped = goerrors.New("user is not domain mapped to an organization") ErrSourceTokenExpired = goerrors.New("source token has expired") )
var ( // ErrKeyFormat is raised when something is wrong with the // encryption keys. ErrKeyFormat = errors.New("key format error") // ErrTokenVerification is raised when token verification fails. ErrTokenVerification = errors.New("failed to verify token") )
var ( // ErrCacheNotReady is returned when the provider List fails (e.g. informer // not yet synced). Callers on the JWS dispatch path surface this as HTTP 503 // Service Unavailable, signaling a transient warm-up condition. ErrCacheNotReady = errors.New("provider list unavailable") // ErrUnknownIssuer is returned when no trusted provider's issuer matches the // token's iss claim. This is an expected outcome (an untrusted or unrecognized // issuer), not a lookup failure — callers surface it as HTTP 401, distinct from // the transient/config errors handleValidatorError otherwise handles. ErrUnknownIssuer = errors.New("no trusted provider matches issuer") )
Functions ¶
func AccessTokenSubjectTokenType ¶ added in v1.17.0
func AccessTokenSubjectTokenType() string
func PassportIssuedTokenType ¶ added in v1.17.0
func PassportIssuedTokenType() string
Types ¶
type ActorClaim ¶ added in v1.17.0
type ActorClaim struct {
// Subject identifies the acting party.
Subject string `json:"sub"`
// Act nests the previous actor when a delegation chain is in play.
Act *ActorClaim `json:"act,omitempty"`
}
ActorClaim is the RFC 8693 section 4.1 "act" claim. It identifies the acting party in a delegation chain and is omitted when no delegation has occurred. Non-identity claims (exp, nbf, aud) are not meaningful here per the RFC and are deliberately not included.
type Authenticator ¶
type Authenticator struct {
// contains filtered or unexported fields
}
Authenticator provides Keystone authentication functionality.
func New ¶
func New(options *Options, namespace string, issuer common.IssuerValue, client client.Client, jwtIssuer *jose.JWTIssuer, userdb *userdb.UserDatabase, rbac *rbac.RBAC) (*Authenticator, error)
New returns a new authenticator with required fields populated. It constructs the authenticator with the validator cache and initializes metrics. Per-provider validators are built lazily by validatorForIssuer when a passport is validated. Deprecated --auth0-exchange-{issuer,audience} flags feed a synthetic auth0-legacy provider for backward compatibility; new deployments should use OAuth2Provider bearerTrust blocks instead.
func (*Authenticator) Authorization ¶
func (a *Authenticator) Authorization(w http.ResponseWriter, r *http.Request)
Authorization redirects the client to the OIDC autorization endpoint to get an authorization code. Note that this function is responsible for either returning an authorization grant or error via a HTTP 302 redirect, or returning a HTML fragment for errors that cannot follow the provided redirect URI.
func (*Authenticator) Callback ¶ added in v0.2.52
func (a *Authenticator) Callback(w http.ResponseWriter, r *http.Request)
OIDCCallback is called by the authorization endpoint in order to return an authorization back to us. We then exchange the code for an ID token, and refresh token. Remember, as far as the client is concerned we're still doing the code grant, so return errors in the redirect query.
func (*Authenticator) ExchangePassport ¶ added in v1.17.0
func (a *Authenticator) ExchangePassport(ctx context.Context, options *openapi.TokenRequestOptions) (*openapi.Token, error)
ExchangePassport runs the RFC 8693 token-exchange flow against pre-parsed request options. It validates the source access token, resolves identity, authorises the requested org/project scope, and returns a signed passport in the access_token field. The ACL is fetched only to authorise the requested scope; it is not embedded in the passport — downstream services continue to fetch ACL via the existing remote authoriser path keyed off passport-verified identity.
This is the entry point for in-process callers that already hold typed TokenRequestOptions and don't need form parsing. The HTTP handler reaches it via TokenExchange.
func (*Authenticator) GetUserinfo ¶ added in v0.2.58
func (a *Authenticator) GetUserinfo(ctx context.Context, r *http.Request, token string) (*openapi.Userinfo, *Claims, error)
GetUserinfo does access token introspection.
func (*Authenticator) GetUserinfoFromBearer ¶ added in v1.17.4
func (a *Authenticator) GetUserinfoFromBearer(ctx context.Context, r *http.Request, token string) (*openapi.Userinfo, *Claims, string, error)
GetUserinfoFromBearer resolves an external or UNI bearer token presented directly — to the local authorizer (/api/v1/...) or to the OIDC userinfo endpoint (/oauth2/v2/userinfo) — without the token-exchange round-trip. It shares dispatchUserinfo with the exchange path and returns the src_iss alongside userinfo and claims.
func (*Authenticator) InvalidateToken ¶ added in v0.2.49
func (a *Authenticator) InvalidateToken(ctx context.Context, token string)
InvalidateToken immediately invalidates the token so it's unusable again. TODO: this only considers caching in the identity service, it's still usable.
func (*Authenticator) Login ¶
func (a *Authenticator) Login(w http.ResponseWriter, r *http.Request)
Login handles the response from the user login prompt.
func (*Authenticator) Token ¶
func (a *Authenticator) Token(w http.ResponseWriter, r *http.Request) (*openapi.Token, error)
Token issues an OAuth2 access token from the provided authorization code.
func (*Authenticator) TokenAuthorizationCode ¶ added in v0.2.30
func (a *Authenticator) TokenAuthorizationCode(w http.ResponseWriter, r *http.Request) (*openapi.Token, error)
TokenAuthorizationCode issues a token based on whether the provided code is correct and the client code verifier (PKCS) matches.
func (*Authenticator) TokenClientCredentials ¶ added in v0.2.30
func (a *Authenticator) TokenClientCredentials(w http.ResponseWriter, r *http.Request) (*openapi.Token, error)
TokenClientCredentials issues a token if the client credentials are valid. We only support mTLS based authentication. TODO: delete me, services should use mTLS alone.
func (*Authenticator) TokenExchange ¶ added in v1.16.1
func (a *Authenticator) TokenExchange(_ http.ResponseWriter, r *http.Request) (*openapi.Token, error)
TokenExchange implements RFC 8693 OAuth 2.0 Token Exchange for UNI passports when invoked via the OAuth 2.0 token endpoint. It parses the form body and hands off to ExchangePassport; non-handler callers should use that directly.
func (*Authenticator) TokenRefreshToken ¶ added in v0.2.30
func (a *Authenticator) TokenRefreshToken(w http.ResponseWriter, r *http.Request) (*openapi.Token, error)
TokenRefreshToken issues a token if the provided refresh token is valid.
func (*Authenticator) Verify ¶ added in v0.1.14
func (a *Authenticator) Verify(ctx context.Context, info *VerifyInfo) (*Claims, error)
Verify checks the access token parses and validates.
type Claims ¶
type Claims struct {
jwt.Claims `json:",inline"`
// Type is the type of access token this is.
Type TokenType `json:"typ"`
// Federated is set when the type is a federated user.
Federated *FederatedClaims `json:"fed,omitempty"`
// ServiceAccount is set when the type is a service account.
ServiceAccount *ServiceAccountClaims `json:"sa,omitempty"`
// Service is set when the type is a service.
Service *ServiceClaims `json:"svc,omitempty"`
}
Claims is an application specific set of claims. TODO: this technically isn't conformant to oauth2 in that we don't specify the client_id claim, and there are probably others.
type Code ¶
type Code struct {
// ID is a unique identifier for the code.
ID string `json:"id"`
// OAuth2Provider is the name of the provider configuration in
// use, this will reference the issuer and allow discovery.
OAuth2Provider string `json:"oap"`
// UserID is the user that issued the code.
UserID string `json:"uid"`
// ClientQuery stores the full client query string.
ClientQuery string `json:"cq"`
// IDToken is the full set of claims returned by the provider.
IDToken *oidc.IDToken `json:"idt"`
// Interactive declares whether this is an interactive login
// or not (e.g. cookie based).
Interactive bool `json:"int"`
}
Code is an authorization code to return to the client that can be exchanged for an access token. Much like how we client things in the oauth2 state during the OIDC exchange, to mitigate problems with horizonal scaling and sharing stuff, we do the same here.
type Error ¶
type Error string
const ( ErrorInvalidRequest Error = "invalid_request" ErrorAccessDenied Error = "access_denied" ErrorUnsupportedResponseType Error = "unsupported_response_type" ErrorInvalidScope Error = "invalid_scope" ErrorServerError Error = "server_error" ErrorLoginRequired Error = "login_required" ErrorRequestNotSupported Error = "request_not_supported" ErrorRequestURINotSupported Error = "request_uri_not_supported" ErrorInteractionRequired Error = "interaction_required" ErrorRegistrationNotSupported Error = "registration_not_supported" )
type FederatedClaims ¶ added in v0.2.59
type FederatedClaims struct {
// Provider is the backend identity provider.
Provider string `json:"idp"`
// ClientID is the oauth2 client that the user is using.
ClientID string `json:"cid"`
// UserID is set when the token is issued to a user.
// TODO: this should be the subject.
UserID string `json:"uid"`
// Scope is the set of scopes requested by the client, and is used to
// populate the userinfo response.
Scope Scope `json:"sco"`
}
type IssueInfo ¶ added in v0.2.4
type IssueInfo struct {
// Issuer should be from the HTTP Host header, as requested by the client.
Issuer string
// Audience should be from the HTTP Host header, as only we can decipher the token.
Audience string
// Subject is the user, or service account ID, the token is valid for. This is used
// for RBAC.
Subject string
// Type is the type of access token this is.
Type TokenType `json:"typ"`
// Federated is set when the type is a federated user.
Federated *FederatedClaims `json:"fed,omitempty"`
// ServiceAccount is set when the type is a service account.
ServiceAccount *ServiceAccountClaims `json:"sa,omitempty"`
// Service is set when the type is a service.
Service *ServiceClaims `json:"svc,omitempty"`
// Duration is the token lifetime. Please note this should only be used for
// service account tokens that by definition need to be long lived.
Duration *time.Duration
// Interactive declares whether this is an interactive login
// or not (e.g. cookie based).
Interactive bool `json:"int"`
// AuthorizationCodeID is required when doing code exchange and records the
AuthorizationCodeID *string
}
IssueInfo controls how the access token is encoded.
type LoginStateClaims ¶ added in v0.2.52
type LoginStateClaims struct {
Query string `json:"query"`
}
LoginStateClaims are used to encrypt information across the login dialog.
type Options ¶
type Options struct {
// AccessTokenDuration should be short to prevent long term use.
AccessTokenDuration time.Duration
// RefreshTokenDuration should be driven by the signing key rotation
// period.
RefreshTokenDuration time.Duration
// TokenVerificationLeeway tells us how permissive we should or shouldn't
// be of timing.
TokenVerificationLeeway time.Duration
// TokenLeewayDuration allows us to remove a period from the IdP access token
// lifetime so we can "guarantee" ours will expire before theirs and force
// a refresh before any errors can come from the IdP.
TokenLeewayDuration time.Duration
// TokenCacheSize is used to control the size of the LRU cache for token validation
// checks. This bounds the memory use to prevent DoS attacks.
TokenCacheSize int
// CodeCacheSize is used to set the number of authorization code in flight.
CodeCacheSize int
// ValidatorCacheSize controls how many per-provider auth0.Validator instances
// are kept in the LRU cache. Each entry holds a built validator keyed by
// provider name + spec fingerprint.
ValidatorCacheSize int
// Auth0ExchangeIssuer is the Auth0 tenant issuer accepted as a passport
// exchange source token issuer.
Auth0ExchangeIssuer string
// Auth0ExchangeAudience is the Auth0 API audience accepted for passport
// exchange source tokens.
Auth0ExchangeAudience string
}
type PassportClaims ¶ added in v1.17.0
type PassportClaims struct {
jwt.Claims `json:",inline"`
// Type distinguishes passports from access tokens.
Type string `json:"typ"`
// Acctype is the account type: "user", "service", or "system".
Acctype openapi.AuthClaimsAcctype `json:"acctype"`
// Source identifies which IdP issued the original token.
Source string `json:"source"`
// Email is the user's email address, if available.
Email string `json:"email,omitempty"`
// OrgIDs is the list of organization IDs the subject is authorized for.
//nolint:tagliatelle
OrgIDs []string `json:"org_ids"`
// OrgID is the current organization context from the exchange request.
//nolint:tagliatelle
OrgID string `json:"org_id,omitempty"`
// ProjectID is the current project context from the exchange request.
//nolint:tagliatelle
ProjectID string `json:"project_id,omitempty"`
// SrcIss is the issuer URL (verbatim, as the IdP emits it) that authenticated
// the subject, or the PassportSourceUNI sentinel for UNI-local tokens. It is
// the security-load-bearing issuer for the platform-admin match; Source
// stays a coarse audit label.
//nolint:tagliatelle
SrcIss string `json:"src_iss"`
// Actor expresses delegation per RFC 8693 section 4.1; omitted when the
// passport's subject is itself the acting party.
Actor *ActorClaim `json:"act,omitempty"`
}
PassportClaims defines the JWT claims for a passport token.
type RefreshTokenClaims ¶ added in v0.2.4
type RefreshTokenClaims struct {
jwt.Claims `json:",inline"`
// Federated is set when the type is a federated user.
Federated *FederatedClaims `json:"fed,omitempty"`
}
RefreshTokenClaims is a basic set of JWT claims, plus a wrapper for the IdP's refresh token.
type Scope ¶
type Scope []string
Scope defines a list of scopes.
func (*Scope) MarshalJSON ¶ added in v0.1.2
MarshalJSON implements json.Marshaller.
func (*Scope) UnmarshalJSON ¶ added in v0.1.2
UnmarshalJSON implments json.Unmarshaller.
type ServiceAccountClaims ¶ added in v0.2.59
type ServiceAccountClaims struct {
// OrganizationID is the identifier of the organization.
OrganizationID string `json:"oid"`
}
type ServiceClaims ¶ added in v0.2.59
type ServiceClaims struct {
//nolint: tagliatelle
X509Thumbprint string `json:"x5t@S256,omitempty"`
}
type State ¶
type State struct {
// Nonce is the one time nonce used to create the token.
Nonce string `json:"n"`
// Code verifier is required to prove our identity when
// exchanging the code with the token endpoint.
CodeVerifier string `json:"cv"`
// OAuth2Provider is the name of the provider configuration in
// use, this will reference the issuer and allow discovery.
OAuth2Provider string `json:"oap"`
// ClientQuery stores the full client query string.
ClientQuery string `json:"cq"`
}
State records state across the call to the authorization server. This must be encrypted with JWE.
type TokenType ¶ added in v0.2.59
type TokenType string
const ( // TokenTypeFederated is used for federated tokens e.g. huamns. TokenTypeFederated TokenType = "fed" // TokenTypeServiceAccount is used for service accounts. TokenTypeServiceAccount TokenType = "sa" // TokenTypeService is used by services acting on behalf of users. // TODO: delete me, services should use mTLS alone. TokenTypeService TokenType = "svc" )
type Tokens ¶ added in v0.2.4
type Tokens struct {
Expiry time.Time
AccessToken string
RefreshToken *string
LastAuthenticationTime time.Time
}
Tokens is the set of tokens and metadata returned by a token issue.