trust

package
v0.7.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 1, 2026 License: BSD-2-Clause Imports: 29 Imported by: 0

Documentation

Overview

Package trust — JWKSKeyResolver implements SD-JWT VC spec §5.3 key resolution with a multi-endpoint discovery chain for maximum interoperability.

Package trust provides a unified trust evaluation interface for all credential formats.

This package bridges the gap between different credential formats' trust models:

  • W3C VC 2.0 Data Integrity: uses DIDs for key identification
  • SD-JWT VC: uses x5c certificate chains with issuer URLs
  • ISO mDOC: uses IACA certificate chains with document signer certificates

The key distinction is between:

  • Name-to-key RESOLUTION: Given a name (DID), fetch the associated public key
  • Name-to-key VALIDATION: Given a name and key, verify the binding is trusted

When DIDs are used, go-trust can perform resolution. When certificates are used (SD-JWT x5c, mDOC MSO), the key is already present, so only validation is needed.

This package uses types from github.com/sirosfoundation/go-trust/pkg/trustapi and adds vc-specific logic like GetEffectiveAction() for policy routing.

Index

Examples

Constants

View Source
const (
	// DefaultTrustCacheTTL is the default TTL for trust decisions.
	// Trust decisions are relatively stable, so a longer TTL is appropriate.
	DefaultTrustCacheTTL = 5 * time.Minute

	// MaxTrustCacheTTL is the maximum TTL for trust decisions.
	MaxTrustCacheTTL = 1 * time.Hour
)
View Source
const (
	// DefaultJWKSCacheTTL is the default TTL for cached JWKS entries.
	DefaultJWKSCacheTTL = 5 * time.Minute

	// DefaultJWKSMaxCapacity is the default max capacity for the JWKS cache.
	DefaultJWKSMaxCapacity = 100
)
View Source
const (
	KeyTypeJWK = trustapi.KeyTypeJWK
	KeyTypeX5C = trustapi.KeyTypeX5C

	RoleIssuer             = trustapi.RoleIssuer
	RoleVerifier           = trustapi.RoleVerifier
	RoleWalletProvider     = trustapi.RoleWalletProvider
	RolePIDProvider        = trustapi.RolePIDProvider
	RoleCredentialIssuer   = trustapi.RoleCredentialIssuer
	RoleCredentialVerifier = trustapi.RoleCredentialVerifier
	RoleAny                = trustapi.RoleAny
)

Constants re-exported from trustapi for convenience.

View Source
const (
	WIAModeETSI = "etsi"
	WIAModeIETF = "ietf"
)

WIA trust-model modes — see WalletAttestationEvaluator.Mode. Mirrors go-wallet-backend's WIAConfig.Mode terminology so operators configure both sides of an interop pair consistently.

View Source
const (
	// ErrMsgNilRequest is returned when an evaluation request is nil.
	ErrMsgNilRequest = "evaluation request is nil"
)

Error messages for trust evaluation. These are package-level constants to ensure consistency across evaluator implementations.

View Source
const (
	// TrustFrameworkNone indicates no trust framework validation occurred.
	// Used by AllowAllEvaluator when operating without a PDP.
	TrustFrameworkNone = "none"
)

TrustFramework constants for common trust framework identifiers.

Variables

View Source
var DefaultAllowedAlgorithms = []string{
	"ES256", "ES384", "ES512",
	"RS256", "RS384", "RS512",
	"PS256", "PS384", "PS512",
	"EdDSA",
}

DefaultAllowedAlgorithms is the secure default set of allowed JWT signature algorithms. These are all considered cryptographically strong as of 2024.

Functions

func BuildAllowedAlgorithmSet added in v0.5.7

func BuildAllowedAlgorithmSet(allowedAlgorithms []string) map[string]bool

BuildAllowedAlgorithmSet creates a set of allowed algorithms for O(1) lookup. The "none" algorithm is NEVER allowed regardless of configuration.

func BuildWalletAttestationPolicyQuery added in v0.7.0

func BuildWalletAttestationPolicyQuery(attestationSource, scope, issuer string) sexp.Element

BuildWalletAttestationPolicyQuery constructs a SPOCP query for wallet attestation authorization. Query format: (wallet (attestation_source <tier>)(scope <scope>)(issuer <provider>))

