Skip to content

hstern/go-caep

Repository files navigation

go-caep

a typed event vocabulary for the OpenID Continuous Access Evaluation Profile.

Implements OpenID CAEP 1.0 (Final Specification, 2025-08-29). Spec: https://openid.net/specs/openid-caep-1_0.html

What this library is and is not

It is the CAEP event vocabulary: the CAEP event-type URIs and a typed Go struct for each event payload — session-revoked, token-claims-change, credential-change, assurance-level-change, device-compliance-change, session-established, session-presented, and risk-level-change — together with decoders registered into the go-secevent event registry. Once registered, a parsed Security Event Token's events decode to typed CAEP values, and CAEP events can be built and encoded back into a SET.

CAEP is the "something changed about an ongoing session or credential" half of the Shared Signals Framework. Each event is a JSON object carried under its event-type URI in a SET's events map, sharing a common envelope (event_timestamp, initiating_entity, reason_admin, reason_user) plus event-specific fields. The subject is named by the SET's sub_id.

The following are deliberately out of scope and belong in dedicated libraries:

  • The SET envelope, parsing, validation, and the event registry — these are go-secevent (RFC 8417). This library plugs its event types into that registry.
  • JWS signature verification / signing and transport — a JOSE/Shared Signals transport layer hands go-secevent the decoded claims-set bytes.
  • RISC events (the account-lifecycle half of Shared Signals) — a sibling vocabulary that registers into the same registry.

Install

go get github.com/hstern/go-caep

Quickstart

Receive: parse a SET into typed CAEP events

A blank import registers every CAEP decoder with go-secevent. Parse takes the already-verified, base64url-decoded claims-set bytes; Events.Typed decodes a known event through the registry.

import (
	caep "github.com/hstern/go-caep"
	secevent "github.com/hstern/go-secevent"
	_ "github.com/hstern/go-caep" // registers the CAEP event decoders
)

set, err := secevent.Parse(payload)
if err != nil {
	return err
}
ev, ok, err := set.Events.Typed(caep.EventCredentialChange)
switch {
case err != nil:
	return err // the payload was malformed for this event type
case ok:
	cc := ev.(caep.CredentialChange)
	fmt.Println(cc.ChangeType, cc.CredentialType)
default:
	// no decoder registered for this URI: it stays raw and round-trips
}

Transmit: build a CAEP event into a SET

Put marshals a typed event into a SET's events map under its event-type URI. The optional Validate enforces the CAEP required-field MUSTs before you send.

e := caep.SessionRevoked{Base: caep.Base{
	EventTimestamp:   secevent.NewNumericDate(time.Now()),
	InitiatingEntity: caep.InitiatingEntityPolicy,
}}
if err := caep.Validate(e); err != nil {
	return err
}

set := &secevent.SET{ /* iss, iat, jti, aud, sub_id … */ Events: secevent.Events{}}
if err := caep.Put(set.Events, e); err != nil {
	return err
}
payload, err := set.Encode() // claims-set bytes for a JOSE signer

Unrecognized members on any event are preserved as json.RawMessage and round-trip byte-stably, so an event from a newer CAEP profile survives a decode/encode cycle unchanged. See the package examples for runnable versions.

Status

v0.1.0 — the first tagged release. As a v0.x series, the public API may still change per SemVer before v1.0.0. Runtime dependencies: the standard library plus go-secevent (which in turn uses go-subjectid).

License

Apache-2.0.

About

Go library implementing the OpenID CAEP 1.0 event vocabulary — typed event payloads registered into go-secevent.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages