Documentation
¶
Overview ¶
Package oidcauth provides OpenID Connect token verification with optional in-memory caching and role-based authorization helpers.
Basic usage ¶
verifier, err := oidcauth.New(ctx, oidcauth.Config{
RealmURL: "https://keycloak.example.com/realms/main",
ClientID: "my-app",
ClientSecret: "secret",
})
if err != nil {
log.Fatal(err)
}
claims, err := verifier.Verify(ctx, bearerToken)
if err != nil {
// handle errors.Is(err, oidcauth.ErrTokenRevoked), etc.
}
Caching ¶
By default no cache is used and every call to Verify hits the provider. Attach a MemoryCache to avoid redundant network round-trips:
cache := oidcauth.NewMemoryCache(ctx, oidcauth.DefaultCacheDuration) defer cache.Close() verifier, err := oidcauth.New(ctx, config, oidcauth.WithCache(cache))
Custom backends (Redis, Memcached, etc.) can be used by implementing the Cache interface:
type Cache interface {
Get(key string, now time.Time) (Claims, bool)
Set(key string, claims Claims, now time.Time)
}
Role-based authorization ¶
HasRole checks whether a token carries a specific Keycloak client role:
if !verifier.HasRole(claims, "admin") {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
Error handling ¶
All errors wrap one of the package-level sentinels and can be inspected with errors.Is:
switch {
case errors.Is(err, oidcauth.ErrTokenRevoked):
// token was revoked server-side
case errors.Is(err, oidcauth.ErrTokenValidationFailed):
// signature / expiry / audience check failed
case errors.Is(err, oidcauth.ErrIntrospectionFailed):
// could not reach the introspection endpoint
}
Index ¶
Constants ¶
const DefaultCacheDuration = 5 * time.Minute
DefaultCacheDuration is the TTL used when no custom duration is provided.
Variables ¶
var ( ErrInvalidRealmURL = errors.New("invalid OIDC configuration URL") ErrEmptyClientID = errors.New("client ID cannot be empty") ErrTokenValidationFailed = errors.New("token validation failed") ErrProviderInitFailed = errors.New("failed to initialize OIDC provider") ErrIntrospectionFailed = errors.New("token introspection failed") ErrTokenRevoked = errors.New("access token has been revoked") )
Sentinel errors returned by the OIDC verifier.
Functions ¶
This section is empty.
Types ¶
type Cache ¶
type Cache interface {
Get(key string, now time.Time) (Claims, bool)
Set(key string, claims Claims, now time.Time)
}
Cache is the interface for token caching backends. Implement it to plug in Redis, Memcached, or any other store.
type Claims ¶
type Claims struct {
Aud []string `json:"aud"`
AllowedOrigins []string `json:"allowed-origins"`
Jti string `json:"jti"`
Iss string `json:"iss"`
Sub string `json:"sub"`
Typ string `json:"typ"`
Azp string `json:"azp"`
Sid string `json:"sid"`
Acr string `json:"acr"`
Scope string `json:"scope"`
Name string `json:"name"`
PreferredUsername string `json:"preferred_username"`
GivenName string `json:"given_name"`
FamilyName string `json:"family_name"`
Email string `json:"email"`
Exp float64 `json:"exp"`
Iat float64 `json:"iat"`
AuthTime int `json:"auth_time"`
RealmAccess map[string][]string `json:"realm_access"`
ResourceAccess map[string]map[string][]string `json:"resource_access"`
EmailVerified bool `json:"email_verified"`
}
Claims represents the structure of the claims extracted from an authentication token.
type Config ¶
type Config struct {
RealmURL string // Issuer URL (e.g. https://kc.example.com/realms/main).
ClientID string // OAuth client ID used for audience checks and introspection auth.
ClientSecret string // Confidential client secret used for introspection.
RequestTimeout time.Duration // HTTP timeout for provider calls. Defaults to 30s.
SkipIssuerCheck bool // Disable iss claim validation (test-only).
SkipClientIDCheck bool // Disable aud claim validation against ClientID (test-only).
SkipExpiryCheck bool // Disable exp claim validation (test-only).
}
Config controls how the OIDC verifier connects to the identity provider and validates tokens. RealmURL and ClientID are required; everything else has a sensible default.
type Introspection ¶
Introspection represents the result of token introspection, including the claims and the active status of the token.
type MemoryCache ¶
type MemoryCache struct {
// contains filtered or unexported fields
}
MemoryCache is a thread-safe in-memory Cache with TTL-based eviction. Create one with NewMemoryCache and attach it to a verifier via WithCache.
func NewMemoryCache ¶
func NewMemoryCache(ctx context.Context, duration time.Duration) *MemoryCache
NewMemoryCache returns a MemoryCache that caps each entry's TTL at duration and runs a background eviction goroutine until ctx is cancelled or Close is called.
func (*MemoryCache) Close ¶
func (c *MemoryCache) Close()
Close stops the background eviction goroutine. Safe to call multiple times.
type OIDC ¶
type OIDC struct {
// contains filtered or unexported fields
}
OIDC verifies tokens issued by an OpenID Connect provider and exposes helpers for role-based authorization. A single OIDC value is safe for concurrent use.
func New ¶
New builds an OIDC verifier and discovers the provider's metadata. The supplied context bounds only the discovery call; use WithCache to control caching behaviour.
func (*OIDC) HasRole ¶
HasRole reports whether the given claims include the named role for this verifier's client (i.e. claims.ResourceAccess[ClientID].roles).
func (*OIDC) Verify ¶
Verify validates a bearer token and returns its claims.
The flow is:
- cache lookup, return immediately on hit (if a Cache was attached);
- local JWT verification (signature, iss, aud, exp);
- remote introspection to catch revoked-but-not-yet-expired tokens;
- cache the claims (if a Cache was attached).
Any failure in steps 2 or 3 returns ErrTokenValidationFailed; an inactive token returns ErrTokenRevoked. The original error is wrapped so callers using errors.Unwrap can still inspect it.