func ExtractJWTClaimsInfo added in v0.5.7

func ExtractJWTClaimsInfo(token *jwt.Token) (issuerID, credentialType string)

ExtractJWTClaimsInfo extracts the issuer identifier and credential type from JWT claims.

func ValidateSigningMethodForKey added in v0.5.7

func ValidateSigningMethodForKey(token *jwt.Token, publicKey crypto.PublicKey) error

ValidateSigningMethodForKey checks that the JWT signing method is compatible with the provided public key type.

Types

type AllowAllEvaluator

type AllowAllEvaluator struct{}

AllowAllEvaluator is a TrustEvaluator that always returns trusted=true. This is used when no PDP URL is configured ("allow all" mode).

In "allow all" mode:

  • All trust evaluation requests return Trusted=true
  • The TrustFramework is set to "none" to indicate no trust validation occurred
  • Key resolution is not supported (returns an error)

This provides a consistent behavior across applications when trust evaluation is not required or during development/testing scenarios.

func NewAllowAllEvaluator

func NewAllowAllEvaluator() *AllowAllEvaluator

NewAllowAllEvaluator creates a trust evaluator that accepts all requests. Use this when operating in "allow all" mode without a PDP.

Example
package main

import (
	"fmt"

	"github.com/SUNET/vc/pkg/trust"
)

func main() {
	evaluator := trust.NewAllowAllEvaluator()
	fmt.Printf("%T\n", evaluator)
}
Output:
*trust.AllowAllEvaluator

func (*AllowAllEvaluator) Evaluate

Evaluate implements TrustEvaluator. Always returns trusted=true for supported key types.

Example
package main

import (
	"context"
	"fmt"

	"github.com/SUNET/vc/pkg/trust"
)

func main() {
	ctx := context.Background()
	evaluator := trust.NewAllowAllEvaluator()

	req := trust.NewEvaluationRequest("https://issuer.example.com", trust.KeyTypeJWK, nil)
	decision, err := evaluator.Evaluate(ctx, req)
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	fmt.Println("trusted:", decision.Trusted)
	fmt.Println("reason:", decision.Reason)
	fmt.Println("framework:", decision.TrustFramework)
}
Output:
trusted: true
reason: allow all mode: no PDP configured
framework: none

func (*AllowAllEvaluator) ResolveKey

func (e *AllowAllEvaluator) ResolveKey(ctx context.Context, verificationMethod string) (crypto.PublicKey, error)

ResolveKey attempts to resolve a key but is not supported in allow-all mode. Key resolution requires an actual PDP service to resolve DIDs and verify trust.

func (*AllowAllEvaluator) SupportsKeyType

func (e *AllowAllEvaluator) SupportsKeyType(kt KeyType) bool

SupportsKeyType implements TrustEvaluator. Supports JWK and X5C key types.

Example
package main

import (
	"fmt"

	"github.com/SUNET/vc/pkg/trust"
)

func main() {
	evaluator := trust.NewAllowAllEvaluator()

	fmt.Println("supports JWK:", evaluator.SupportsKeyType(trust.KeyTypeJWK))
	fmt.Println("supports X5C:", evaluator.SupportsKeyType(trust.KeyTypeX5C))
}
Output:
supports JWK: true
supports X5C: true

type CachedDecision

type CachedDecision struct {
	Decision  *TrustDecision
	CachedAt  time.Time
	ExpiresAt time.Time
}

CachedDecision wraps a TrustDecision with cache metadata.

type CachingTrustEvaluator

type CachingTrustEvaluator struct {
	// contains filtered or unexported fields
}

CachingTrustEvaluator wraps a TrustEvaluator with caching.

func NewCachingTrustEvaluator

func NewCachingTrustEvaluator(evaluator TrustEvaluator, config TrustCacheConfig) *CachingTrustEvaluator

NewCachingTrustEvaluator creates a caching wrapper around a TrustEvaluator.

func (*CachingTrustEvaluator) Cache

func (c *CachingTrustEvaluator) Cache() *TrustCache

Cache returns the underlying cache for advanced operations.

func (*CachingTrustEvaluator) Clear

func (c *CachingTrustEvaluator) Clear()

