ssf

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: MIT Imports: 21 Imported by: 0

README

SSFgo

CI SSF Conformance Go Reference Quality Gate

SSFgo is a lightweight Go implementation of the OpenID Shared Signals Framework, CAEP and RISC, providing embeddable Transmitter and Receiver capabilities with a focus on standards compliance and interoperability.

Status: pre-1.0. Both roles are implemented. Releases are v0.x, where a minor release may break the API; once v1.0.0 is tagged it is covered by COMPATIBILITY.md. The Transmitter passes every module of the OIDF CAEP Interoperability Profile Transmitter plan, and the Receiver every module of the Receiver plan — see conformance/README.md. The full matrix runs daily in CI. OIDF has not yet opened SSF certification. See ROADMAP.md.

Specifications

Specification Status in SSFgo
OpenID Shared Signals Framework 1.0 Transmitter and Receiver
OpenID CAEP 1.0 all 8 event types
OpenID RISC 1.0 all 14 event types
RFC 9967 SCIM events all 12 event types and the scim subject; one event per SET
CAEP Interoperability Profile 1.0 both roles pass the OIDF plans; caep/interop enforces the profile for each
RFC 8417 Security Event Token done
RFC 9493 Subject Identifiers done
RFC 8935 Push delivery / RFC 8936 Poll delivery both sides

The module has no third-party dependencies. Durable storage for PostgreSQL and SQLite is a separate module, storage/sqlstore, which imports no database driver itself.

Install

