Documentation
¶
Overview ¶
Package authn cached.go — cache decorator for Authenticator + TokenService.
CachedClient wraps an Authenticator + TokenService pair with a shared cachex-backed cache. Both Authenticate and VerifyToken share the same cache key for a given token, so a token verified via VerifyToken will be served from cache on the next Authenticate call (and vice versa) — important when middleware authenticates via Authenticator.Authenticate but business code calls TokenService.VerifyToken explicitly.
Cache semantics:
- Hit: return cached Principal without calling the inner provider.
- Miss: call inner provider, cache result on success.
- Invalidate(ctx, token): remove entry; call from RevokeToken, LogoutURL, and any path that invalidates a session.
Cache key: "authn:token:" + sha256_hex(token). We hash the token so cache dumps (Redis MONITOR, MEMORY USAGE, etc.) do not leak live bearer tokens.
TTL: min(cfg.ttl, token_exp - now). A token that expires in 30s is cached for at most 30s even if cfg.ttl is 5m. This prevents serving a cached principal for an already-expired token.
Best-effort: if cache.Get/Set/Del fails, the wrapper falls through to the inner provider. A cache outage never blocks authn.
Limitations:
- The cache does NOT enforce revocation. If a token is revoked at the IdP but Invalidate is not called, the cache will keep returning the cached Principal until the TTL expires. Callers that need revocation semantics must maintain a separate blacklist AND call Invalidate on revoke.
- The cache assumes the inner provider's verification is deterministic for a given token within the TTL window. This is true for JWT-based providers (Casdoor, OIDC) but may not be true for introspection-based providers that check a server-side session table. For those, set TTL=0 or do not wrap.
Package authn defines Kernel's authentication and identity-management boundary.
The package is intentionally provider-neutral. A Casdoor adapter should map OAuth code exchange, JWT parsing, users, organizations, applications and group trees into these contracts, but business code should only see Principal.
Typical flow:
- HTTP/gRPC middleware extracts a bearer token.
- Authenticator verifies it and returns Principal.
- Principal is stored in context.
- Business code uses authz.Authorizer for permissions.
Identity provisioning flow:
- Kernel IAM DB creates the platform organization/application/group.
- IdentityAdmin syncs the identity-provider projection, e.g. Casdoor.
- authz.RelationshipWriter projects owner/member relationships to SpiceDB.
Package authn defines Kernel's provider-neutral authentication contracts.
authn owns the question "who is the caller?". It deliberately does not decide whether the caller can access a business resource; that belongs to authz. Casdoor, OIDC, JWT, mTLS and API-key implementations should all adapt into these interfaces.
Index ¶
- Constants
- func ContextWithPrincipal(ctx context.Context, principal Principal) context.Context
- func ErrIdentityBackendFailed(message string, cause error) error
- func ErrInvalidCredential(message string) error
- func ErrInvalidTokenRequest(message string) error
- func ErrMissingCredential(message string) error
- func ErrUnauthenticated(message string) error
- func ValidateApplication(app Application) error
- func ValidateAuthCodeExchangeRequest(req AuthCodeExchangeRequest) error
- func ValidateGroup(group Group) error
- func ValidateOrganization(org Organization) error
- type Application
- type ApplicationAdmin
- type AssignUserToGroupRequest
- type AttributeSet
- type AuthCodeExchangeRequest
- type Authenticator
- type CachedClient
- func (c *CachedClient) Authenticate(ctx context.Context, credential Credential) (Principal, error)
- func (c *CachedClient) ExchangeCode(ctx context.Context, req AuthCodeExchangeRequest) (TokenSet, Principal, error)
- func (c *CachedClient) Invalidate(ctx context.Context, token string) error
- func (c *CachedClient) RefreshToken(ctx context.Context, req RefreshTokenRequest) (TokenSet, error)
- func (c *CachedClient) RevokeToken(ctx context.Context, req RevokeTokenRequest) error
- func (c *CachedClient) VerifyToken(ctx context.Context, req VerifyTokenRequest) (Principal, error)
- type CachedOption
- type CallbackRequest
- type CallbackResult
- type CreateApplicationRequest
- type CreateGroupRequest
- type CreateOrganizationRequest
- type Credential
- type DeleteApplicationRequest
- type DeleteGroupRequest
- type DeleteOrganizationRequest
- type Group
- type GroupAdmin
- type GroupFilter
- type IdentityAdmin
- type IdentityProfile
- type IdentityProfileRequest
- type LoginService
- type LoginURL
- type LoginURLRequest
- type Organization
- type OrganizationAdmin
- type Principal
- func (p Principal) Attribute(key string) any
- func (p Principal) Expired(now time.Time) bool
- func (p Principal) HasGroup(group string) bool
- func (p Principal) HasRole(role string) bool
- func (p Principal) HasScope(scope string) bool
- func (p Principal) IsAnonymous() bool
- func (p Principal) IsAuthenticated() bool
- func (p Principal) Normalize() Principal
- type ProfileService
- type RefreshTokenRequest
- type RevokeTokenRequest
- type TokenAuthenticator
- type TokenService
- type TokenSet
- type TokenVerifier
- type UpdateApplicationRequest
- type UpdateGroupRequest
- type UpdateOrganizationRequest
- type User
- type UserDirectory
- type UserFilter
- type VerifyTokenRequest
Constants ¶
const ( CodeMissingCredential = errorx.Code("AUTHN_MISSING_CREDENTIAL") CodeInvalidCredential = errorx.Code("AUTHN_INVALID_CREDENTIAL") CodeUnauthenticated = errorx.Code("AUTHN_UNAUTHENTICATED") CodeInvalidTokenRequest = errorx.Code("AUTHN_INVALID_TOKEN_REQUEST") CodeIdentityBackendFailed = errorx.Code("AUTHN_IDENTITY_BACKEND_FAILED") CodeIdentityObjectNotFound = errorx.Code("AUTHN_IDENTITY_OBJECT_NOT_FOUND") CodeIdentityObjectConflict = errorx.Code("AUTHN_IDENTITY_OBJECT_CONFLICT") CodeUnsupportedIdentityFlow = errorx.Code("AUTHN_UNSUPPORTED_IDENTITY_FLOW") )
const ( SubjectTypeUser = "user" SubjectTypeService = "service" SubjectTypeAgent = "agent" SubjectTypeWorkflow = "workflow" SubjectTypeWorkload = "workload" SubjectTypeAnonymous = "anonymous" )
const ( AuthMethodOAuth = "oauth" AuthMethodOIDC = "oidc" AuthMethodJWT = "jwt" AuthMethodAPIKey = "api_key" AuthMethodMTLS = "mtls" AuthMethodSession = "session" AuthMethodDevToken = "dev_token" AuthMethodNone = "none" )
const ( CredentialBearer = "bearer" CredentialBasic = "basic" CredentialAPIKey = "api_key" CredentialMTLS = "mtls" CredentialCode = "authorization_code" )
const ( // Casdoor group types. A user can belong to one Physical group and multiple Virtual groups. GroupTypePhysical = "Physical" GroupTypeVirtual = "Virtual" )
Variables ¶
This section is empty.
Functions ¶
func ContextWithPrincipal ¶
func ErrInvalidCredential ¶
func ErrInvalidTokenRequest ¶
func ErrMissingCredential ¶
func ErrUnauthenticated ¶
func ValidateApplication ¶
func ValidateApplication(app Application) error
func ValidateAuthCodeExchangeRequest ¶
func ValidateAuthCodeExchangeRequest(req AuthCodeExchangeRequest) error
func ValidateGroup ¶
func ValidateOrganization ¶
func ValidateOrganization(org Organization) error
Types ¶
type Application ¶
type Application struct {
ID string
ExternalID string
OrgID string
Name string
DisplayName string
ClientID string
ClientSecret string
RedirectURIs []string
GrantTypes []string
Scopes []string
Providers []string
EnablePassword bool
EnableSignup bool
Attributes AttributeSet
}
Application represents a login client/application in the identity provider.
type ApplicationAdmin ¶
type ApplicationAdmin interface {
CreateApplication(ctx context.Context, req CreateApplicationRequest) (Application, error)
GetApplication(ctx context.Context, orgID, appID string) (Application, error)
UpdateApplication(ctx context.Context, req UpdateApplicationRequest) (Application, error)
DeleteApplication(ctx context.Context, req DeleteApplicationRequest) error
}
ApplicationAdmin manages identity-provider applications / OAuth clients.
type AttributeSet ¶
AttributeSet carries provider-specific claims or admin metadata. Values should be JSON-serializable when they are persisted or sent to remote systems.
type AuthCodeExchangeRequest ¶
type AuthCodeExchangeRequest struct {
Code string
State string
RedirectURI string
CodeVerifier string
OrgID string
AppID string
Metadata map[string]string
}
AuthCodeExchangeRequest is the provider-neutral shape for OAuth code exchange.
type Authenticator ¶
type Authenticator interface {
Authenticate(ctx context.Context, credential Credential) (Principal, error)
}
Authenticator verifies a transport credential and returns a normalized Principal.
type CachedClient ¶ added in v0.0.3
type CachedClient struct {
// contains filtered or unexported fields
}
CachedClient wraps an Authenticator + TokenService with a shared cache.
Construction:
client := casdoor.New(cfg) // implements both interfaces
cached := authn.NewCachedClient(client, client, cache,
authn.WithCachedTTL(5*time.Minute))
_ = authn.Authenticator(cached) // usable as Authenticator
_ = authn.TokenService(cached) // usable as TokenService
Both `auth` and `tokens` may point to the same object (typical for the casdoor Client which implements both). They are accepted separately so callers can mix providers (e.g. JWT verifier for Authenticate, introspection endpoint for TokenService) if needed.
func NewCachedClient ¶ added in v0.0.3
func NewCachedClient(auth Authenticator, tokens TokenService, cache cachex.Cache, opts ...CachedOption) *CachedClient
NewCachedClient wraps an Authenticator + TokenService with a cache.
If cache is nil, the returned CachedClient delegates every call to the inner providers without any caching. This lets callers always go through CachedClient (no nil checks) even when caching is disabled.
func (*CachedClient) Authenticate ¶ added in v0.0.3
func (c *CachedClient) Authenticate(ctx context.Context, credential Credential) (Principal, error)
Authenticate verifies the credential and returns the cached Principal on hit, or delegates to the inner Authenticator on miss.
func (*CachedClient) ExchangeCode ¶ added in v0.0.3
func (c *CachedClient) ExchangeCode(ctx context.Context, req AuthCodeExchangeRequest) (TokenSet, Principal, error)
ExchangeCode is a one-shot operation — never cached. Delegates directly.
func (*CachedClient) Invalidate ¶ added in v0.0.3
func (c *CachedClient) Invalidate(ctx context.Context, token string) error
Invalidate removes a token's cached Principal. Call this from revocation flows that bypass RevokeToken (e.g. hub's local-blacklist fallback when the IdP's RevokeToken is UNIMPLEMENTED) so the next Authenticate/VerifyToken re-queries the inner provider (or, more usefully, the hub blacklist layer rejects the call before it reaches the cache).
func (*CachedClient) RefreshToken ¶ added in v0.0.3
func (c *CachedClient) RefreshToken(ctx context.Context, req RefreshTokenRequest) (TokenSet, error)
RefreshToken is a one-shot operation — never cached. Delegates directly.
func (*CachedClient) RevokeToken ¶ added in v0.0.3
func (c *CachedClient) RevokeToken(ctx context.Context, req RevokeTokenRequest) error
RevokeToken delegates to the inner TokenService and, on success, removes the token from the cache. On failure, the cache entry is left untouched (the inner provider may have rejected the request, in which case there is nothing to invalidate; or the inner provider is UNIMPLEMENTED, in which case the caller — typically a hub-level repo — should call Invalidate explicitly after updating its own blacklist).
func (*CachedClient) VerifyToken ¶ added in v0.0.3
func (c *CachedClient) VerifyToken(ctx context.Context, req VerifyTokenRequest) (Principal, error)
VerifyToken verifies the token and returns the cached Principal on hit, or delegates to the inner TokenService on miss.
type CachedOption ¶ added in v0.0.3
type CachedOption func(*CachedClient)
CachedOption configures a CachedClient.
func WithCachedTTL ¶ added in v0.0.3
func WithCachedTTL(ttl time.Duration) CachedOption
WithCachedTTL sets the maximum cache TTL. The effective TTL for a given token is min(this, token_exp - now). Default is 5 minutes. Set to 0 to effectively disable caching (every call goes to the inner provider).
type CallbackRequest ¶
type CallbackRequest struct {
Code string
State string
ExpectedState string
RedirectURI string
OrgID string
AppID string
Metadata map[string]string
}
CallbackRequest is the provider-neutral OAuth/OIDC callback payload.
type CallbackResult ¶
CallbackResult is the result of a successful browser callback flow.
type CreateApplicationRequest ¶
type CreateApplicationRequest struct {
Application Application
IdempotencyKey string
Metadata map[string]string
}
type CreateGroupRequest ¶
type CreateOrganizationRequest ¶
type CreateOrganizationRequest struct {
Organization Organization
IdempotencyKey string
Metadata map[string]string
}
type Credential ¶
Credential is authentication input extracted by HTTP/gRPC middleware.
func BearerCredential ¶
func BearerCredential(header string) (Credential, bool)
type DeleteGroupRequest ¶
type Group ¶
type Group struct {
ID string
ExternalID string
OrgID string
ParentID string
Name string
DisplayName string
Type string
Path string
Users []string
Attributes AttributeSet
}
Group models Casdoor's organization tree/groups without coupling Kernel to Casdoor names. Group.Type can be physical, virtual, team, etc.
type GroupAdmin ¶
type GroupAdmin interface {
CreateGroup(ctx context.Context, req CreateGroupRequest) (Group, error)
GetGroup(ctx context.Context, orgID, groupID string) (Group, error)
ListGroups(ctx context.Context, filter GroupFilter) ([]Group, error)
UpdateGroup(ctx context.Context, req UpdateGroupRequest) (Group, error)
DeleteGroup(ctx context.Context, req DeleteGroupRequest) error
AssignUserToGroup(ctx context.Context, req AssignUserToGroupRequest) error
RemoveUserFromGroup(ctx context.Context, req AssignUserToGroupRequest) error
}
GroupAdmin manages app/org group trees. Casdoor maps this naturally to organization groups with ParentGroup.
type GroupFilter ¶
type IdentityAdmin ¶
type IdentityAdmin interface {
TokenService
UserDirectory
OrganizationAdmin
ApplicationAdmin
GroupAdmin
}
IdentityAdmin is the full identity management surface expected from a Casdoor adapter. Keep it out of normal business services; use it in IAM provisioning.
func NoopAdmin ¶
func NoopAdmin() IdentityAdmin
NoopAdmin returns an IdentityAdmin that reports unsupported operations. Use it as a safe default when identity provisioning is explicitly disabled.
type IdentityProfile ¶
type IdentityProfile struct {
Principal Principal
// User is the canonical user projection from the identity provider when it
// can be read. It may be zero when only token claims were available.
User User
// Groups contains expanded group objects. Principal.Groups and User.Groups
// are usually only group IDs/names; this slice carries display names, parent
// IDs and group type when available.
Groups []Group
// CurrentApplication is the login/OIDC application used by the current flow.
// A user does not usually "belong" to an application in the same way they
// belong to a group; the application here means the OAuth client that issued
// the token or handled the login.
CurrentApplication Application
Warnings []string
Attributes AttributeSet
}
IdentityProfile is the normalized post-login identity snapshot used by handlers, middleware and Kernel IAM sync logic.
func (IdentityProfile) GroupIDs ¶
func (p IdentityProfile) GroupIDs() []string
func (IdentityProfile) HasFullUser ¶
func (p IdentityProfile) HasFullUser() bool
func (IdentityProfile) IsPartial ¶
func (p IdentityProfile) IsPartial() bool
type IdentityProfileRequest ¶
type IdentityProfileRequest struct {
Principal Principal
Token string
Credential Credential
OrgID string
AppID string
IncludeUser bool
IncludeGroups bool
IncludeCurrentApplication bool
// AllowPartial returns Principal plus whatever profile data can be read when
// admin/read APIs fail. This is useful for normal request paths where token
// authentication must not fail only because optional profile enrichment is
// unavailable.
AllowPartial bool
Metadata map[string]string
}
IdentityProfileRequest controls how much identity-provider data should be loaded after login or token verification.
For request handling, pass Principal when you already have one from Authenticate/VerifyToken. For test tools and middleware, pass Token or Credential and the implementation will authenticate first.
type LoginService ¶
type LoginService interface {
BuildLoginURL(ctx context.Context, req LoginURLRequest) (LoginURL, error)
HandleCallback(ctx context.Context, req CallbackRequest) (CallbackResult, error)
}
LoginService is the provider-neutral browser login contract used by HTTP handlers, examples and application boot code. Implementations can use Casdoor/OIDC SDKs internally, but callers only depend on Kernel authn types.
type LoginURL ¶
type LoginURL struct {
URL string
RedirectURI string
State string
Scope string
Provider string
OrgID string
AppID string
}
LoginURL is the safe redirect target returned by LoginService.
type LoginURLRequest ¶
type LoginURLRequest struct {
RedirectURI string
State string
Scope string
OrgID string
AppID string
Metadata map[string]string
}
LoginURLRequest asks an identity provider for a hosted login URL.
type Organization ¶
type Organization struct {
ID string
ExternalID string
Name string
DisplayName string
OwnerID string
ParentID string
Tags []string
Enabled bool
Attributes AttributeSet
}
Organization is Kernel's identity-side organization projection. Kernel IAM DB can store richer business org metadata; this type is for authn provider sync.
type OrganizationAdmin ¶
type OrganizationAdmin interface {
CreateOrganization(ctx context.Context, req CreateOrganizationRequest) (Organization, error)
GetOrganization(ctx context.Context, orgID string) (Organization, error)
UpdateOrganization(ctx context.Context, req UpdateOrganizationRequest) (Organization, error)
DeleteOrganization(ctx context.Context, req DeleteOrganizationRequest) error
}
OrganizationAdmin manages identity-provider organizations.
type Principal ¶
type Principal struct {
SubjectID string
SubjectType string
Provider string
ExternalID string
Issuer string
Audience []string
TenantID string
OrgID string
AppID string
ProjectID string
Username string
Name string
Email string
Phone string
Roles []string
Groups []string
Scopes []string
// AuthMethod records how the subject authenticated. It is intentionally a
// string instead of an enum type so adapters can preserve provider-specific
// methods while still using the AuthMethod* constants above.
AuthMethod string
Attributes AttributeSet
IssuedAt time.Time
ExpiresAt time.Time
}
Principal is the normalized identity passed to business code.
SubjectID must be stable inside Kernel. For Casdoor this should normally map from the Casdoor user's stable UUID when available, not only owner/name.
func (Principal) IsAnonymous ¶
func (Principal) IsAuthenticated ¶
type ProfileService ¶
type ProfileService interface {
GetIdentityProfile(ctx context.Context, req IdentityProfileRequest) (IdentityProfile, error)
}
ProfileService enriches an authenticated Principal with identity-provider profile data. It is intentionally provider-neutral: callers should not have to know whether the backing system is Casdoor, OIDC, LDAP, SCIM, etc.
type RefreshTokenRequest ¶
type RevokeTokenRequest ¶
type TokenAuthenticator ¶
type TokenAuthenticator struct {
Verifier TokenVerifier
Issuer string
Audience []string
OrgID string
AppID string
}
TokenAuthenticator adapts a TokenService/TokenVerifier to Authenticator.
func (TokenAuthenticator) Authenticate ¶
func (a TokenAuthenticator) Authenticate(ctx context.Context, credential Credential) (Principal, error)
type TokenService ¶
type TokenService interface {
ExchangeCode(ctx context.Context, req AuthCodeExchangeRequest) (TokenSet, Principal, error)
RefreshToken(ctx context.Context, req RefreshTokenRequest) (TokenSet, error)
VerifyToken(ctx context.Context, req VerifyTokenRequest) (Principal, error)
RevokeToken(ctx context.Context, req RevokeTokenRequest) error
}
TokenService covers OAuth/OIDC token flows such as Casdoor code exchange, refresh, validation and revocation.
type TokenSet ¶
type TokenSet struct {
AccessToken string
RefreshToken string
IDToken string
TokenType string
Scope string
ExpiresAt time.Time
Raw AttributeSet
}
TokenSet is the result of OAuth/OIDC token operations.
type TokenVerifier ¶
type TokenVerifier func(ctx context.Context, req VerifyTokenRequest) (Principal, error)
TokenVerifier adapts JWT/OIDC libraries into Authenticator.
type UpdateApplicationRequest ¶
type UpdateApplicationRequest struct {
Application Application
Metadata map[string]string
}
type UpdateGroupRequest ¶
type UpdateOrganizationRequest ¶
type UpdateOrganizationRequest struct {
Organization Organization
Metadata map[string]string
}
type User ¶
type User struct {
ID string
ExternalID string
Provider string
OrgID string
Username string
DisplayName string
Email string
Phone string
Roles []string
Groups []string
Enabled bool
Attributes AttributeSet
}
User mirrors identity-provider user data without importing a provider SDK.
type UserDirectory ¶
type UserDirectory interface {
GetUser(ctx context.Context, orgID, userID string) (User, error)
FindUsers(ctx context.Context, filter UserFilter) ([]User, error)
UpsertUser(ctx context.Context, user User) (User, error)
DisableUser(ctx context.Context, orgID, userID string) error
}
UserDirectory reads and provisions identity-provider users. Business modules should usually go through Kernel IAM service, not a provider SDK directly.
type UserFilter ¶
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package callback contains reusable HTTP helpers for browser based authn callback flows.
|
Package callback contains reusable HTTP helpers for browser based authn callback flows. |
|
Package casdoor adapts the official Casdoor Go SDK to Kernel authn contracts.
|
Package casdoor adapts the official Casdoor Go SDK to Kernel authn contracts. |