Clear removes all entries from the cache.

func (*CachingTrustEvaluator) Evaluate

Evaluate checks the cache first, then delegates to the wrapped evaluator.

func (*CachingTrustEvaluator) Invalidate

func (c *CachingTrustEvaluator) Invalidate(req *EvaluationRequest)

Invalidate removes an entry from the cache.

func (*CachingTrustEvaluator) Stop

func (c *CachingTrustEvaluator) Stop()

Stop stops the cache's automatic expiration.

func (*CachingTrustEvaluator) SupportsKeyType

func (c *CachingTrustEvaluator) SupportsKeyType(kt KeyType) bool

SupportsKeyType delegates to the wrapped evaluator.

type CombinedTrustService

type CombinedTrustService interface {
	TrustEvaluator
	KeyResolver
}

CombinedTrustService combines evaluation and resolution capabilities. This is the full interface for trust management across all credential formats.

type CompositeEvaluator

type CompositeEvaluator struct {
	// contains filtered or unexported fields
}

CompositeEvaluator combines multiple TrustEvaluators with configurable strategy.

func NewCompositeEvaluator

func NewCompositeEvaluator(strategy CompositeStrategy, evaluators ...TrustEvaluator) *CompositeEvaluator

NewCompositeEvaluator creates a composite evaluator with the given strategy.

Example
package main

import (
	"context"
	"fmt"

	"github.com/SUNET/vc/pkg/trust"
)

func main() {
	ctx := context.Background()

	// Create a composite evaluator with two AllowAll evaluators using FirstSuccess strategy
	eval1 := trust.NewAllowAllEvaluator()
	eval2 := trust.NewAllowAllEvaluator()
	composite := trust.NewCompositeEvaluator(trust.StrategyFirstSuccess, eval1, eval2)

	req := trust.NewEvaluationRequest("https://issuer.example.com", trust.KeyTypeJWK, nil)
	decision, err := composite.Evaluate(ctx, req)
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	fmt.Println("trusted:", decision.Trusted)
	fmt.Println("supports JWK:", composite.SupportsKeyType(trust.KeyTypeJWK))
}
Output:
trusted: true
supports JWK: true

func (*CompositeEvaluator) AddEvaluator

func (c *CompositeEvaluator) AddEvaluator(eval TrustEvaluator)

AddEvaluator adds an evaluator to the composite.

func (*CompositeEvaluator) Evaluate

Evaluate implements TrustEvaluator.

func (*CompositeEvaluator) SupportsKeyType

func (c *CompositeEvaluator) SupportsKeyType(kt KeyType) bool

SupportsKeyType returns true if any evaluator supports the given key type.

type CompositeStrategy

type CompositeStrategy int

CompositeStrategy determines how multiple evaluators are combined.

const (
	// StrategyFirstSuccess returns success on the first positive decision.
	// This is useful for "any trust source" scenarios.
	StrategyFirstSuccess CompositeStrategy = iota

	// StrategyAllMustSucceed requires all evaluators to return a positive decision.
	// This is useful for "all trust sources must agree" scenarios.
	StrategyAllMustSucceed

	// StrategyFallback tries evaluators in order, returning the first non-error result.
	// This is useful for "try local first, then remote" scenarios.
	StrategyFallback
)

type EvaluationRequest

type EvaluationRequest struct {
	trustapi.EvaluationRequest
}

EvaluationRequest contains the parameters for a trust evaluation. This embeds trustapi.EvaluationRequest and adds vc-specific methods.

func NewEvaluationRequest

func NewEvaluationRequest(subjectID string, keyType KeyType, key any) *EvaluationRequest

NewEvaluationRequest creates a new EvaluationRequest with the given parameters. This is a convenience constructor.

Example
package main

import (
	"fmt"

	"github.com/SUNET/vc/pkg/trust"
)

func main() {
	req := trust.NewEvaluationRequest(
		"https://issuer.example.com",
		trust.KeyTypeJWK,
		nil,
	)

	fmt.Println("subject:", req.SubjectID)
	fmt.Println("key type:", req.KeyType)
}
Output:
subject: https://issuer.example.com
key type: jwk

func (*EvaluationRequest) GetEffectiveAction

func (r *EvaluationRequest) GetEffectiveAction() string

GetEffectiveAction returns the action name to use for policy routing. Priority: 1. Explicit Action field, 2. Composed from Role + CredentialType/DocType, 3. Role alone

This is vc-specific logic that maps credential types to go-trust policy names.

Example
package main

import (
	"fmt"

	"github.com/SUNET/vc/pkg/trust"
)

func main() {
	// With explicit role set
	req := trust.NewEvaluationRequest("https://issuer.example.com", trust.KeyTypeJWK, nil)
	req.Role = trust.RoleIssuer
	req.CredentialType = "PID"

	fmt.Println("PID issuer action:", req.GetEffectiveAction())

	// With a verifier role
	req2 := trust.NewEvaluationRequest("https://verifier.example.com", trust.KeyTypeJWK, nil)
	req2.Role = trust.RoleVerifier

	fmt.Println("verifier action:", req2.GetEffectiveAction())
}
Output:
PID issuer action: pid-provider
verifier action: credential-verifier

type GoTrustEvaluator

type GoTrustEvaluator struct {
	// contains filtered or unexported fields
}

GoTrustEvaluator implements TrustEvaluator using go-trust AuthZEN client. It can validate both JWK and x5c key types against a Policy Decision Point.

func NewGoTrustEvaluator

func NewGoTrustEvaluator(pdpURL string) *GoTrustEvaluator

NewGoTrustEvaluator creates a trust evaluator using go-trust with a known PDP URL.

func NewGoTrustEvaluatorWithClient

func NewGoTrustEvaluatorWithClient(client *authzenclient.Client) *GoTrustEvaluator

NewGoTrustEvaluatorWithClient creates a trust evaluator with a pre-configured client.

func NewGoTrustEvaluatorWithDiscovery

func NewGoTrustEvaluatorWithDiscovery(ctx context.Context, baseURL string) (*GoTrustEvaluator, error)

NewGoTrustEvaluatorWithDiscovery creates a trust evaluator using AuthZEN discovery.

func (*GoTrustEvaluator) Evaluate

Evaluate implements TrustEvaluator.

func (*GoTrustEvaluator) GetClient

func (e *GoTrustEvaluator) GetClient() *authzenclient.Client

GetClient returns the underlying AuthZEN client for advanced usage.

func (*GoTrustEvaluator) ResolveKey

func (e *GoTrustEvaluator) ResolveKey(ctx context.Context, verificationMethod string) (crypto.PublicKey, error)

ResolveKey implements KeyResolver for DID-based resolution.

func (*GoTrustEvaluator) SupportsKeyType

func (e *GoTrustEvaluator) SupportsKeyType(kt KeyType) bool

SupportsKeyType implements TrustEvaluator.

type JWKSKeyResolver

type JWKSKeyResolver struct {
	// contains filtered or unexported fields
}

JWKSKeyResolver resolves issuer public keys using a multi-endpoint discovery chain per SD-JWT VC §5.3 with fallbacks for maximum interoperability:

  1. .well-known/jwt-vc-issuer → inline jwks or jwks_uri (SD-JWT VC §5.3 primary)
  2. .well-known/openid-credential-issuer → authorization_servers → AS metadata → jwks_uri
  3. .well-known/openid-configuration → jwks_uri (OIDC Discovery)
  4. .well-known/oauth-authorization-server → jwks_uri (RFC 8414)

Resolved JWKS are cached per issuer URL. Keys are matched by kid.

func NewJWKSKeyResolver

func NewJWKSKeyResolver(config JWKSResolverConfig) *JWKSKeyResolver

NewJWKSKeyResolver creates a new resolver for SD-JWT VC issuer key resolution. The parseJWK function must be provided to convert JWK maps to crypto.PublicKey (this avoids coupling pkg/trust to pkg/jose).

func (*JWKSKeyResolver) InvalidateIssuer

func (r *JWKSKeyResolver) InvalidateIssuer(issuerURL string)

InvalidateIssuer removes a cached JWKS for a specific issuer. Useful when key rotation is detected (e.g., kid not found in cached JWKS).

func (*JWKSKeyResolver) Len

func (r *JWKSKeyResolver) Len() int