Requires Go 1.26.6 or later (per go.mod's go directive).

go get github.com/idfoundry/ssfgo
go get github.com/idfoundry/ssfgo/storage/sqlstore # durable storage, optional

Usage

GETTING_STARTED.md walks through embedding each role step by step, and docs/guides covers one feature each — session revocation, push or poll, the CAEP Interoperability Profile, SCIM events, storage and scaling, testing, observability and keys in a KMS or HSM. In brief:

A Transmitter — for example inside an identity provider — serves the SSF endpoints and emits events:

tx, err := transmitter.New(transmitter.Config{
	Issuer:          "https://idp.example.com/ssf",
	SigningKeys:     []transmitter.SigningKey{{Signer: key, Algorithm: ssf.RS256, KeyID: "2026-09"}},
	EventsSupported: interop.EventTypes(),
	DeliveryMethods: []ssf.DeliveryMethod{ssf.DeliveryPush, ssf.DeliveryPoll},
	DefaultSubjects: ssf.DefaultSubjectsAll,
	Store:           memstore.NewStreamStore(),
	Assurance:       ssf.AssuranceDevelopment, // AssuranceProduction refuses in-memory stores: use storage/sqlstore
	Authorize:       authorizeAccessToken, // your OAuth resource-server check
	PermitEvent:     permitEvent,          // which Receiver may see which subject's events
	Limits:          transmitter.RecommendedLimits(),
	PushRetry:       transmitter.RecommendedPushRetry(),
})
go tx.Run(ctx) // push delivery
http.ListenAndServeTLS(":443", cert, key, tx.Handler())

tx.Emit(ctx, ssf.IssSubSubject{Issuer: iss, Subject: "alice"}, caep.SessionRevoked{
	Common: caep.Common{ReasonAdmin: ssf.LocalizedText{"en": "Suspicious activity"}},
})

A Receiver — for example inside a relying party — creates a stream and handles typed events:

rx, err := receiver.New(ctx, receiver.Config{
	Issuer:      "https://idp.example.com/ssf",
	Audience:    "https://rp.example.com",
	Registry:    registry, // ssf.NewRegistry() + caep.Register
	Algorithms:  receiver.RecommendedAlgorithms(),
	TokenSource: &receiver.ClientCredentials{TokenURL: tokenURL, ClientID: id, ClientSecret: ssf.NewSecret(secret), AuthMethod: receiver.ClientSecretBasic},
	ReplayStore: memstore.NewReplayStore(),
	Assurance:   ssf.AssuranceDevelopment,
	Limits:      receiver.RecommendedLimits(), // replay window, key age, clock skew
})
// Optional: interop.ApplyReceiver(&cfg) before receiver.New holds the
// Transmitter to the CAEP Interoperability Profile.
receiver.On(rx, func(ctx context.Context, set ssf.SET, e caep.SessionRevoked) error {
	return sessions.RevokeAll(ctx, set.Subject)
})
pushSecret := ssf.NewSecret("Bearer " + randomToken) // withheld from logs and %v; Reveal() reads it
http.Handle("/ssf/events", rx.PushHandler(receiver.PushOptions{AuthorizationHeader: pushSecret}))
// Creates the stream on the first start; later starts reuse it, updating
// whatever changed, and wait out a Transmitter that is briefly unavailable.
stream, err := rx.EnsureStream(ctx, receiver.StreamRequest{Delivery: &ssf.Delivery{
	Method: ssf.DeliveryPush, EndpointURL: "https://rp.example.com/ssf/events", AuthorizationHeader: pushSecret,
}})

memstore keeps everything in memory, so ssf.AssuranceProduction refuses it. To survive restarts, or to run several instances on one database (HorizontallyScaled, which needs PostgreSQL), use storage/sqlstore:

// go get github.com/idfoundry/ssfgo/storage/sqlstore
db, err := sql.Open("pgx", dsn) // any database/sql driver for PostgreSQL or SQLite
err = sqlstore.CreateSchema(ctx, db, sqlstore.Postgres)
store, err := sqlstore.NewStreamStore(ctx, db, sqlstore.Postgres)   // transmitter.Config.Store
replay, err := sqlstore.NewReplayStore(ctx, db, sqlstore.Postgres)  // receiver.Config.ReplayStore
revocations, err := sqlstore.NewRevocationStore(ctx, db, sqlstore.Postgres) // revocation.Options.Store

examples/session-revocation runs both sides in one process: cd examples/session-revocation && go run .. Like every example, it is its own module and uses only the public API.

To revoke tokens as events arrive, revocation records what session-revoked, account-disabled and similar events mean and checks the application's validated tokens against it:

rev, err := revocation.New(revocation.Options{
	Store:     memstore.NewRevocationStore(),
	Issuers:   revocation.SameIssuer,           // or StaticTokenIssuers{transmitter: tokenIssuer}
	Events:    revocation.RecommendedEvents(),  // session-revoked, account-disabled, ...
	Retention: 24 * time.Hour,                  // at least the longest token lifetime
	Assurance: ssf.AssuranceDevelopment,        // production needs a durable store, e.g. sqlstore
})
if err := rev.Register(rx); err != nil { // fails if rx's Registry lacks one of Events
	return err
}
api = rev.Middleware(tokenOf, api)   // 401 for a token issued before its revocation

Both roles report what they do through optional Hooks in their config, for metrics or traces without a dependency on any metrics library, and answer readiness probes with Ready:

cfg.Hooks = receiver.Hooks{SET: func(ctx context.Context, i receiver.SETInfo) {
	setsTotal.WithLabelValues(string(i.EventType), i.Outcome.String()).Inc() // e.g. Prometheus
}}
http.HandleFunc("/readyz", func(w http.ResponseWriter, r *http.Request) {
	if err := rx.Ready(r.Context()); err != nil {
		http.Error(w, err.Error(), http.StatusServiceUnavailable)
	}
})

To test an application that plays one role, ssftest runs the other in-process: ssftest.NewTransmitter for testing a Receiver, ssftest.NewReceiver for testing a Transmitter.

tx := ssftest.NewTransmitter(t)
rx, err := receiver.New(ctx, tx.ReceiverConfig(registry))
stream, err := rx.EnsureStream(ctx, receiver.StreamRequest{})
err = tx.Emit(ctx, subject, caep.SessionRevoked{...})
_, err = rx.Poll(ctx, stream, receiver.PollOptions{}) // your handlers run

Design

See ARCHITECTURE.md, and SECURITY.md for the security model and how to report a vulnerability.

Contributing

See CONTRIBUTING.md. Changes are listed in CHANGELOG.md, and UPGRADING.md says what to change for each breaking one.

License

MIT — see LICENSE.

Documentation

Overview

Package ssf holds the value types shared by every part of SSFgo: subject identifiers (RFC 9493 and OpenID Shared Signals Framework 1.0 §3), the Event contract and Registry that event families such as caep, risc and scim plug into, SSF's own verification and stream-updated events, and the decoded view of a Security Event Token (SET).

This package knows nothing about any particular event family. It never imports caep, risc or scim; they register themselves with a Registry instead.

Encoding and signing SETs is deliberately not exposed here. Applications emit typed events through a Transmitter and receive verified SETs from a Receiver; neither needs to build a JWT by hand.

Index

Examples

Constants

View Source
const OAuth2SpecURN = "urn:ietf:rfc:6749" // NOSONAR: a public RFC identifier, not a secret

OAuth2SpecURN is the authorization scheme spec_urn for OAuth 2.0 (RFC 6749). The CAEP Interoperability Profile §2.3.7 requires Transmitters to advertise it.

View Source
const SpecVersion = "1_0"

SpecVersion is the "spec_version" SSFgo implements (SSF 1.0 §7.1).

View Source
const WellKnownPath = "/.well-known/ssf-configuration"

WellKnownPath is the path segment Transmitter Configuration Metadata is published under (SSF 1.0 §7.2).

Variables

View Source
var ErrInvalidEvent = errors.New("ssf: invalid event")

ErrInvalidEvent is wrapped by every error that reports a malformed event object.

View Source
var ErrInvalidSubject = errors.New("ssf: invalid subject")

ErrInvalidSubject is wrapped by every error that reports a malformed or incomplete subject.

View Source
var ErrSecretSerialization = errors.New("ssf: secret values cannot be marshaled")

ErrSecretSerialization is returned by Secret.MarshalText, so a Secret is never serialized — into a log line, a JSON body, a debug dump — by code that does not know it holds one.

View Source
var ErrUnsupportedEventType = errors.New("ssf: unsupported event type")

ErrUnsupportedEventType is returned by Registry.Decode for an event type the registry has no decoder for.

Functions

func Register

func Register[E Event](r *Registry) error

Register adds event type E to r. E's zero value supplies the event type URI. Registering a type twice is an error.

func SubjectsEqual

func SubjectsEqual(a, b Subject) bool

SubjectsEqual reports whether a and b are identical: the same format and the same member values. Aliases compare their identifiers in order.

func SubjectsMatch

func SubjectsMatch(a, b Subject) bool

SubjectsMatch reports whether a and b match under SSF 1.0 §8.1.3.1. Simple subjects match when they are identical. Two complex subjects match when every member defined in both is identical; a member defined in only one of them acts as a wildcard. A simple subject never matches a complex one.

func ValidateIssuer

func ValidateIssuer(issuer string) error

ValidateIssuer reports whether issuer is an https URL with no query or fragment (SSF 1.0 §7.1).

func WellKnownURL

func WellKnownURL(issuer string) (string, error)

WellKnownURL returns where issuer publishes its Transmitter Configuration Metadata: "/.well-known/ssf-configuration" inserted between the host and any path, with a trailing "/" removed first (SSF 1.0 §7.2).

Example

A Transmitter's metadata is at a well-known location derived from its issuer (SSF 1.0 §7.2).

package main

import (
	"fmt"

	ssf "github.com/idfoundry/ssfgo"
)

func main() {
	u, err := ssf.WellKnownURL("https://idp.example.com/tenants/acme")
	if err != nil {
		panic(err)
	}
	fmt.Println(u)
}
Output:
https://idp.example.com/.well-known/ssf-configuration/tenants/acme

Types

type AccountSubject

type AccountSubject struct {
	// URI is the "acct" URI, such as "acct:alice@example.com". Required.
	URI string
}

AccountSubject identifies a subject by an "acct" URI (RFC 9493 §3.2.1).

func (AccountSubject) Format

func (AccountSubject) Format() SubjectFormat

Format implements Subject.

func (AccountSubject) MarshalJSON

func (s AccountSubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (AccountSubject) Validate

func (s AccountSubject) Validate() error

Validate implements Subject.

type AddSubjectRequest

type AddSubjectRequest struct {
	// StreamID is the stream to add the subject to. Required.
	StreamID string
	// Subject is the subject to add. Required.
	Subject Subject
	// Verified is nil when the Receiver did not say; the Transmitter
	// should then assume the subject was verified.
	Verified *bool
}

AddSubjectRequest is the body of an Add Subject request (SSF 1.0 §8.1.3.2).

func (AddSubjectRequest) MarshalJSON

func (r AddSubjectRequest) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (*AddSubjectRequest) UnmarshalJSON

func (r *AddSubjectRequest) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

type AliasesSubject

type AliasesSubject struct {
	// Identifiers are the subject's identifiers, one or more.
	Identifiers []Subject
}

AliasesSubject identifies one subject by several Subject Identifiers (RFC 9493 §3.2.8). Its identifiers may not themselves be aliases or complex subjects.

func (AliasesSubject) Format

func (AliasesSubject) Format() SubjectFormat

Format implements Subject.

func (AliasesSubject) MarshalJSON

func (s AliasesSubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (AliasesSubject) Validate

func (s AliasesSubject) Validate() error

Validate implements Subject.

type Assurance

type Assurance uint8

Assurance is the deployment a Transmitter, Receiver or Revoker is configured for. It is required: there is no default, and the zero value is invalid.

const (
	// AssuranceDevelopment accepts what tests and local development use:
	// in-memory stores, loopback hosts.
	AssuranceDevelopment Assurance = iota + 1
	// AssuranceProduction refuses them: every store must declare it is
	// durable (storage.Capabilities), and, when the deployment is
	// horizontally scaled, consistent across instances; every signing key
	// must be declared durable (KeyCustody); the issuer and endpoints
	// configured must not be loopback hosts.
	AssuranceProduction
)

func (Assurance) IsValid

func (a Assurance) IsValid() bool

IsValid reports whether a is AssuranceDevelopment or AssuranceProduction.

func (Assurance) String

func (a Assurance) String() string

String returns "development" or "production".

type Audience

type Audience []string

Audience is a JWT "aud" value: one string or an array of strings (RFC 7519 §4.1.3). It encodes a single value as a string, and no values as an empty array rather than null, so every encoding decodes again.

func (Audience) MarshalJSON

func (a Audience) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (*Audience) UnmarshalJSON

func (a *Audience) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

type AuthorizationScheme

type AuthorizationScheme struct {
	// SpecURN is the URN of the specification defining the scheme, such
	// as OAuth2SpecURN.
	SpecURN string `json:"spec_urn"`
}

AuthorizationScheme names a scheme protecting the stream management API (SSF 1.0 §7.1.1).

type ComplexSubject

type ComplexSubject struct {
	// User is the "user" member; nil if absent.
	User Subject
	// Device is the "device" member; nil if absent.
	Device Subject
	// Session is the "session" member; nil if absent.
	Session Subject
	// Application is the "application" member; nil if absent.
	Application Subject
	// Tenant is the "tenant" member; nil if absent.
	Tenant Subject
	// OrgUnit is the "org_unit" member; nil if absent.
	OrgUnit Subject
	// Group is the "group" member; nil if absent.
	Group Subject
	// Additional maps further member names to their subjects.
	Additional map[string]Subject
}

ComplexSubject describes one Subject Principal through several of its attributes (SSF 1.0 §3.3). At least one member must be set. Members are simple subjects: a ComplexSubject never nests another.

Additional carries member names beyond those SSF 1.0 §3.3 lists; its keys must not repeat a named member or "format".

func (ComplexSubject) Format

func (ComplexSubject) Format() SubjectFormat

Format implements Subject.

func (ComplexSubject) MarshalJSON

func (s ComplexSubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler. Defined members are encoded in SSF 1.0 §3.3 order, followed by Additional members sorted by name.

func (ComplexSubject) Validate

func (s ComplexSubject) Validate() error

Validate implements Subject.

type DIDSubject

type DIDSubject struct {
	// URL is the DID URL, such as "did:example:123456". Required.
	URL string
}

DIDSubject identifies a subject by a Decentralized Identifier URL (RFC 9493 §3.2.6).

func (DIDSubject) Format

func (DIDSubject) Format() SubjectFormat

Format implements Subject.

func (DIDSubject) MarshalJSON

func (s DIDSubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (DIDSubject) Validate

func (s DIDSubject) Validate() error

Validate implements Subject.

type DefaultSubjects

type DefaultSubjects string

DefaultSubjects says whether newly created streams include every appropriate subject or none (SSF 1.0 §7.1).

const (
	// DefaultSubjectsAll adds every appropriate subject to new streams;
	// Receivers remove the ones they do not want.
	DefaultSubjectsAll DefaultSubjects = "ALL"
	// DefaultSubjectsNone adds no subjects to new streams; Receivers add
	// the ones they want.
	DefaultSubjectsNone DefaultSubjects = "NONE"
)

type Delivery

type Delivery struct {
	// Method is the "method" member: DeliveryPush or DeliveryPoll.
	Method DeliveryMethod `json:"method"`
	// EndpointURL is where the Transmitter pushes SETs (push, set by the
	// Receiver) or where the Receiver polls for them (poll, set by the
	// Transmitter).
	EndpointURL string `json:"endpoint_url,omitempty"`
	// AuthorizationHeader is the push-only Authorization header value
	// the Transmitter sends with every push request (SSF 1.0 §6.1.1).
	AuthorizationHeader Secret `json:"authorization_header,omitzero"`
}

Delivery is a stream's "delivery" member (SSF 1.0 §6.1).

func (Delivery) LogValue

func (d Delivery) LogValue() slog.Value

LogValue implements slog.LogValuer: a logged Delivery withholds its Authorization header, which a JSON handler would otherwise take from MarshalJSON.

func (Delivery) MarshalJSON

func (d Delivery) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler. A Delivery's JSON is its wire form (SSF 1.0 §6.1), and so includes the Authorization header: it is for the protocol and for storage, never for a log.

type DeliveryMethod

type DeliveryMethod string

DeliveryMethod identifies how SETs are delivered on a stream (SSF 1.0 §6.1).

const (
	// DeliveryPush is push-based delivery over HTTP (RFC 8935).
	DeliveryPush DeliveryMethod = "urn:ietf:rfc:8935"
	// DeliveryPoll is poll-based delivery over HTTP (RFC 8936).
	DeliveryPoll DeliveryMethod = "urn:ietf:rfc:8936"
)

type EmailSubject

type EmailSubject struct {
	// Email is the email address. Required.
	Email string
}

EmailSubject identifies a subject by email address (RFC 9493 §3.2.2). Addresses are compared exactly; a Receiver that needs provider-specific canonicalization (RFC 9493 §3.2.2.1) applies it itself.

func (EmailSubject) Format

func (EmailSubject) Format() SubjectFormat

Format implements Subject.

func (EmailSubject) MarshalJSON

func (s EmailSubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (EmailSubject) Validate

func (s EmailSubject) Validate() error

Validate implements Subject. It checks only that the address has a non-empty local part and domain; RFC 5322 addr-spec syntax is otherwise the Transmitter's responsibility.

type Event

type Event interface {
	EventType() EventType
	// Validate reports whether every member the event type requires is
	// present and every member present has a permitted value.
	Validate() error
}

Event is one event family's typed representation of an event object — the value under its EventType in a SET's "events" claim. It does not include the subject: SSF 1.0 §3.1 carries the primary subject in the SET's top-level "sub_id" claim.

Implementations are value types whose JSON encoding is the event object, and whose EventType does not depend on the receiver's value, so the zero value reports its type.

type EventType

type EventType string

EventType is an event type URI, the key of a SET's "events" claim (RFC 8417 §2.2).

const (
	// VerificationEventType is the verification event (SSF 1.0 §8.1.4.1).
	VerificationEventType EventType = "https://schemas.openid.net/secevent/ssf/event-type/verification"
	// StreamUpdatedEventType is the stream-updated event (SSF 1.0 §8.1.5).
	StreamUpdatedEventType EventType = "https://schemas.openid.net/secevent/ssf/event-type/stream-updated"
)

Event types defined by SSF 1.0 itself.

type IPAddressesSubject

type IPAddressesSubject struct {
	// Addresses are the observed IPv4 or IPv6 addresses, one or more.
	Addresses []netip.Addr
}

IPAddressesSubject identifies a subject by the IP addresses the Transmitter observed for it (SSF 1.0 §3.5.3).

func (IPAddressesSubject) Format

Format implements Subject.

func (IPAddressesSubject) MarshalJSON

func (s IPAddressesSubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (IPAddressesSubject) Validate

func (s IPAddressesSubject) Validate() error

Validate implements Subject.

type IssSubSubject

type IssSubSubject struct {
	// Issuer is the "iss" of the subject's issuer. Required.
	Issuer string
	// Subject is the "sub", unique within Issuer. Required.
	Subject string
}

IssSubSubject identifies a subject by issuer and subject (RFC 9493 §3.2.3).

func (IssSubSubject) Format

func (IssSubSubject) Format() SubjectFormat

Format implements Subject.

func (IssSubSubject) MarshalJSON

func (s IssSubSubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (IssSubSubject) Validate

func (s IssSubSubject) Validate() error

Validate implements Subject.

type JWTIDSubject

type JWTIDSubject struct {
	// Issuer is the JWT's "iss". Required.
	Issuer string
	// JWTID is the JWT's "jti". Required.
	JWTID string
}

JWTIDSubject identifies a JWT by its issuer and "jti" (SSF 1.0 §3.5.1).

func (JWTIDSubject) Format

func (JWTIDSubject) Format() SubjectFormat

Format implements Subject.

func (JWTIDSubject) MarshalJSON

func (s JWTIDSubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (JWTIDSubject) Validate

func (s JWTIDSubject) Validate() error

Validate implements Subject.

type KeyCustody

type KeyCustody struct {
	// Durable means the key survives a process restart: held by a KMS or
	// an HSM, or loaded from durable storage, rather than generated at
	// startup.
	Durable bool
	// CrossInstanceConsistent means every instance of a horizontally
	// scaled deployment uses the same key.
	CrossInstanceConsistent bool
}

KeyCustody is what is declared about how a private key is held. Under AssuranceProduction a Transmitter's signing keys, and a Receiver's private_key_jwt key, must be declared durable — and, when the deployment is horizontally scaled, shared by every instance — because nothing about a crypto.Signer says whether its key survives a restart.

A Transmitter signs SETs when it queues them, so a signing key made afresh at each start strands every SET queued before a restart: the Receiver no longer finds its key, and rejects it. Instances with keys of their own sign SETs that only some JWKS documents verify.

type KeyCustodyAssurance

type KeyCustodyAssurance interface {
	KeyCustody() KeyCustody
}

KeyCustodyAssurance is implemented by a crypto.Signer that declares how its key is held — a KMS or HSM client, say. A key that neither implements it nor has custody declared for it in its configuration counts as neither durable nor shared.

type LocalizedText

type LocalizedText map[string]string

LocalizedText is a JSON object mapping BCP 47 language tags (RFC 5646) to human-readable text, as used by CAEP's "reason_admin" and "reason_user" (CAEP 1.0 §2).

A nil or empty LocalizedText means "absent": use it with the `omitempty` struct tag. When present it must hold at least one entry.

func (*LocalizedText) UnmarshalJSON

func (t *LocalizedText) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler. It rejects anything but a JSON object of strings — CAEP 1.0 §2 does not permit a bare string.

func (LocalizedText) Validate

func (t LocalizedText) Validate() error

Validate reports whether t is non-empty and every key is a plausible language tag. The tag grammar is not checked in full.

type NumericDate

type NumericDate struct {
	time.Time
}

NumericDate is a JSON number of seconds since the Unix epoch (RFC 7519 §2), as used by "iat" and CAEP's "event_timestamp".

The zero value means "absent": use it with the `omitzero` struct tag. Encoding truncates to whole seconds; decoding accepts fractional seconds.

func NewNumericDate

func NewNumericDate(t time.Time) NumericDate

NewNumericDate returns t as a NumericDate truncated to whole seconds.

func (NumericDate) MarshalJSON

func (d NumericDate) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (*NumericDate) UnmarshalJSON

func (d *NumericDate) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler. It rejects anything but a JSON number, including a numeric string.

type OpaqueSubject

type OpaqueSubject struct {
	// ID is the opaque identifier. Required.
	ID string
}

OpaqueSubject identifies a subject by an opaque string (RFC 9493 §3.2.4). SSF's verification and stream-updated events use it to carry a stream ID.

func (OpaqueSubject) Format

func (OpaqueSubject) Format() SubjectFormat

Format implements Subject.

func (OpaqueSubject) MarshalJSON

func (s OpaqueSubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (OpaqueSubject) Validate

func (s OpaqueSubject) Validate() error

Validate implements Subject.

type PhoneNumberSubject

type PhoneNumberSubject struct {
	// PhoneNumber is the number in E.164 form, with its "+" prefix, such
	// as "+12065550100". Required.
	PhoneNumber string
}

PhoneNumberSubject identifies a subject by telephone number (RFC 9493 §3.2.5).

func (PhoneNumberSubject) Format

Format implements Subject.

func (PhoneNumberSubject) MarshalJSON

func (s PhoneNumberSubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (PhoneNumberSubject) Validate

func (s PhoneNumberSubject) Validate() error

Validate implements Subject. It requires the international prefix "+" (RFC 9493 §3.2.5) but does not otherwise police E.164 formatting.

type ProprietarySubject

type ProprietarySubject struct {
	// FormatName is the "format" member. Required.
	FormatName SubjectFormat
	// Members maps each other member's name to its raw JSON value.
	Members map[string]json.RawMessage
}

ProprietarySubject carries a Subject Identifier whose format is agreed between Transmitter and Receiver out of band (SSF 1.0 §3.4). Members holds every member except "format", as raw JSON.

func (ProprietarySubject) Format

func (s ProprietarySubject) Format() SubjectFormat

Format implements Subject.

func (ProprietarySubject) MarshalJSON

func (s ProprietarySubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler. Members are sorted by name.

func (ProprietarySubject) Validate

func (s ProprietarySubject) Validate() error

Validate implements Subject.

type Registry

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

Registry maps event type URIs to decoders. There is no global registry: a Receiver is given one, and a Transmitter derives the event types it supports from one. NewRegistry returns a registry that already holds SSF's own events; event families add theirs with Register — for example caep.Register(r) and risc.Register(r).

A Registry is safe for concurrent use.

func NewRegistry

func NewRegistry() *Registry

NewRegistry returns a registry holding SSF 1.0's verification and stream-updated events.

func (*Registry) Decode

func (r *Registry) Decode(typ EventType, payload json.RawMessage) (Event, error)

Decode decodes and validates the event object payload as typ. It returns an error wrapping ErrUnsupportedEventType if typ is not registered.

func (*Registry) Supports

func (r *Registry) Supports(typ EventType) bool

Supports reports whether r has a decoder for typ.

func (*Registry) Types

func (r *Registry) Types() []EventType

Types returns every registered event type, sorted.

type RemoveSubjectRequest

type RemoveSubjectRequest struct {
	// StreamID is the stream to remove the subject from. Required.
	StreamID string
	// Subject is the subject to remove. Required.
	Subject Subject
}

RemoveSubjectRequest is the body of a Remove Subject request (SSF 1.0 §8.1.3.3).

func (RemoveSubjectRequest) MarshalJSON

func (r RemoveSubjectRequest) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (*RemoveSubjectRequest) UnmarshalJSON

func (r *RemoveSubjectRequest) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

type SAMLAssertionIDSubject

type SAMLAssertionIDSubject struct {
	// Issuer is the assertion's Issuer. Required.
	Issuer string
	// AssertionID is the assertion's ID. Required.
	AssertionID string
}

SAMLAssertionIDSubject identifies a SAML 2.0 assertion (SSF 1.0 §3.5.2).

func (SAMLAssertionIDSubject) Format

Format implements Subject.

func (SAMLAssertionIDSubject) MarshalJSON

func (s SAMLAssertionIDSubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (SAMLAssertionIDSubject) Validate

func (s SAMLAssertionIDSubject) Validate() error

Validate implements Subject.

type SCIMSubject

type SCIMSubject struct {
	// URI is the resource's path relative to the SCIM service provider's
	// base URI, such as "/Users/2b2f880af6674ac284bae9381673d462".
	// Required.
	URI string
	// ExternalID is the resource's "externalId", if known.
	ExternalID string
	// ID is the resource's "id", which RFC 9967 allows alongside URI for
	// backwards compatibility.
	ID string
	// Attributes holds further members — SCIM attributes unique within the
	// service provider, such as "userName" or "emails" — as raw JSON. Its
	// keys must not be "format", "uri", "externalId" or "id".
	Attributes map[string]json.RawMessage
}

SCIMSubject identifies a SCIM resource (RFC 9967 §2.1).

func (SCIMSubject) Format

func (SCIMSubject) Format() SubjectFormat

Format implements Subject.

func (SCIMSubject) MarshalJSON

func (s SCIMSubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler. Attributes follow the modelled members, sorted by name.

func (SCIMSubject) Validate

func (s SCIMSubject) Validate() error

Validate implements Subject.

type SET

type SET struct {
	// Issuer is the "iss" claim: the Transmitter's issuer identifier.
	Issuer string
	// Audience is the "aud" claim. It holds at least one value.
	Audience []string
	// JWTID is the "jti" claim, unique per SET.
	JWTID string
	// IssuedAt is the "iat" claim.
	IssuedAt time.Time
	// TransactionID is the optional "txn" claim (SSF 1.0 §4.1.9). SETs
	// caused by the same underlying occurrence may share it.
	TransactionID string
	// Subject is the "sub_id" claim (SSF 1.0 §3.1).
	Subject Subject
	// Event is the single entry of the "events" claim.
	Event Event
}

SET is the content of a Security Event Token (RFC 8417) as profiled by SSF 1.0 §4: one event about one primary subject.

A Receiver hands handlers a SET only after verifying its signature, issuer, audience and freshness. A Transmitter builds SETs itself from the events an application emits; applications never construct or sign one directly.

func (SET) Validate

func (s SET) Validate() error

Validate reports whether s has every member SSF 1.0 §4 requires and whether its event and subject are valid together.

type Secret

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

Secret holds a credential — a client secret, a push Authorization header — that must not reach a log, an error message or a debug dump by accident. Every fmt verb, LogValue and MarshalText withhold it, as does fmt printing a struct that holds a Secret in an unexported field; Reveal is the only way to read it, at the point it is sent.

A Secret can be decoded, and compared with ==. A wire type that must carry one, such as Delivery, reveals it in its own MarshalJSON.

Example

A Secret is withheld wherever it is printed or logged; Reveal gives it up where it is sent.

package main

import (
	"fmt"

	ssf "github.com/idfoundry/ssfgo"
)

func main() {
	header := ssf.NewSecret("Bearer s3cret")
	fmt.Printf("%v %+v %#v\n", header, ssf.Delivery{AuthorizationHeader: header}, header)
	fmt.Println(header.Reveal())
}
Output:
[REDACTED] {Method: EndpointURL: AuthorizationHeader:[REDACTED]} ssf.Secret([REDACTED])
Bearer s3cret

func NewSecret

func NewSecret(value string) Secret

NewSecret returns value as a Secret.

func (Secret) Format

func (s Secret) Format(f fmt.State, verb rune)

Format implements fmt.Formatter, so every verb — %d and %x included — prints the placeholder, and %#v the GoString.

func (Secret) GoString

func (s Secret) GoString() string

GoString implements fmt.GoStringer, so %#v withholds the value too.

func (Secret) IsZero

func (s Secret) IsZero() bool

IsZero reports whether s holds no value.

func (Secret) LogValue

func (s Secret) LogValue() slog.Value

LogValue implements slog.LogValuer, so a Secret logged as an attribute is withheld.

func (Secret) MarshalText

func (s Secret) MarshalText() ([]byte, error)

MarshalText always fails, so a Secret in a struct cannot be serialized by encoding/json or encoding/xml without a MarshalJSON that reveals it on purpose.

func (Secret) Reveal

func (s Secret) Reveal() string

Reveal returns the secret value.

func (Secret) String

func (s Secret) String() string

String returns a fixed placeholder, never the value.

func (*Secret) UnmarshalText

func (s *Secret) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler: a Secret can be read from the wire.

type SignatureAlgorithm

type SignatureAlgorithm uint8

SignatureAlgorithm is the closed set of JWS algorithms SSFgo signs and verifies Security Event Tokens with. A SET's "alg" header is untrusted input: a Receiver states which algorithms it accepts before any signature is checked, rather than trusting whatever the header claims.

Every asymmetric algorithm of RFC 7518 §3.1 is supported, and EdDSA with Ed25519. HMAC and "none" never are: a SET is verified with the Transmitter's published public keys, never a shared secret.

const (

	// RS256 is RSASSA-PKCS1-v1_5 using SHA-256 (RFC 7518 §3.3), with a
	// minimum 2048-bit modulus. The CAEP Interoperability Profile §2.6
	// requires every event to be signed with it.
	RS256 SignatureAlgorithm

	// PS256 is RSASSA-PSS using SHA-256 and MGF1 with SHA-256
	// (RFC 7518 §3.5), with a minimum 2048-bit modulus.
	PS256

	// ES256 is ECDSA using the P-256 curve and SHA-256 (RFC 7518 §3.4).
	ES256

	// EdDSA is pure EdDSA using Ed25519 (RFC 8037 §3.1).
	EdDSA

	// RS384 is RSASSA-PKCS1-v1_5 using SHA-384 (RFC 7518 §3.3).
	RS384

	// RS512 is RSASSA-PKCS1-v1_5 using SHA-512 (RFC 7518 §3.3).
	RS512

	// PS384 is RSASSA-PSS using SHA-384 and MGF1 with SHA-384
	// (RFC 7518 §3.5).
	PS384

	// PS512 is RSASSA-PSS using SHA-512 and MGF1 with SHA-512
	// (RFC 7518 §3.5).
	PS512

	// ES384 is ECDSA using the P-384 curve and SHA-384 (RFC 7518 §3.4).
	ES384

	// ES512 is ECDSA using the P-521 curve and SHA-512 (RFC 7518 §3.4).
	ES512
)

func ParseSignatureAlgorithm

func ParseSignatureAlgorithm(alg string) (SignatureAlgorithm, error)

ParseSignatureAlgorithm maps a JOSE "alg" header value to a SignatureAlgorithm. It rejects every value outside the closed set, including "none" and every HMAC algorithm. Matching is exact: "rs256" is not RS256.

func SignatureAlgorithms

func SignatureAlgorithms() []SignatureAlgorithm

SignatureAlgorithms returns every algorithm SSFgo supports, in the order of their constants.

func (SignatureAlgorithm) IsValid

func (a SignatureAlgorithm) IsValid() bool

IsValid reports whether a is one of the algorithms SSFgo supports.

func (SignatureAlgorithm) String

func (a SignatureAlgorithm) String() string

String returns the JOSE "alg" header value for a, or "" if a is not a recognized algorithm.

type StreamConfiguration

type StreamConfiguration struct {
	// StreamID is the "stream_id" the Transmitter assigned.
	StreamID string `json:"stream_id"`
	// Issuer is the Transmitter's issuer identifier, the "iss" of the
	// stream's SETs.
	Issuer string `json:"iss"`
	// Audience is the "aud" of the stream's SETs.
	Audience Audience `json:"aud"`
	// EventsSupported are the event types the Transmitter supports.
	EventsSupported []EventType `json:"events_supported,omitempty"`
	// EventsRequested are the event types the Receiver asked for.
	EventsRequested []EventType `json:"events_requested,omitempty"`
	// EventsDelivered is always encoded, as an empty array when no
	// event types are delivered.
	EventsDelivered []EventType `json:"events_delivered"`
	// Delivery is how the stream's SETs are delivered.
	Delivery Delivery `json:"delivery"`
	// MinVerificationInterval is in seconds; zero means none.
	MinVerificationInterval int `json:"min_verification_interval,omitempty"`
	// Description is the Receiver's free-text description of the stream;
	// empty if none.
	Description string `json:"description,omitempty"`
	// InactivityTimeout is in seconds; zero means none.
	InactivityTimeout int `json:"inactivity_timeout,omitempty"`
}

StreamConfiguration is an event stream's configuration (SSF 1.0 §8.1.1), as the Transmitter returns it.

func (StreamConfiguration) LogValue

func (c StreamConfiguration) LogValue() slog.Value

LogValue implements slog.LogValuer: a logged StreamConfiguration withholds its delivery's Authorization header.

func (StreamConfiguration) MarshalJSON

func (c StreamConfiguration) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler, encoding a nil EventsDelivered as an empty array because the member is required.

type StreamState

type StreamState struct {
	// StreamID is the stream's "stream_id".
	StreamID string `json:"stream_id"`
	// Status is the stream's status: enabled, paused or disabled.
	Status StreamStatus `json:"status"`
	// Reason is free text explaining the status; empty if none given.
	Reason string `json:"reason,omitempty"`
}

StreamState is a stream's status as read from, or written to, the Status Endpoint (SSF 1.0 §8.1.2).

type StreamStatus

type StreamStatus string

StreamStatus is the status of an event stream (SSF 1.0 §8.1.2).

const (
	// StreamEnabled means the Transmitter transmits events over the
	// stream.
	StreamEnabled StreamStatus = "enabled"
	// StreamPaused means the Transmitter holds events and transmits them
	// once the stream is enabled again.
	StreamPaused StreamStatus = "paused"
	// StreamDisabled means the Transmitter neither transmits nor holds
	// events.
	StreamDisabled StreamStatus = "disabled"
)

func (StreamStatus) IsValid

func (s StreamStatus) IsValid() bool

IsValid reports whether s is one of the statuses SSF 1.0 §8.1.2 defines.

type StreamUpdated

type StreamUpdated struct {
	// Status is the stream's new status. Required.
	Status StreamStatus `json:"status"`
	// Reason is free text explaining the change; empty if none given.
	// Untrusted on receipt: it is the Transmitter's text.
	Reason string `json:"reason,omitempty"`
}

StreamUpdated tells the Receiver that the Transmitter changed a stream's status (SSF 1.0 §8.1.5). Its SET's "sub_id" is an OpaqueSubject whose ID is the stream ID.

func (StreamUpdated) EventType

func (StreamUpdated) EventType() EventType

EventType implements Event.

func (StreamUpdated) Validate

func (e StreamUpdated) Validate() error

Validate implements Event.

func (StreamUpdated) ValidateSubject

func (StreamUpdated) ValidateSubject(s Subject) error

ValidateSubject implements SubjectConstrainedEvent.

type Subject

type Subject interface {
	// Format returns the value of the subject's "format" member.
	Format() SubjectFormat
	// Validate reports whether every member the format requires is
	// present and well formed.
	Validate() error
	json.Marshaler
	// contains filtered or unexported methods
}

Subject is a Subject Member value (SSF 1.0 §3.1.4): either a simple Subject Identifier (RFC 9493) or a ComplexSubject.

Subject is a closed set. Its implementations are exactly the *Subject types in this package, so a type switch over them is exhaustive. A format agreed between two parties out of band (SSF 1.0 §3.4) is carried by ProprietarySubject.

MarshalJSON validates before encoding, so an invalid subject can never be emitted.

func ParseSubject

func ParseSubject(data []byte) (Subject, error)

ParseSubject decodes and validates a Subject Member value.

Members the format does not define are ignored rather than rejected: SSF 1.0 §4.2.3 requires Receivers to ignore fields they do not understand. A format ParseSubject does not recognize is returned as a ProprietarySubject, which the caller may reject.

type SubjectConstrainedEvent

type SubjectConstrainedEvent interface {
	Event
	ValidateSubject(Subject) error
}

SubjectConstrainedEvent is implemented by events whose definition restricts the SET's "sub_id" — for example SSF's verification event, which requires an opaque stream ID.

type SubjectFormat

type SubjectFormat string

SubjectFormat is the value of a Subject Identifier's "format" member (RFC 9493 §3).

const (
	FormatAccount     SubjectFormat = "account"
	FormatEmail       SubjectFormat = "email"
	FormatIssSub      SubjectFormat = "iss_sub"
	FormatOpaque      SubjectFormat = "opaque"
	FormatPhoneNumber SubjectFormat = "phone_number"
	FormatDID         SubjectFormat = "did"
	FormatURI         SubjectFormat = "uri"
	FormatAliases     SubjectFormat = "aliases"
)

Subject Identifier formats registered by RFC 9493 §3.2.

const (
	FormatJWTID           SubjectFormat = "jwt_id"
	FormatSAMLAssertionID SubjectFormat = "saml_assertion_id"
	FormatIPAddresses     SubjectFormat = "ip-addresses"
	FormatComplex         SubjectFormat = "complex"
)

Subject Identifier formats defined by SSF 1.0 §3.5, and the complex subject format of SSF 1.0 §3.3.

const FormatSCIM SubjectFormat = "scim"

FormatSCIM identifies a SCIM resource (RFC 9967 §2.1), the subject of SCIM events.

type TransmitterMetadata

type TransmitterMetadata struct {
	// SpecVersion is the version of SSF implemented, such as SpecVersion.
	SpecVersion string `json:"spec_version,omitempty"`
	// Issuer is the Transmitter's issuer identifier, an https URL. A
	// Receiver checks it against the issuer it expected.
	Issuer string `json:"issuer"`
	// JWKSURI is where the Transmitter publishes the keys that sign its
	// SETs. It must be https.
	JWKSURI string `json:"jwks_uri,omitempty"`
	// DeliveryMethodsSupported are the delivery methods the Transmitter
	// supports.
	DeliveryMethodsSupported []DeliveryMethod `json:"delivery_methods_supported,omitempty"`
	// ConfigurationEndpoint is the stream configuration endpoint
	// (SSF 1.0 §8.1.1); empty if not supported.
	ConfigurationEndpoint string `json:"configuration_endpoint,omitempty"`
	// StatusEndpoint is the stream status endpoint (SSF 1.0 §8.1.2);
	// empty if not supported.
	StatusEndpoint string `json:"status_endpoint,omitempty"`
	// AddSubjectEndpoint is the Add Subject endpoint (SSF 1.0 §8.1.3.2);
	// empty if not supported.
	AddSubjectEndpoint string `json:"add_subject_endpoint,omitempty"`
	// RemoveSubjectEndpoint is the Remove Subject endpoint
	// (SSF 1.0 §8.1.3.3); empty if not supported.
	RemoveSubjectEndpoint string `json:"remove_subject_endpoint,omitempty"`
	// VerificationEndpoint is the Verification endpoint
	// (SSF 1.0 §8.1.4.2); empty if not supported.
	VerificationEndpoint string `json:"verification_endpoint,omitempty"`
	// CriticalSubjectMembers names complex-subject members a Receiver
	// must understand: a Receiver rejects a SET whose subject carries
	// one it does not process (SSF 1.0 §3.6).
	CriticalSubjectMembers []string `json:"critical_subject_members,omitempty"`
	// AuthorizationSchemes are the schemes protecting the stream
	// management API.
	AuthorizationSchemes []AuthorizationScheme `json:"authorization_schemes,omitempty"`
	// DefaultSubjects says whether new streams include every subject or
	// none; empty if the Transmitter does not say.
	DefaultSubjects DefaultSubjects `json:"default_subjects,omitempty"`
}

TransmitterMetadata is the Transmitter Configuration Metadata document (SSF 1.0 §7.1). Array members with no elements are omitted, as §7.2.3 requires.

type URISubject

type URISubject struct {
	// URI is the subject's URI. Required.
	URI string
}

URISubject identifies a subject by URI (RFC 9493 §3.2.7).

func (URISubject) Format

func (URISubject) Format() SubjectFormat

Format implements Subject.

func (URISubject) MarshalJSON

func (s URISubject) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (URISubject) Validate

func (s URISubject) Validate() error

Validate implements Subject.

type Verification

type Verification struct {
	// State echoes the value the Receiver supplied when it requested
	// verification. It is empty for a verification the Transmitter
	// sends unprompted.
	State string `json:"state,omitempty"`
}

Verification is sent over a stream to confirm it is configured correctly (SSF 1.0 §8.1.4.1). Its SET's "sub_id" is an OpaqueSubject whose ID is the stream ID.

func (Verification) EventType

func (Verification) EventType() EventType

EventType implements Event.

func (Verification) Validate

func (Verification) Validate() error

Validate implements Event. Every member is optional.

func (Verification) ValidateSubject

func (Verification) ValidateSubject(s Subject) error

ValidateSubject implements SubjectConstrainedEvent.

type VerificationRequest

type VerificationRequest struct {
	// StreamID is the stream to verify.
	StreamID string `json:"stream_id"`
	// State is an opaque value the Transmitter echoes in the verification
	// event; empty if none.
	State string `json:"state,omitempty"`
}

VerificationRequest is the body of a request to the Verification Endpoint (SSF 1.0 §8.1.4.2).

Directories

Path Synopsis
Package caep implements the eight event types of OpenID Continuous Access Evaluation Profile 1.0 (CAEP) on top of the Shared Signals Framework.
Package caep implements the eight event types of OpenID Continuous Access Evaluation Profile 1.0 (CAEP) on top of the Shared Signals Framework.
interop
Package interop applies the OpenID CAEP Interoperability Profile 1.0 to an SSFgo Transmitter or Receiver.
Package interop applies the OpenID CAEP Interoperability Profile 1.0 to an SSFgo Transmitter or Receiver.
cmd
conformance-receiver command
Command conformance-receiver drives SSFgo's Receiver through an OIDF SSF Receiver test plan against a running conformance suite.
Command conformance-receiver drives SSFgo's Receiver through an OIDF SSF Receiver test plan against a running conformance suite.
conformance-transmitter command
Command conformance-transmitter runs an SSFgo Transmitter configured for the OpenID Foundation SSF conformance suite's CAEP Interoperability Profile Transmitter plan, with in-memory storage.
Command conformance-transmitter runs an SSFgo Transmitter configured for the OpenID Foundation SSF conformance suite's CAEP Interoperability Profile Transmitter plan, with in-memory storage.
internal
assurance
Package assurance applies ssf.AssuranceProduction's requirements, the same for every role.
Package assurance applies ssf.AssuranceProduction's requirements, the same for every role.
clientassertion
Package clientassertion builds the signed JWTs a client presents to an OAuth 2.0 token endpoint instead of a client secret (RFC 7523 §2.2, OpenID Connect Core §9: client_secret_jwt and private_key_jwt).
Package clientassertion builds the signed JWTs a client presents to an OAuth 2.0 token endpoint instead of a client secret (RFC 7523 §2.2, OpenID Connect Core §9: client_secret_jwt and private_key_jwt).
conformance/txharness
Package txharness runs an SSFgo Transmitter configured for the OpenID Foundation SSF conformance suite's CAEP Interoperability Profile Transmitter plan.
Package txharness runs an SSFgo Transmitter configured for the OpenID Foundation SSF conformance suite's CAEP Interoperability Profile Transmitter plan.
critical
Package critical implements the "crit" (Critical) Header Parameter check RFC 7515 §4.1.11 (JWS) and RFC 7516 §4.1.13 (JWE, which inherits the JWS rule) both require: a header must be rejected only if "crit" names a parameter the recipient doesn't actually understand and process — every other unrecognized member is ignored, never rejected (RFC 7515 §4.2/§4.3, RFC 7516 §4.2/§4.3).
Package critical implements the "crit" (Critical) Header Parameter check RFC 7515 §4.1.11 (JWS) and RFC 7516 §4.1.13 (JWE, which inherits the JWS rule) both require: a header must be rejected only if "crit" names a parameter the recipient doesn't actually understand and process — every other unrecognized member is ignored, never rejected (RFC 7515 §4.2/§4.3, RFC 7516 §4.2/§4.3).
doccheck command
Command doccheck builds the Go code in the documentation, so it cannot drift from the API it describes.
Command doccheck builds the Go code in the documentation, so it cannot drift from the API it describes.
doclint command
Command doclint reports exported identifiers of the public packages that have no doc comment: declarations, and the fields of exported structs (design rule 14).
Command doclint reports exported identifiers of the public packages that have no doc comment: declarations, and the fields of exported structs (design rule 14).
jose
Package jose implements the JWS and JWK primitives SSFgo needs to sign and verify Security Event Tokens: compact serialization; RSASSA-PKCS1-v1_5 and RSASSA-PSS with SHA-256, -384 and -512, ECDSA on P-256, P-384 and P-521, and EdDSA with Ed25519 — every asymmetric algorithm of RFC 7518 §3.1, and RFC 8037's; and public JWK / JWK Set parsing.
Package jose implements the JWS and JWK primitives SSFgo needs to sign and verify Security Event Tokens: compact serialization; RSASSA-PKCS1-v1_5 and RSASSA-PSS with SHA-256, -384 and -512, ECDSA on P-256, P-384 and P-521, and EdDSA with Ed25519 — every asymmetric algorithm of RFC 7518 §3.1, and RFC 8037's; and public JWK / JWK Set parsing.
jsonobj
Package jsonobj decodes a JSON object strictly: a member named twice is an error, not a value the last occurrence silently wins.
Package jsonobj decodes a JSON object strictly: a member named twice is an error, not a value the last occurrence silently wins.
peertext
Package peertext makes text from the other party — a Transmitter's error body, a Receiver's rejection, a header member of a SET anyone could push — safe to log, return or report to a hook: cut to a bound the caller names, with anything but printable ASCII replaced, so it can neither flood a log nor forge or disguise a line of one.
Package peertext makes text from the other party — a Transmitter's error body, a Receiver's rejection, a header member of a SET anyone could push — safe to log, return or report to a hook: cut to a bound the caller names, with anything but printable ASCII replaced, so it can neither flood a log nor forge or disguise a line of one.
setcodec
Package setcodec signs and verifies Security Event Tokens as profiled by SSF 1.0 §4.
Package setcodec signs and verifies Security Event Tokens as profiled by SSF 1.0 §4.
testcert
Package testcert makes throwaway TLS certificates for SSFgo's conformance harnesses.
Package testcert makes throwaway TLS certificates for SSFgo's conformance harnesses.
Package receiver is an embeddable SSF Receiver (OpenID Shared Signals Framework 1.0).
Package receiver is an embeddable SSF Receiver (OpenID Shared Signals Framework 1.0).
Package revocation turns the security events a Receiver gets into revoked tokens: a session revoked, an account disabled or purged, a SCIM resource deactivated or deleted.
Package revocation turns the security events a Receiver gets into revoked tokens: a session revoked, an account disabled or purged, a SCIM resource deactivated or deleted.
Package risc implements the event types of OpenID Risk Incident Sharing and Coordination 1.0 (RISC) on top of the Shared Signals Framework.
Package risc implements the event types of OpenID Risk Incident Sharing and Coordination 1.0 (RISC) on top of the Shared Signals Framework.
Package scim implements the SCIM events of RFC 9967 on top of the Shared Signals Framework: provisioning changes of a SCIM service provider — resources created, patched, replaced, deleted, activated and deactivated — feed membership changes, and the completion of asynchronous SCIM requests.
Package scim implements the SCIM events of RFC 9967 on top of the Shared Signals Framework: provisioning changes of a SCIM service provider — resources created, patched, replaced, deleted, activated and deactivated — feed membership changes, and the completion of asynchronous SCIM requests.
Package ssftest runs an SSF Transmitter or Receiver in-process, for testing an application that plays the other role.
Package ssftest runs an SSF Transmitter or Receiver in-process, for testing an application that plays the other role.
Package storage defines the persistence contracts SSFgo's roles depend on.
Package storage defines the persistence contracts SSFgo's roles depend on.
memstore
Package memstore is an in-memory implementation of SSFgo's storage contracts, for tests, examples and conformance runs.
Package memstore is an in-memory implementation of SSFgo's storage contracts, for tests, examples and conformance runs.
storagetest
Package storagetest is a contract test suite for implementations of SSFgo's storage interfaces.
Package storagetest is a contract test suite for implementations of SSFgo's storage interfaces.
sqlstore module
Package transmitter is an embeddable SSF Transmitter (OpenID Shared Signals Framework 1.0).
Package transmitter is an embeddable SSF Transmitter (OpenID Shared Signals Framework 1.0).

Jump to

Keyboard shortcuts

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