Documentation
¶
Overview ¶
Package caep implements the OpenID Continuous Access Evaluation Profile (CAEP) 1.0 event vocabulary: the CAEP event-type URIs and their typed event payloads, registered into the go-secevent event registry so a Security Event Token's events decode to typed Go values.
CAEP events ride inside an RFC 8417 Security Event Token (the go-secevent envelope). This package owns only the CAEP event payloads — one typed struct per event type, each carried under its event-type URI in a SET's events map. Importing the package for its side effects registers every event type's decoder with go-secevent:
import (
secevent "github.com/hstern/go-secevent"
_ "github.com/hstern/go-caep" // registers the CAEP event decoders
)
set, _ := secevent.Parse(payload)
if ev, ok, _ := set.Events.Typed(caep.EventSessionRevoked); ok {
revoked := ev.(caep.SessionRevoked)
_ = revoked.InitiatingEntity
}
Spec: https://openid.net/specs/openid-caep-1_0.html
Example (Decode) ¶
Example_decode shows the receiver side: parse an already-verified SET claims set and recover the typed CAEP event. Importing go-caep for its side effects (the blank import in this package's other files) registers the decoders.
package main
import (
"fmt"
caep "github.com/hstern/go-caep"
secevent "github.com/hstern/go-secevent"
)
func main() {
payload := []byte(`{
"iss": "https://idp.example.com/",
"iat": 1615305600,
"jti": "set-0001",
"aud": "https://rp.example.com/",
"events": {
"https://schemas.openid.net/secevent/caep/event-type/credential-change": {
"credential_type": "fido2-roaming",
"change_type": "create",
"friendly_name": "YubiKey 5C"
}
}
}`)
set, err := secevent.Parse(payload)
if err != nil {
fmt.Println("parse:", err)
return
}
ev, ok, err := set.Events.Typed(caep.EventCredentialChange)
if err != nil || !ok {
fmt.Println("not a recognized credential-change event")
return
}
cc := ev.(caep.CredentialChange)
fmt.Printf("%s %s (%s)\n", cc.ChangeType, cc.CredentialType, cc.FriendlyName)
}
Output: create fido2-roaming (YubiKey 5C)
Example (Encode) ¶
Example_encode shows the transmitter side: build a typed CAEP event and place it into a SET's events map under its event-type URI with Put.
package main
import (
"fmt"
caep "github.com/hstern/go-caep"
secevent "github.com/hstern/go-secevent"
)
func main() {
e := caep.SessionRevoked{Base: caep.Base{
InitiatingEntity: caep.InitiatingEntityPolicy,
ReasonAdmin: map[string]string{"en": "policy revoked the session"},
}}
events := secevent.Events{}
if err := caep.Put(events, e); err != nil {
fmt.Println("put:", err)
return
}
fmt.Printf("%s\n", events[caep.EventSessionRevoked])
}
Output: {"initiating_entity":"policy","reason_admin":{"en":"policy revoked the session"}}
Index ¶
- Constants
- Variables
- func Put(events secevent.Events, e secevent.Event) error
- func Validate(e secevent.Event) error
- type AssuranceLevelChange
- type AssuranceNamespace
- type Base
- type ChangeDirection
- type ComplianceStatus
- type CredentialChange
- type CredentialChangeType
- type CredentialType
- type DeviceComplianceChange
- type InitiatingEntity
- type RiskLevel
- type RiskLevelChange
- type RiskPrincipal
- type SessionEstablished
- type SessionPresented
- type SessionRevoked
- type TokenClaimsChange
Examples ¶
Constants ¶
const ( // EventSessionRevoked identifies a Session Revoked event (CAEP 1.0 §3.2). EventSessionRevoked = eventTypeBase + "session-revoked" // EventTokenClaimsChange identifies a Token Claims Change event (§3.3). EventTokenClaimsChange = eventTypeBase + "token-claims-change" // EventCredentialChange identifies a Credential Change event (§3.4). EventCredentialChange = eventTypeBase + "credential-change" // EventAssuranceLevelChange identifies an Assurance Level Change event (§3.5). EventAssuranceLevelChange = eventTypeBase + "assurance-level-change" // EventSessionEstablished identifies a Session Established event (§3.6). EventSessionEstablished = eventTypeBase + "session-established" // EventSessionPresented identifies a Session Presented event (§3.7). EventSessionPresented = eventTypeBase + "session-presented" // EventDeviceComplianceChange identifies a Device Compliance Change event (§3.8). EventDeviceComplianceChange = eventTypeBase + "device-compliance-change" // EventRiskLevelChange identifies a Risk Level Change event (§3.9). EventRiskLevelChange = eventTypeBase + "risk-level-change" )
CAEP 1.0 event-type URIs. Each is the key under which an event of the corresponding type appears in a SET's events claim, and the string its payload's EventTypeURI method returns.
const SpecVersion = "CAEP 1.0"
SpecVersion is the OpenID CAEP specification version this build implements.
Variables ¶
var ( ErrMissingClaims = errors.New(`caep: token-claims-change: missing required field "claims"`) ErrMissingCredentialType = errors.New(`caep: credential-change: missing required field "credential_type"`) ErrMissingChangeType = errors.New(`caep: credential-change: missing required field "change_type"`) ErrMissingNamespace = errors.New(`caep: assurance-level-change: missing required field "namespace"`) ErrMissingCurrentLevel = errors.New(`caep: missing required field "current_level"`) ErrMissingPreviousStatus = errors.New(`caep: device-compliance-change: missing required field "previous_status"`) ErrMissingCurrentStatus = errors.New(`caep: device-compliance-change: missing required field "current_status"`) ErrMissingPrincipal = errors.New(`caep: risk-level-change: missing required field "principal"`) )
Missing-required-field errors returned by Validate. They identify the CAEP required-field MUSTs; match them with errors.Is. When an event is missing more than one required field, Validate joins the corresponding errors.
Functions ¶
func Put ¶
Put marshals e and stores it in events under e.EventTypeURI(), the producer- side counterpart to go-secevent's Events.Typed. The events map must be non-nil. It is a thin convenience over json.Marshal plus a map assignment.
func Validate ¶
Validate reports whether e carries the fields CAEP 1.0 requires for its event type. It returns nil when e is complete, or the missing-field sentinel errors joined together (inspect with errors.Is) when it is not.
Validation is opt-in and wire-shape-bound only: decoding never calls it, and it never asserts anything about an event's meaning. Event types with no required event-specific fields — session-revoked, session-established, session-presented, and any non-CAEP event — always validate.
Types ¶
type AssuranceLevelChange ¶
type AssuranceLevelChange struct {
Base
// Namespace is the assurance framework CurrentLevel is expressed in (required).
Namespace AssuranceNamespace `json:"namespace,omitempty"`
// CurrentLevel is the new assurance level, per Namespace (required).
CurrentLevel string `json:"current_level,omitempty"`
// PreviousLevel is the prior assurance level; omitted means unknown.
PreviousLevel string `json:"previous_level,omitempty"`
// ChangeDirection reports whether the level increased or decreased.
ChangeDirection ChangeDirection `json:"change_direction,omitempty"`
// contains filtered or unexported fields
}
AssuranceLevelChange is an Assurance Level Change event (CAEP 1.0 §3.5), signaling that the subject's identity-assurance level changed. Namespace and CurrentLevel are required (enforced by Validate); an omitted PreviousLevel means the previous level is unknown.
func (AssuranceLevelChange) EventTypeURI ¶
func (AssuranceLevelChange) EventTypeURI() string
EventTypeURI reports the CAEP Assurance Level Change event-type URI.
func (AssuranceLevelChange) MarshalJSON ¶
func (e AssuranceLevelChange) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler, re-emitting any open-extension members.
func (*AssuranceLevelChange) UnmarshalJSON ¶
func (e *AssuranceLevelChange) UnmarshalJSON(b []byte) error
UnmarshalJSON implements json.Unmarshaler, capturing unrecognized members.
type AssuranceNamespace ¶
type AssuranceNamespace string
AssuranceNamespace names the framework an assurance level is expressed in (CAEP 1.0 §3.5). The spec permits custom values, so decoding is lenient.
const ( AssuranceNamespaceRFC8176 AssuranceNamespace = "RFC8176" AssuranceNamespaceRFC6711 AssuranceNamespace = "RFC6711" AssuranceNamespaceISOIEC29115 AssuranceNamespace = "ISO-IEC-29115" AssuranceNamespaceNISTIAL AssuranceNamespace = "NIST-IAL" AssuranceNamespaceNISTAAL AssuranceNamespace = "NIST-AAL" AssuranceNamespaceNISTFAL AssuranceNamespace = "NIST-FAL" )
The AssuranceNamespace values listed by CAEP 1.0 §3.5.
type Base ¶
type Base struct {
// EventTimestamp is when the event occurred, as an RFC 7519 NumericDate
// (seconds since the Unix epoch). Reuses go-secevent's NumericDate so the
// wire form matches the SET envelope's iat/toe claims.
EventTimestamp *secevent.NumericDate `json:"event_timestamp,omitempty"`
// InitiatingEntity is what caused the event (admin, user, policy, system).
InitiatingEntity InitiatingEntity `json:"initiating_entity,omitempty"`
// ReasonAdmin is an administrative message keyed by BCP47 language tag.
ReasonAdmin map[string]string `json:"reason_admin,omitempty"`
// ReasonUser is an end-user message keyed by BCP47 language tag.
ReasonUser map[string]string `json:"reason_user,omitempty"`
}
Base is the common envelope every CAEP event may carry (CAEP 1.0 §3.1). It is embedded by each event type; all four fields are optional. The subject of a CAEP event is the enclosing SET's sub_id, not a field here.
type ChangeDirection ¶
type ChangeDirection string
ChangeDirection reports whether an assurance level rose or fell (§3.5).
const ( ChangeDirectionIncrease ChangeDirection = "increase" ChangeDirectionDecrease ChangeDirection = "decrease" )
The ChangeDirection values defined by CAEP 1.0 §3.5.
type ComplianceStatus ¶
type ComplianceStatus string
ComplianceStatus is a device compliance status (CAEP 1.0 §3.8).
const ( ComplianceStatusCompliant ComplianceStatus = "compliant" ComplianceStatusNotCompliant ComplianceStatus = "not-compliant" )
The ComplianceStatus values defined by CAEP 1.0 §3.8.
type CredentialChange ¶
type CredentialChange struct {
Base
// CredentialType is the kind of credential that changed (required).
CredentialType CredentialType `json:"credential_type,omitempty"`
// ChangeType is the kind of change (required).
ChangeType CredentialChangeType `json:"change_type,omitempty"`
// FriendlyName is a human-readable credential identifier.
FriendlyName string `json:"friendly_name,omitempty"`
// X509Issuer is the issuer of an x509 credential.
X509Issuer string `json:"x509_issuer,omitempty"`
// X509Serial is the serial number of an x509 credential.
X509Serial string `json:"x509_serial,omitempty"`
// FIDO2AAGUID is the FIDO2 Authenticator Attestation GUID.
FIDO2AAGUID string `json:"fido2_aaguid,omitempty"`
// contains filtered or unexported fields
}
CredentialChange is a Credential Change event (CAEP 1.0 §3.4), signaling that a credential was created, revoked, updated, or deleted for the subject. CredentialType and ChangeType are required (enforced by Validate).
func (CredentialChange) EventTypeURI ¶
func (CredentialChange) EventTypeURI() string
EventTypeURI reports the CAEP Credential Change event-type URI.
func (CredentialChange) MarshalJSON ¶
func (e CredentialChange) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler, re-emitting any open-extension members.
func (*CredentialChange) UnmarshalJSON ¶
func (e *CredentialChange) UnmarshalJSON(b []byte) error
UnmarshalJSON implements json.Unmarshaler, capturing unrecognized members.
type CredentialChangeType ¶
type CredentialChangeType string
CredentialChangeType is the kind of change in a CredentialChange (§3.4).
const ( CredentialChangeCreate CredentialChangeType = "create" CredentialChangeRevoke CredentialChangeType = "revoke" CredentialChangeUpdate CredentialChangeType = "update" CredentialChangeDelete CredentialChangeType = "delete" )
The CredentialChangeType values defined by CAEP 1.0 §3.4.
type CredentialType ¶
type CredentialType string
CredentialType identifies the kind of credential in a CredentialChange (CAEP 1.0 §3.4). Decoding is lenient: an unrecognized value is preserved.
const ( CredentialTypePassword CredentialType = "password" CredentialTypePIN CredentialType = "pin" CredentialTypeX509 CredentialType = "x509" CredentialTypeFIDO2Platform CredentialType = "fido2-platform" CredentialTypeFIDO2Roaming CredentialType = "fido2-roaming" CredentialTypeFIDOU2F CredentialType = "fido-u2f" CredentialTypeVerifiableCredential CredentialType = "verifiable-credential" CredentialTypePhoneVoice CredentialType = "phone-voice" CredentialTypePhoneSMS CredentialType = "phone-sms" CredentialTypeApp CredentialType = "app" )
The CredentialType values listed by CAEP 1.0 §3.4.
type DeviceComplianceChange ¶
type DeviceComplianceChange struct {
Base
// PreviousStatus is the device's prior compliance status (required).
PreviousStatus ComplianceStatus `json:"previous_status,omitempty"`
// CurrentStatus is the device's new compliance status (required).
CurrentStatus ComplianceStatus `json:"current_status,omitempty"`
// contains filtered or unexported fields
}
DeviceComplianceChange is a Device Compliance Change event (CAEP 1.0 §3.8), signaling that a device's compliance status changed. Both statuses are required (enforced by Validate).
func (DeviceComplianceChange) EventTypeURI ¶
func (DeviceComplianceChange) EventTypeURI() string
EventTypeURI reports the CAEP Device Compliance Change event-type URI.
func (DeviceComplianceChange) MarshalJSON ¶
func (e DeviceComplianceChange) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler, re-emitting any open-extension members.
func (*DeviceComplianceChange) UnmarshalJSON ¶
func (e *DeviceComplianceChange) UnmarshalJSON(b []byte) error
UnmarshalJSON implements json.Unmarshaler, capturing unrecognized members.
type InitiatingEntity ¶
type InitiatingEntity string
InitiatingEntity identifies what caused a CAEP event (CAEP 1.0 §3.1). The spec defines four values; decoding is lenient, so an unrecognized value is preserved verbatim rather than rejected.
const ( InitiatingEntityAdmin InitiatingEntity = "admin" InitiatingEntityUser InitiatingEntity = "user" InitiatingEntityPolicy InitiatingEntity = "policy" InitiatingEntitySystem InitiatingEntity = "system" )
The InitiatingEntity values defined by CAEP 1.0 §3.1.
type RiskLevelChange ¶
type RiskLevelChange struct {
Base
// Principal is the entity the risk assessment is about (required).
Principal RiskPrincipal `json:"principal,omitempty"`
// CurrentLevel is the present risk rating (required).
CurrentLevel RiskLevel `json:"current_level,omitempty"`
// PreviousLevel is the prior risk rating; omitted means unknown.
PreviousLevel RiskLevel `json:"previous_level,omitempty"`
// RiskReason explains the risk change (recommended).
RiskReason string `json:"risk_reason,omitempty"`
// contains filtered or unexported fields
}
RiskLevelChange is a Risk Level Change event (CAEP 1.0 §3.9), signaling that the assessed risk for a principal changed. Principal and CurrentLevel are required (enforced by Validate); RiskReason is recommended, and an omitted PreviousLevel means the previous level is unknown.
func (RiskLevelChange) EventTypeURI ¶
func (RiskLevelChange) EventTypeURI() string
EventTypeURI reports the CAEP Risk Level Change event-type URI.
func (RiskLevelChange) MarshalJSON ¶
func (e RiskLevelChange) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler, re-emitting any open-extension members.
func (*RiskLevelChange) UnmarshalJSON ¶
func (e *RiskLevelChange) UnmarshalJSON(b []byte) error
UnmarshalJSON implements json.Unmarshaler, capturing unrecognized members.
type RiskPrincipal ¶
type RiskPrincipal string
RiskPrincipal is the kind of entity a RiskLevelChange is about (CAEP 1.0 §3.9). The spec permits other defined entities, so decoding is lenient.
const ( RiskPrincipalUser RiskPrincipal = "USER" RiskPrincipalDevice RiskPrincipal = "DEVICE" RiskPrincipalSession RiskPrincipal = "SESSION" RiskPrincipalTenant RiskPrincipal = "TENANT" RiskPrincipalOrgUnit RiskPrincipal = "ORG_UNIT" RiskPrincipalGroup RiskPrincipal = "GROUP" )
The RiskPrincipal values listed by CAEP 1.0 §3.9.
type SessionEstablished ¶
type SessionEstablished struct {
Base
// FingerprintUA is a fingerprint of the session's user agent (fp_ua).
FingerprintUA string `json:"fp_ua,omitempty"`
// ACR is the Authentication Context Class Reference of the session.
ACR string `json:"acr,omitempty"`
// AMR is the set of Authentication Methods References for the session.
AMR []string `json:"amr,omitempty"`
// ExtID is an external session identifier for correlation.
ExtID string `json:"ext_id,omitempty"`
// contains filtered or unexported fields
}
SessionEstablished is a Session Established event (CAEP 1.0 §3.6), signaling that a new session was created for the subject. All fields are optional.
func (SessionEstablished) EventTypeURI ¶
func (SessionEstablished) EventTypeURI() string
EventTypeURI reports the CAEP Session Established event-type URI.
func (SessionEstablished) MarshalJSON ¶
func (e SessionEstablished) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler, re-emitting any open-extension members.
func (*SessionEstablished) UnmarshalJSON ¶
func (e *SessionEstablished) UnmarshalJSON(b []byte) error
UnmarshalJSON implements json.Unmarshaler, capturing unrecognized members.
type SessionPresented ¶
type SessionPresented struct {
Base
// FingerprintUA is a fingerprint of the session's user agent (fp_ua).
FingerprintUA string `json:"fp_ua,omitempty"`
// ExtID is an external session identifier for correlation.
ExtID string `json:"ext_id,omitempty"`
// contains filtered or unexported fields
}
SessionPresented is a Session Presented event (CAEP 1.0 §3.7), signaling that an existing session was presented to a receiver. All fields are optional.
func (SessionPresented) EventTypeURI ¶
func (SessionPresented) EventTypeURI() string
EventTypeURI reports the CAEP Session Presented event-type URI.
func (SessionPresented) MarshalJSON ¶
func (e SessionPresented) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler, re-emitting any open-extension members.
func (*SessionPresented) UnmarshalJSON ¶
func (e *SessionPresented) UnmarshalJSON(b []byte) error
UnmarshalJSON implements json.Unmarshaler, capturing unrecognized members.
type SessionRevoked ¶
type SessionRevoked struct {
Base
// contains filtered or unexported fields
}
SessionRevoked is a Session Revoked event (CAEP 1.0 §3.2). It has no event-specific fields; it signals that the sessions of the SET's subject are revoked, so tokens issued before EventTimestamp should no longer be honored.
func (SessionRevoked) EventTypeURI ¶
func (SessionRevoked) EventTypeURI() string
EventTypeURI reports the CAEP Session Revoked event-type URI.
func (SessionRevoked) MarshalJSON ¶
func (e SessionRevoked) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler, re-emitting any open-extension members.
func (*SessionRevoked) UnmarshalJSON ¶
func (e *SessionRevoked) UnmarshalJSON(b []byte) error
UnmarshalJSON implements json.Unmarshaler, capturing unrecognized members.
type TokenClaimsChange ¶
type TokenClaimsChange struct {
Base
// Claims maps each changed claim name to its new value (required).
Claims map[string]json.RawMessage `json:"claims,omitempty"`
// contains filtered or unexported fields
}
TokenClaimsChange is a Token Claims Change event (CAEP 1.0 §3.3), signaling that one or more token claims for the subject changed value. Claims is required (enforced by Validate).
Each Claims value is kept as a json.RawMessage: the changed claims are arbitrary JSON, so their bytes round-trip unchanged rather than being coerced into a Go type.
func (TokenClaimsChange) EventTypeURI ¶
func (TokenClaimsChange) EventTypeURI() string
EventTypeURI reports the CAEP Token Claims Change event-type URI.
func (TokenClaimsChange) MarshalJSON ¶
func (e TokenClaimsChange) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler, re-emitting any open-extension members.
func (*TokenClaimsChange) UnmarshalJSON ¶
func (e *TokenClaimsChange) UnmarshalJSON(b []byte) error
UnmarshalJSON implements json.Unmarshaler, capturing unrecognized members.