Len returns the number of issuers currently cached.

func (*JWKSKeyResolver) ResolveKeyByKID

func (r *JWKSKeyResolver) ResolveKeyByKID(ctx context.Context, issuerURL, kid string) (crypto.PublicKey, map[string]any, error)

ResolveKeyByKID resolves the public key for the given issuer and kid. Returns the public key and the JWK map (for trust evaluation).

Per SD-JWT VC §5.3, the metadata is fetched from {issuer}/.well-known/jwt-vc-issuer. Resolved JWKS are cached per issuer URL.

func (*JWKSKeyResolver) Stop

func (r *JWKSKeyResolver) Stop()

Stop stops the cache's automatic expiration goroutine.

type JWKSResolverConfig

type JWKSResolverConfig struct {
	// HTTPClient is the HTTP client used for fetching metadata and JWKS.
	// If nil, a default client with 30s timeout is used.
	HTTPClient *http.Client

	// CacheTTL is the time-to-live for cached JWKS entries per issuer.
	// Default: 5 minutes.
	CacheTTL time.Duration

	// MaxCapacity is the maximum number of issuers to cache.
	// Default: 100.
	MaxCapacity uint64

	// ParseJWKToPublicKey converts a JWK map to a crypto.PublicKey.
	// If nil, a default implementation using lestrrat-go/jwx is expected
	// to be injected by the caller (avoids coupling pkg/trust to pkg/jose).
	ParseJWKToPublicKey func(jwkData any) (crypto.PublicKey, error)
}

JWKSResolverConfig contains configuration for the JWKSKeyResolver.

type JWTKeyMaterial added in v0.5.7

type JWTKeyMaterial struct {
	KeyType     KeyType
	KeyMaterial any
	PublicKey   crypto.PublicKey
	IssuerID    string
}

JWTKeyMaterial holds key material extracted from a JWT header for signature verification and trust evaluation.

type JWTTrustVerifier added in v0.5.7

type JWTTrustVerifier struct {
	// contains filtered or unexported fields
}

JWTTrustVerifier verifies JWT credential signatures and evaluates issuer trust. It handles key extraction from x5c, jwk, DID, and kid/JWKS headers, verifies signatures, and delegates trust decisions to the configured TrustEvaluator.

func NewJWTTrustVerifier added in v0.5.7

func NewJWTTrustVerifier(cfg JWTTrustVerifierConfig) *JWTTrustVerifier

NewJWTTrustVerifier creates a new JWT trust verifier with the given configuration.

func (*JWTTrustVerifier) EvaluateIssuerTrust added in v0.5.7

func (v *JWTTrustVerifier) EvaluateIssuerTrust(ctx context.Context, vpToken string, scope string) error

EvaluateIssuerTrust verifies the credential signature and evaluates the trust of the credential issuer. It splits the SD-JWT VP token, verifies the issuer JWT signature using key material from the header (x5c, jwk, DID resolution, or kid/JWKS resolution), and evaluates trust via the configured PDP.

func (*JWTTrustVerifier) VerifyJWTSignature added in v0.7.0

func (v *JWTTrustVerifier) VerifyJWTSignature(ctx context.Context, tokenString, scope string) (*jwt.Token, *JWTKeyMaterial, error)

VerifyJWTSignature parses tokenString and verifies its signature using key material resolved from its own header/claims (x5c, embedded jwk, DID-based issuer, or kid/JWKS lookup - see extractJWTKeyMaterial), WITHOUT evaluating PDP trust. Exposed separately from EvaluateIssuerTrust so callers that need a different PDP role or request shape than EvaluateIssuerTrust's hardcoded RoleCredentialIssuer/SD-JWT-VP splitting (e.g. WalletAttestationEvaluator, which verifies a WIA - a plain JWT, not an SD-JWT VP - and then evaluates trust with RoleWalletProvider) can reuse the same verification instead of hand-rolling a parallel, easy-to-get-wrong implementation.

issuerID/credentialType for key resolution and logging come from the token's own iss/vct claims (ExtractJWTClaimsInfo) - correct for any JWT that uses the iss claim conventionally, WIAs included; vct simply stays empty for non-SD-JWT-VC tokens like a WIA.

