Documentation
¶
Index ¶
- Constants
- Variables
- func CreateMockKeycloakServer(config MockKeycloakServerConfig) *httptest.Server
- func FilterToAllowedRoles(roles []string) (allowed []string, err error)
- func GenerateExpiredTestJWT(claims jwt.MapClaims) (string, error)
- func GenerateFutureTestJWT(claims jwt.MapClaims) (string, error)
- func GenerateJWKSFromRSAKey(publicKey *rsa.PublicKey, keyID string) string
- func GenerateJWTWithWrongSignature(claims jwt.MapClaims) (string, error)
- func GenerateMalformedJWT() string
- func GenerateTestJWT(claims jwt.Claims, key *rsa.PrivateKey) (string, error)
- func GetConsistentTestRSAKey() *rsa.PrivateKey
- func GetIsServiceAccountFromContext(c echo.Context) bool
- func GetRolesFromAttribute(claims jwt.MapClaims, attribute string) ([]string, error)
- func IsValidRole(role string) bool
- func SetIsServiceAccountInContext(c echo.Context, isServiceAccount bool)
- type AuthContextKey
- type ClaimMapping
- type JWTOriginConfig
- func (jc *JWTOriginConfig) AddConfig(name, issuer, url string, origin string, serviceAccount bool, ...)
- func (jc *JWTOriginConfig) AddConfigWithProcessor(name, issuer, url string, origin string, serviceAccount bool, ...)
- func (jc *JWTOriginConfig) AddJwksConfig(cfg *JwksConfig)
- func (jc *JWTOriginConfig) GetAllConfigs() map[string]*JwksConfig
- func (jc *JWTOriginConfig) GetConfig(issuer string) *JwksConfig
- func (jc *JWTOriginConfig) GetConfigsByOrigin(origin string) map[string]*JwksConfig
- func (jc *JWTOriginConfig) GetFirstConfigByOrigin(origin string) *JwksConfig
- func (jc *JWTOriginConfig) GetKasProcessor() TokenProcessor
- func (jc *JWTOriginConfig) GetKeycloakProcessor() TokenProcessor
- func (jc *JWTOriginConfig) GetProcessorByIssuer(issuer string) TokenProcessor
- func (jc *JWTOriginConfig) GetProcessorByOrigin(origin string) TokenProcessor
- func (jc *JWTOriginConfig) GetSsaProcessor() TokenProcessor
- func (jc *JWTOriginConfig) IsServiceAccount(issuer string) bool
- func (jc *JWTOriginConfig) RemoveConfig(issuer string)
- func (jc *JWTOriginConfig) SetProcessorForOrigin(origin string, processor TokenProcessor)
- func (jc *JWTOriginConfig) SetProcessors(keycloakProcessor, ssaProcessor, kasProcessor TokenProcessor)
- func (jc *JWTOriginConfig) UpdateAllJWKS() error
- type JwksConfig
- func (jcfg *JwksConfig) GetClaimMappings() []ClaimMapping
- func (jcfg *JwksConfig) GetJWKS() *core.JWKS
- func (jcfg *JwksConfig) GetKeyByID(id string) (interface{}, error)
- func (jcfg *JwksConfig) GetOrgDataFromClaim(claims jwt.MapClaims, reqOrgFromRoute string) (cdbm.OrgData, bool, error)
- func (jcfg *JwksConfig) GetSubjectPrefix() string
- func (jcfg *JwksConfig) HasClaimMappings() bool
- func (jcfg *JwksConfig) KeyCount() int
- func (jcfg *JwksConfig) MatchesIssuer(issuer string) bool
- func (jcfg *JwksConfig) UpdateJWKS() error
- func (jcfg *JwksConfig) ValidateAudience(claims jwt.MapClaims) error
- func (jcfg *JwksConfig) ValidateScopes(claims jwt.MapClaims) error
- func (jcfg *JwksConfig) ValidateToken(authHeader string, claims jwt.Claims) (*jwt.Token, error)
- type KeycloakConfig
- type MockKeycloakServerConfig
- type TestMockResponses
- type TokenProcessor
Constants ¶
const ( TokenOriginKasLegacy = "kas-legacy" // Legacy KAS tokens TokenOriginKasSsa = "kas-ssa" // KAS SSA tokens TokenOriginKeycloak = "keycloak" // Keycloak tokens TokenOriginCustom = "custom" // Custom/third-party tokens (default if not specified) )
TokenOrigin constants define the source of JWT tokens These string values correspond to what's configured in the issuer configmap
Variables ¶
var ( // ServiceAccountRoles are the default roles assigned to service accounts ServiceAccountRoles = []string{"FORGE_PROVIDER_ADMIN", "FORGE_TENANT_ADMIN"} // AllowedRoles is the set of valid roles that can be assigned to users. // Both static roles in config and dynamic roles from claims must be from this set. AllowedRoles = map[string]bool{ "FORGE_TENANT_ADMIN": true, "FORGE_PROVIDER_ADMIN": true, } )
var AllowedOrigins = []string{TokenOriginKasLegacy, TokenOriginKasSsa, TokenOriginKeycloak, TokenOriginCustom}
AllowedOrigins is the list of valid token origins for the service
var ( // DefaultMockResponses provides standard mock responses for tests (backward compatibility) DefaultMockResponses = GetDefaultMockResponses() )
Functions ¶
func CreateMockKeycloakServer ¶
func CreateMockKeycloakServer(config MockKeycloakServerConfig) *httptest.Server
CreateMockKeycloakServer creates a consolidated mock Keycloak server
func FilterToAllowedRoles ¶
FilterToAllowedRoles filters a list of roles to only include allowed roles. Returns core.ErrInvalidRole if no valid roles remain after filtering.
func GenerateExpiredTestJWT ¶
GenerateExpiredTestJWT generates an expired JWT for testing
func GenerateFutureTestJWT ¶
GenerateFutureTestJWT generates a JWT that's not yet valid
func GenerateJWKSFromRSAKey ¶
GenerateJWKSFromRSAKey creates a JWKS JSON response from an RSA public key
func GenerateJWTWithWrongSignature ¶
GenerateJWTWithWrongSignature generates a JWT with wrong signature
func GenerateMalformedJWT ¶
func GenerateMalformedJWT() string
GenerateMalformedJWT generates a malformed JWT for testing
func GenerateTestJWT ¶
GenerateTestJWT creates a JWT token with the given claims and key
func GetConsistentTestRSAKey ¶
func GetConsistentTestRSAKey() *rsa.PrivateKey
GetConsistentTestRSAKey returns a consistent RSA key for testing This ensures JWT tokens and JWKS responses use the same key
func GetIsServiceAccountFromContext ¶
GetIsServiceAccountFromContext returns whether the request is from a service account
func GetRolesFromAttribute ¶
GetRolesFromAttribute extracts roles from a nested claim attribute and filters to allowed roles. Returns nil if the attribute doesn't exist or contains no valid roles.
func IsValidRole ¶
IsValidRole checks if a single role is in the AllowedRoles set.
func SetIsServiceAccountInContext ¶
SetIsServiceAccountInContext stores whether the request is from a service account
Types ¶
type AuthContextKey ¶
type AuthContextKey string
AuthContextKey is a custom type for context keys to avoid collisions
type ClaimMapping ¶
type ClaimMapping struct {
// OrgAttribute: JWT claim path to extract org name (e.g., "org", "data.org"). Makes this a dynamic mapping.
OrgAttribute string `mapstructure:"orgAttribute"`
// OrgDisplayAttribute: JWT claim path for org display name (dynamic mappings only)
OrgDisplayAttribute string `mapstructure:"orgDisplayAttribute"`
// OrgName: fixed organization name (static mapping). Used when OrgAttribute is empty.
OrgName string `mapstructure:"orgName"`
// OrgDisplayName: display name for static org mappings
OrgDisplayName string `mapstructure:"orgDisplayName"`
// RolesAttribute: JWT claim path to extract roles (e.g., "roles", "data.roles"). Takes precedence over Roles.
RolesAttribute string `mapstructure:"rolesAttribute"`
// Roles: static role list. Used when RolesAttribute is empty and IsServiceAccount is false.
Roles []string `mapstructure:"roles"`
// IsServiceAccount: if true, assigns admin roles (FORGE_PROVIDER_ADMIN, FORGE_TENANT_ADMIN). Ignores RolesAttribute/Roles.
IsServiceAccount bool `mapstructure:"isServiceAccount"`
}
ClaimMapping defines how to map JWT claims to organization data. Dynamic mode: set OrgAttribute to extract org from token claims. Static mode: set OrgName for a fixed organization.
func (*ClaimMapping) GetOrgNameAndDisplayName ¶
func (cm *ClaimMapping) GetOrgNameAndDisplayName(claims jwt.MapClaims) (orgName string, displayName string)
GetOrgNameAndDisplayName extracts org and display name from claims (dynamic mappings only).
func (*ClaimMapping) GetRoles ¶
func (cm *ClaimMapping) GetRoles(claims jwt.MapClaims) ([]string, error)
GetRoles returns roles based on mapping config: service account roles, dynamic extraction, or static roles.
func (*ClaimMapping) IsOrgDynamic ¶
func (cm *ClaimMapping) IsOrgDynamic() bool
IsOrgDynamic returns true if this is a valid dynamic org mapping. Dynamic mappings require all three attributes:
- OrgAttribute: JWT claim path to extract org name (e.g., "org", "data.org")
- OrgDisplayAttribute: JWT claim path to extract org display name (e.g., "org_display", "data.orgDisplayName")
- RolesAttribute: JWT claim path to extract roles (e.g., "roles", "data.roles")
Service accounts are not allowed with dynamic orgs.
func (*ClaimMapping) IsOrgStatic ¶
func (cm *ClaimMapping) IsOrgStatic() bool
IsOrgStatic returns true if using a fixed org name (OrgName set).
type JWTOriginConfig ¶
type JWTOriginConfig struct {
sync.RWMutex // protects concurrent access to configs and handlers maps
// contains filtered or unexported fields
}
JWTOriginConfig holds configuration for JWT origins with multiple JWKS configs and handlers
func NewJWTOriginConfig ¶
func NewJWTOriginConfig() *JWTOriginConfig
NewJWTOriginConfig initializes and returns a configuration object with empty maps
func (*JWTOriginConfig) AddConfig ¶
func (jc *JWTOriginConfig) AddConfig(name, issuer, url string, origin string, serviceAccount bool, audiences []string, scopes []string)
AddConfig adds a new JWKS config with the specified name, issuer, URL, origin, and serviceAccount flag
func (*JWTOriginConfig) AddConfigWithProcessor ¶
func (jc *JWTOriginConfig) AddConfigWithProcessor(name, issuer, url string, origin string, serviceAccount bool, audiences []string, scopes []string, processor TokenProcessor)
AddConfigWithProcessor adds a new JWKS config and processor for the specified origin
func (*JWTOriginConfig) AddJwksConfig ¶
func (jc *JWTOriginConfig) AddJwksConfig(cfg *JwksConfig)
AddJwksConfig adds a pre-configured JwksConfig for an issuer This is the preferred method for adding configurations
func (*JWTOriginConfig) GetAllConfigs ¶
func (jc *JWTOriginConfig) GetAllConfigs() map[string]*JwksConfig
GetAllConfigs returns all JWKS configurations
func (*JWTOriginConfig) GetConfig ¶
func (jc *JWTOriginConfig) GetConfig(issuer string) *JwksConfig
GetConfig returns the JWKS configuration for the specified issuer
func (*JWTOriginConfig) GetConfigsByOrigin ¶
func (jc *JWTOriginConfig) GetConfigsByOrigin(origin string) map[string]*JwksConfig
GetConfigsByOrigin returns all JWKS configurations for the specified origin
func (*JWTOriginConfig) GetFirstConfigByOrigin ¶
func (jc *JWTOriginConfig) GetFirstConfigByOrigin(origin string) *JwksConfig
GetFirstConfigByOrigin returns the first JWKS configuration with the specified origin
func (*JWTOriginConfig) GetKasProcessor ¶
func (jc *JWTOriginConfig) GetKasProcessor() TokenProcessor
GetKasProcessor returns the processor for KAS tokens
func (*JWTOriginConfig) GetKeycloakProcessor ¶
func (jc *JWTOriginConfig) GetKeycloakProcessor() TokenProcessor
GetKeycloakProcessor returns the processor for Keycloak tokens
func (*JWTOriginConfig) GetProcessorByIssuer ¶
func (jc *JWTOriginConfig) GetProcessorByIssuer(issuer string) TokenProcessor
GetProcessorByIssuer finds a processor that exactly matches the given issuer
func (*JWTOriginConfig) GetProcessorByOrigin ¶
func (jc *JWTOriginConfig) GetProcessorByOrigin(origin string) TokenProcessor
GetProcessorByOrigin returns the processor for the specified origin
func (*JWTOriginConfig) GetSsaProcessor ¶
func (jc *JWTOriginConfig) GetSsaProcessor() TokenProcessor
GetSsaProcessor returns the processor for SSA tokens
func (*JWTOriginConfig) IsServiceAccount ¶
func (jc *JWTOriginConfig) IsServiceAccount(issuer string) bool
IsServiceAccount checks if the given issuer supports service account tokens
func (*JWTOriginConfig) RemoveConfig ¶
func (jc *JWTOriginConfig) RemoveConfig(issuer string)
RemoveConfig removes the JWKS configuration for the specified issuer
func (*JWTOriginConfig) SetProcessorForOrigin ¶
func (jc *JWTOriginConfig) SetProcessorForOrigin(origin string, processor TokenProcessor)
SetProcessorForOrigin sets a processor for the specified token origin
func (*JWTOriginConfig) SetProcessors ¶
func (jc *JWTOriginConfig) SetProcessors(keycloakProcessor, ssaProcessor, kasProcessor TokenProcessor)
SetProcessors sets all processors at once for easier initialization
func (*JWTOriginConfig) UpdateAllJWKS ¶
func (jc *JWTOriginConfig) UpdateAllJWKS() error
UpdateAllJWKS updates the JWKs for all configurations in the map Updates are performed in parallel for better performance with multiple issuers. Continues on individual failures - only returns error if ALL updates fail.
type JwksConfig ¶
type JwksConfig struct {
Name string
IsUpdating uint32 // atomic flag for concurrent JWKS updates
sync.RWMutex // protects JWKS access
URL string // JWKS endpoint URL
Issuer string // expected "iss" claim value
Origin string // token origin type (e.g., "kas-legacy", "kas-ssa", "keycloak", "custom")
LastUpdated time.Time // last JWKS update timestamp
JWKSTimeout time.Duration // fetch timeout (default: 5s)
Audiences []string // allowed audience values (token must have at least one)
Scopes []string // required scopes (token must have ALL)
ClaimMappings []ClaimMapping // org/role mapping configuration
// ServiceAccount enables client credentials flow (Keycloak only).
// For custom issuers, use ClaimMapping.IsServiceAccount instead.
ServiceAccount bool
// ReservedOrgNames prevents dynamic org mappings from claiming statically-configured org names.
// Populated by carbide-rest-api during initialization.
ReservedOrgNames map[string]bool
// contains filtered or unexported fields
}
JwksConfig holds configuration for a JWKS endpoint and token validation.
func NewJwksConfig ¶
func NewJwksConfig(name string, url string, issuer string, origin string, serviceAccount bool, audiences []string, scopes []string) *JwksConfig
NewJwksConfig is a function that initializes and returns a configuration object for managing JWKS
func (*JwksConfig) GetClaimMappings ¶
func (jcfg *JwksConfig) GetClaimMappings() []ClaimMapping
GetClaimMappings returns the claim mappings.
func (*JwksConfig) GetJWKS ¶
func (jcfg *JwksConfig) GetJWKS() *core.JWKS
GetJWKS returns the enhanced JWKS with go-jose capabilities
func (*JwksConfig) GetKeyByID ¶
func (jcfg *JwksConfig) GetKeyByID(id string) (interface{}, error)
GetKeyByID is a method that returns a JWK secret by ID with enhanced validation
func (*JwksConfig) GetOrgDataFromClaim ¶
func (jcfg *JwksConfig) GetOrgDataFromClaim(claims jwt.MapClaims, reqOrgFromRoute string) (cdbm.OrgData, bool, error)
GetOrgDataFromClaim extracts org data for the requested org from claim mappings. This method validates org access and returns errors if:
- core.ErrReservedOrgName: dynamic org claims a statically-configured org name
- core.ErrInvalidConfiguration: no claim mapping configured for the requested org
- core.ErrNoClaimRoles: no roles found for the requested org
Returns orgData, isServiceAccount, and any error.
func (*JwksConfig) GetSubjectPrefix ¶
func (jcfg *JwksConfig) GetSubjectPrefix() string
GetSubjectPrefix returns the issuer-derived prefix for namespacing subjects.
func (*JwksConfig) HasClaimMappings ¶
func (jcfg *JwksConfig) HasClaimMappings() bool
HasClaimMappings returns true if claim mappings are configured.
func (*JwksConfig) KeyCount ¶
func (jcfg *JwksConfig) KeyCount() int
KeyCount returns the number of keys in the JWKS
func (*JwksConfig) MatchesIssuer ¶
func (jcfg *JwksConfig) MatchesIssuer(issuer string) bool
MatchesIssuer checks if the given issuer exactly matches the configured issuer
func (*JwksConfig) UpdateJWKS ¶
func (jcfg *JwksConfig) UpdateJWKS() error
UpdateJWKS fetches and validates JWKS from the configured URL. Throttled to minUpdateInterval.
func (*JwksConfig) ValidateAudience ¶
func (jcfg *JwksConfig) ValidateAudience(claims jwt.MapClaims) error
ValidateAudience checks token has at least one configured audience. Returns nil if none configured.
func (*JwksConfig) ValidateScopes ¶
func (jcfg *JwksConfig) ValidateScopes(claims jwt.MapClaims) error
ValidateScopes checks token has ALL configured scopes. Returns nil if none configured.
func (*JwksConfig) ValidateToken ¶
ValidateToken parses token from Authorization header with caller-provided claims and enhanced validation
type KeycloakConfig ¶
type KeycloakConfig struct {
BaseURL string
ExternalBaseURL string
ClientID string
ClientSecret string
Realm string
Issuer string
ServiceAccountEnabled bool
// contains filtered or unexported fields
}
KeycloakConfig represents the configuration for Keycloak authentication
func NewKeycloakConfig ¶
func NewKeycloakConfig(baseURL, externalBaseURL, clientID, clientSecret, realm string, serviceAccountEnabled bool) *KeycloakConfig
NewKeycloakConfig creates a new KeycloakConfig instance and attempts to fetch JWKS
func (*KeycloakConfig) GetJwksConfig ¶
func (kc *KeycloakConfig) GetJwksConfig() (*JwksConfig, error)
GetJwksConfig gets the JWKS configuration, retrying fetch if needed
type MockKeycloakServerConfig ¶
type MockKeycloakServerConfig struct {
Responses TestMockResponses
ValidCredentials map[string]string // username -> password
ValidTokens map[string]bool // token -> valid
ValidCodes map[string]bool // code -> valid
}
MockKeycloakServerConfig configures the mock server behavior
func DefaultMockServerConfig ¶
func DefaultMockServerConfig() MockKeycloakServerConfig
DefaultMockServerConfig provides a standard configuration
type TestMockResponses ¶
type TestMockResponses struct {
AdminLogin string
IDPs string
Token string
UserInfo string
JWKS string
}
TestMockResponses contains all mock response data
func GetDefaultMockResponses ¶
func GetDefaultMockResponses() TestMockResponses
GetDefaultMockResponses provides standard mock responses for tests This generates JWKS dynamically based on the consistent test RSA key