Move Go reference implementation to refimpl/go-lang/ and add new Python reference implementation in refimpl/python/. Update build.sh with renamed draft and simplified tool paths. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
85 lines
2.6 KiB
Go
85 lines
2.6 KiB
Go
package ect
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// Env names for production configuration. All optional; zero values use defaults.
|
|
const (
|
|
EnvIATMaxAgeMinutes = "ECT_IAT_MAX_AGE_MINUTES" // max age of iat (default 15)
|
|
EnvIATMaxFutureSec = "ECT_IAT_MAX_FUTURE_SEC" // max iat in future / clock skew (default 30)
|
|
EnvDefaultExpiryMin = "ECT_DEFAULT_EXPIRY_MIN" // default token expiry when exp is zero (default 10)
|
|
EnvJTIReplayCacheSize = "ECT_JTI_REPLAY_CACHE_SIZE" // max JTIs to remember for replay check (0 = disabled)
|
|
EnvJTIReplayTTLMin = "ECT_JTI_REPLAY_TTL_MIN" // TTL for JTI cache entries (default 60)
|
|
)
|
|
|
|
// Config holds production-friendly settings loaded from environment.
|
|
type Config struct {
|
|
IATMaxAge time.Duration
|
|
IATMaxFuture time.Duration
|
|
DefaultExpiry time.Duration
|
|
JTIReplaySize int // 0 = no replay cache
|
|
JTIReplayTTL time.Duration
|
|
}
|
|
|
|
// DefaultConfig returns in-process defaults (no env).
|
|
func DefaultConfig() Config {
|
|
return Config{
|
|
IATMaxAge: 15 * time.Minute,
|
|
IATMaxFuture: 30 * time.Second,
|
|
DefaultExpiry: 10 * time.Minute,
|
|
JTIReplayTTL: 60 * time.Minute,
|
|
}
|
|
}
|
|
|
|
// LoadConfigFromEnv returns Config with values from environment where set.
|
|
func LoadConfigFromEnv() Config {
|
|
c := DefaultConfig()
|
|
if v := os.Getenv(EnvIATMaxAgeMinutes); v != "" {
|
|
if n, err := strconv.Atoi(v); err == nil && n > 0 {
|
|
c.IATMaxAge = time.Duration(n) * time.Minute
|
|
}
|
|
}
|
|
if v := os.Getenv(EnvIATMaxFutureSec); v != "" {
|
|
if n, err := strconv.Atoi(v); err == nil && n >= 0 {
|
|
c.IATMaxFuture = time.Duration(n) * time.Second
|
|
}
|
|
}
|
|
if v := os.Getenv(EnvDefaultExpiryMin); v != "" {
|
|
if n, err := strconv.Atoi(v); err == nil && n > 0 {
|
|
c.DefaultExpiry = time.Duration(n) * time.Minute
|
|
}
|
|
}
|
|
if v := os.Getenv(EnvJTIReplayCacheSize); v != "" {
|
|
if n, err := strconv.Atoi(v); err == nil && n >= 0 {
|
|
c.JTIReplaySize = n
|
|
}
|
|
}
|
|
if v := os.Getenv(EnvJTIReplayTTLMin); v != "" {
|
|
if n, err := strconv.Atoi(v); err == nil && n > 0 {
|
|
c.JTIReplayTTL = time.Duration(n) * time.Minute
|
|
}
|
|
}
|
|
return c
|
|
}
|
|
|
|
// CreateOptions returns CreateOptions from this config.
|
|
func (c Config) CreateOptions(keyID string) CreateOptions {
|
|
return CreateOptions{
|
|
KeyID: keyID,
|
|
IATMaxAge: c.IATMaxAge,
|
|
DefaultExpiry: c.DefaultExpiry,
|
|
}
|
|
}
|
|
|
|
// VerifyOptions returns VerifyOptions from this config (VerifierID, ResolveKey, Store must be set by caller).
|
|
func (c Config) VerifyOptions() VerifyOptions {
|
|
opts := DefaultVerifyOptions()
|
|
opts.IATMaxAge = c.IATMaxAge
|
|
opts.IATMaxFuture = c.IATMaxFuture
|
|
opts.DAG = DefaultDAGConfig()
|
|
return opts
|
|
}
|