type JWTTrustVerifierConfig added in v0.5.7

type JWTTrustVerifierConfig struct {
	TrustEvaluator             TrustEvaluator
	JWKSResolver               *JWKSKeyResolver
	AllowedSignatureAlgorithms []string
	ParseX5C                   ParseX5CFunc
	ParseJWK                   ParseJWKFunc
	Log                        Logger
}

JWTTrustVerifierConfig configures a JWTTrustVerifier.

type KeyResolver

type KeyResolver interface {
	// ResolveKey retrieves the public key for the given verification method.
	ResolveKey(ctx context.Context, verificationMethod string) (crypto.PublicKey, error)
}

KeyResolver resolves public keys from identifiers. This is used when the key needs to be fetched (DID-based credentials).

type KeyType

type KeyType = trustapi.KeyType

KeyType indicates the format of the public key being validated.

type LocalTrustConfig deprecated

type LocalTrustConfig struct {
	// TrustedRoots are the trusted root certificates.
	TrustedRoots []*x509.Certificate

	// AllowedRoles limits which roles are accepted. Nil means all roles.
	AllowedRoles []string

	// Clock is used for time-based validation. If nil, time.Now() is used.
	Clock func() time.Time
}

LocalTrustConfig configures a LocalTrustEvaluator.

Deprecated: See LocalTrustEvaluator deprecation notice.

type LocalTrustEvaluator deprecated

type LocalTrustEvaluator struct {
	// contains filtered or unexported fields
}

LocalTrustEvaluator implements TrustEvaluator using local trust anchors.

Deprecated: LocalTrustEvaluator performs trust evaluation locally without consulting an AuthZEN PDP. For harmonized trust management across applications, use NewTrustEvaluatorFromConfig instead, which returns AllowAllEvaluator when no PDP URL is configured (returning trusted=true for all requests).

LocalTrustEvaluator is retained for backward compatibility and testing purposes.

func NewLocalTrustEvaluator

func NewLocalTrustEvaluator(config LocalTrustConfig) *LocalTrustEvaluator

NewLocalTrustEvaluator creates a new local trust evaluator.

func (*LocalTrustEvaluator) AddTrustedRoot

func (e *LocalTrustEvaluator) AddTrustedRoot(cert *x509.Certificate)

AddTrustedRoot adds a trusted root certificate.

func (*LocalTrustEvaluator) Evaluate

Evaluate implements TrustEvaluator.

func (*LocalTrustEvaluator) GetTrustedRoots

func (e *LocalTrustEvaluator) GetTrustedRoots() []*x509.Certificate

GetTrustedRoots returns all trusted root certificates.

func (*LocalTrustEvaluator) SupportsKeyType

func (e *LocalTrustEvaluator) SupportsKeyType(kt KeyType) bool

SupportsKeyType implements TrustEvaluator.

type Logger added in v0.5.7

type Logger interface {
	Debug(msg string, args ...any)
	Warn(msg string, args ...any)
	Info(msg string, args ...any)
}

Logger is a minimal logging interface for the JWT trust verifier.

type ParseJWKFunc added in v0.5.7

type ParseJWKFunc func(jwkData any) (crypto.PublicKey, error)

ParseJWKFunc parses a JWK map into a public key.

type ParseX5CFunc added in v0.5.7

type ParseX5CFunc func(x5cRaw any) ([]*x509.Certificate, error)

ParseX5CFunc parses an x5c header value into a certificate chain.

type Role

type Role = trustapi.Role

Role represents the expected role of the key holder.

type TrustCache

type TrustCache struct {
	// contains filtered or unexported fields
}

TrustCache caches trust evaluation results to avoid repeated remote calls. It uses a composite key based on SubjectID, KeyType, Role, and key fingerprint.

func NewTrustCache

func NewTrustCache(config TrustCacheConfig) *TrustCache

NewTrustCache creates and starts a new trust decision cache.

func (*TrustCache) Clear

func (c *TrustCache) Clear()

Clear removes all entries from the cache.

func (*TrustCache) Get

Get retrieves a cached trust decision for the given request. Returns nil if not found or expired.

func (*TrustCache) Invalidate

func (c *TrustCache) Invalidate(req *EvaluationRequest)

Invalidate removes a specific entry from the cache.

func (*TrustCache) InvalidateSubject

func (c *TrustCache) InvalidateSubject(subjectID string)

InvalidateSubject removes all entries for a subject from the cache. This is useful when a subject's trust status is known to have changed.

func (*TrustCache) Len

func (c *TrustCache) Len() int

Len returns the number of items currently in the cache.

func (*TrustCache) Set

func (c *TrustCache) Set(req *EvaluationRequest, decision *TrustDecision)

Set stores a trust decision in the cache.

func (*TrustCache) SetWithTTL

func (c *TrustCache) SetWithTTL(req *EvaluationRequest, decision *TrustDecision, ttl time.Duration)

SetWithTTL stores a trust decision with a custom TTL.

func (*TrustCache) Stop

func (c *TrustCache) Stop()

Stop stops the cache's automatic expiration goroutine.

type TrustCacheConfig

type TrustCacheConfig struct {
	// TTL is the time-to-live for cached decisions. Default: 5 minutes.
	TTL time.Duration

	// MaxCapacity is the maximum number of items in the cache.
	// If 0, no capacity limit is applied (items only expire by TTL).
	MaxCapacity uint64
}

TrustCacheConfig contains configuration for the trust cache.

type TrustDecision

type TrustDecision = trustapi.TrustDecision

TrustDecision represents the result of a trust evaluation.

type TrustEvaluator

type TrustEvaluator interface {
	// Evaluate checks if the given key is trusted for the specified subject and role.
	// This is used when the key is already known (SD-JWT x5c, mDOC certificates).
	Evaluate(ctx context.Context, req *EvaluationRequest) (*TrustDecision, error)

	// SupportsKeyType returns true if this evaluator can handle the given key type.
	SupportsKeyType(kt KeyType) bool
}

TrustEvaluator evaluates whether a name-to-key binding is trusted. This extends trustapi.TrustEvaluator to work with our EvaluationRequest.

func NewTrustEvaluatorFromConfig

func NewTrustEvaluatorFromConfig(pdpURL string) TrustEvaluator

NewTrustEvaluatorFromConfig creates the appropriate TrustEvaluator based on configuration. If pdpURL is empty, returns an AllowAllEvaluator (trusted=true for all requests). If pdpURL is set, returns a GoTrustEvaluator that queries the PDP for trust decisions.

This provides harmonized trust management across applications:

  • Empty PDP URL: "allow all" mode - resolved keys are always considered trusted
  • Non-empty PDP URL: "default deny" mode - trust decisions require PDP approval
Example
package main

import (
	"fmt"

	"github.com/SUNET/vc/pkg/trust"
)

func main() {
	// Empty PDP URL returns an AllowAll evaluator
	evaluator := trust.NewTrustEvaluatorFromConfig("")
	fmt.Printf("%T\n", evaluator)
}
Output:
*trust.AllowAllEvaluator

type TrustOptions

type TrustOptions = trustapi.TrustOptions

TrustOptions contains additional options for trust evaluation.

type WalletAttestationEvaluator added in v0.7.0

type WalletAttestationEvaluator struct {
	TrustEvaluator TrustEvaluator
	// Verifier resolves and verifies the WIA's own signing key material -
	// x5c, an embedded jwk header, a DID-based issuer, or kid/JWKS lookup
	// (JWTTrustVerifier.extractJWTKeyMaterial's existing resolution
	// strategies, reused as-is here rather than reimplemented).
	Verifier *JWTTrustVerifier
	// Mode restricts which WIA trust model is accepted: WIAModeETSI
	// (x5c-based, matching EC TS03 v1.5.2 / ETSI TS 119 472-3 — identity
	// verified against the Trusted List for Wallet Providers), WIAModeIETF
	// (iss/JWKS-based, the plain IETF draft format with no ARF/ETSI
	// counterpart), or "" to accept either (the pre-Mode default: whichever
	// format the WIA itself uses). Enforced in Evaluate before any signature
	// verification is attempted, so a mismatched WIA is rejected cheaply and
	// never reaches the PDP with the "wrong" trust model's data.
	Mode string
}

WalletAttestationEvaluator evaluates wallet attestation JWTs by verifying the WIA's own signature locally and then delegating the trust DECISION (only) to the go-trust AuthZEN PDP - the PDP evaluates whether an already-verified key belongs to a trusted wallet provider, it does not verify signatures itself. Signature verification is the caller's responsibility, same as every other trust check in this package (JWTTrustVerifier.EvaluateIssuerTrust).

Supports two WIA formats:

  • IETF draft-ietf-oauth-attestation-based-client-auth: iss claim present
  • EC TS03 §2.2.1 (EUDI): no iss, identity from x5c certificate chain in header

Mode optionally pins which of the two a deployment accepts (see the Mode field); when unset, both remain accepted as determined by the WIA itself.

PKCE (mandatory for public clients) is the sole code-binding mechanism.

func NewWalletAttestationEvaluator added in v0.7.0

func NewWalletAttestationEvaluator(evaluator TrustEvaluator, verifier *JWTTrustVerifier, mode string) *WalletAttestationEvaluator

NewWalletAttestationEvaluator creates a new evaluator. mode is one of WIAModeETSI, WIAModeIETF, or "" to accept either format — see WalletAttestationEvaluator.Mode.

func (*WalletAttestationEvaluator) Evaluate added in v0.7.0

Evaluate verifies a wallet attestation JWT's signature, then evaluates wallet-provider trust via the PDP.

func (*WalletAttestationEvaluator) EvaluateWithPoP added in v0.7.0

func (e *WalletAttestationEvaluator) EvaluateWithPoP(ctx context.Context, attestation, popJWT, expectedAudience string) (*WalletAttestationResult, error)

EvaluateWithPoP validates a wallet attestation (WIA) and its PoP JWT per draft-ietf-oauth-attestation-based-client-auth-04 §3.1 and §5.2.

When popJWT is non-empty, it validates:

  • typ header = "oauth-client-attestation-pop+jwt"
  • signature matches the cnf.jwk from the WIA
  • aud claim contains the expectedAudience (this AS's issuer URL)
  • exp is not in the past, iat is present

When popJWT is empty (legacy form-body mode), only the WIA is validated.

type WalletAttestationPolicyEngine added in v0.7.0

type WalletAttestationPolicyEngine struct {
	// contains filtered or unexported fields
}

WalletAttestationPolicyEngine wraps a SPOCP engine for wallet attestation tier authorization. When nil, all trusted wallets are authorized (default open).

func BuildWalletAttestationPolicyEngine added in v0.7.0

func BuildWalletAttestationPolicyEngine(rules []string, rulesFile string) (*WalletAttestationPolicyEngine, error)

BuildWalletAttestationPolicyEngine creates a SPOCP engine from rules configuration. Returns nil when no rules are configured (default open — all trusted wallets authorized).

func (*WalletAttestationPolicyEngine) Authorize added in v0.7.0

func (e *WalletAttestationPolicyEngine) Authorize(attestationSource, scope, issuer string) bool

Authorize checks if the given attestation tier is authorized for the requested scope. Returns true if no policy engine is configured (default open).

func (*WalletAttestationPolicyEngine) RuleCount added in v0.7.0

func (e *WalletAttestationPolicyEngine) RuleCount() int

RuleCount returns the number of loaded rules, or 0 if engine is nil.

type WalletAttestationResult added in v0.7.0

type WalletAttestationResult struct {
	// Trusted indicates whether the PDP approved the wallet attestation.
	Trusted bool
	// Issuer is the wallet provider identifier.
	// Derived from `iss` claim (IETF draft) or x5c leaf certificate SAN/CN (TS03).
	Issuer string
	// Subject is the wallet instance identifier (sub claim = JWK thumbprint).
	Subject string
	// AttestationSource indicates the attestation tier (e.g., "backend_attested",
	// "ios_app_attest", "android_play_integrity"). Empty if not present in the WIA.
	AttestationSource string
	// Reason is the PDP's trust decision reason.
	Reason string
	// TrustFramework identifies which mechanism validated the attestation.
	TrustFramework string
}

WalletAttestationResult holds the outcome of a wallet attestation trust evaluation.

type X5CCertChain

type X5CCertChain = trustapi.X5CCertChain

X5CCertChain is a helper type for x5c certificate chains.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL