Go: package jose
Generated from the Go source by scripts/gen-docs.sh — do not edit; run it to regenerate. Canonical deep reference: pkg.go.dev/github.com/dnsid-ai/dnsid-go/jose. Guides and account setup: https://docs.dnsid.ai.
import "github.com/dnsid-ai/dnsid-go/jose"Package jose implements the DNSid JOSE profile: creating and verifying DNSid JWTs and compact JWS objects signed with an agent’s operational key.
The main entry type is Profile. A Profile combines an identity resolver (usually a dnsid.IdentityManager), a local agent domain, and a dnsid.KeyProvider. The resolver is required for verification; the local domain and key provider are required for signing. Config bounds token lifetime and clock skew; its zero value applies the profile defaults.
A typical round trip mints a JWT as the local agent and verifies a peer’s token by resolving the issuer’s DNSid identity record from DNS:
profile := jose.NewFromIdentityManagerKeyProvider(idm, jose.Config{})
token, err := profile.CreateJWT(jose.JWTOptions{Audience: "bob.example"})// ... send token to bob.example ...
vd, claims, err := profile.VerifyJWT(ctx, token, jose.VerifyJWTOptions{ExpectedAudience: "bob.example"})// At the receiving side, Bob must verify against its own expected audience.// vd identifies the verified issuer domain; claims holds the parsed JWT.CreateJWS and VerifyJWS provide the same flow for compact JWS over arbitrary payloads.
See https://docs.dnsid.ai for protocol guides and account setup.
Example
Example mints a DNSid JWT as agent.example and verifies it as relying-party.example, entirely offline.
package main
import ( "context" "crypto/tls" "encoding/json" "fmt" "time"
dnsid "github.com/dnsid-ai/dnsid-go" "github.com/dnsid-ai/dnsid-go/jose" dnsidlog "github.com/dnsid-ai/dnsid-go/log")
// The fakes below stand in for live DNS, HTTPS, and transparency-log lookups// so the example runs offline. In production, omit the With... options and// let the verifier resolve the issuer's published identity record.
type fakeDNSResolver struct { records map[string][]dnsid.TXTRecordRData}
func (r fakeDNSResolver) FetchTXT(_ context.Context, name string) ([]dnsid.TXTRecordRData, dnsid.DNSSECState, error) { return r.records[name], dnsid.DNSSECStateUnsigned, nil}
type fakeHTTPSFetcher struct { responses map[string]json.RawMessage}
func (f fakeHTTPSFetcher) FetchJSON(_ context.Context, rawURL string, _ dnsid.FetchOptions) (json.RawMessage, *tls.Certificate, error) { return f.responses[rawURL], nil, nil}
type fakeLogReader struct{}
func (fakeLogReader) Canonical(dnsidlog.LogEvent) ([]byte, error) { return nil, nil }func (fakeLogReader) KeyTimestamp(context.Context, string, string) (time.Time, error) { return time.Now(), nil}func (fakeLogReader) VerifyBilateralBinding(context.Context, dnsidlog.BilateralBindingInput) (dnsidlog.BilateralBinding, error) { return dnsidlog.BilateralBinding{}, nil}func (fakeLogReader) VerifyOperationalContinuity(context.Context, string, string, string) error { return nil}func (fakeLogReader) VerifyGovernanceRelationship(context.Context, string, string) error { return nil }func (fakeLogReader) VerifyNonRevocation(context.Context, string, time.Time) (dnsidlog.LoggedStateEvidence, error) { return dnsidlog.LoggedStateEvidence{}, nil}func (fakeLogReader) ReadEvent(context.Context, dnsidlog.LogRef) (dnsidlog.LogEvent, error) { return dnsidlog.LogEvent{}, nil}func (fakeLogReader) RebuildHistory(context.Context, string) ([]dnsidlog.LogEvent, error) { return nil, nil}
// Example mints a DNSid JWT as agent.example and verifies it as// relying-party.example, entirely offline.func main() { // The agent's identity: its domain, governing organization, entity // record-signing key, and operational key. agentKey := dnsid.GenerateES256KeyProvider() issuer, err := dnsid.NewIdentityManager(dnsid.Config{Identity: &dnsid.IdentityConfig{ Domain: "agent.example", GovernanceID: "agent.example", LogRef: "algorand:ADDR", StatusURL: "https://agent.example/.well-known/dnsid/status.json", KeyURL: "https://agent.example/ku.json", EntityKeyURL: "https://agent.example/ek.json", }}, agentKey, dnsid.WithEntityKeyProvider(dnsid.GenerateES256KeyProvider())) if err != nil { panic(err) }
// Publish the agent's identity record and key sets into the offline // fakes, exactly as they would appear in DNS and over HTTPS. record, err := issuer.CreateTXTRecord() if err != nil { panic(err) } jwksBytes, err := json.Marshal(issuer.GetKeySet().Raw()) if err != nil { panic(err) } entityBytes, err := json.Marshal(issuer.GetEntityKeySet().Raw()) if err != nil { panic(err) } registry := dnsidlog.NewLogRegistry() if err := registry.Register("algorand", func(string) dnsidlog.LogReader { return fakeLogReader{} }); err != nil { panic(err) }
// The relying party's manager resolves the agent's identity from the // fakes above. verifier, err := dnsid.NewIdentityManager(dnsid.Config{Identity: &dnsid.IdentityConfig{ Domain: "relying-party.example", GovernanceID: "relying-party.example", LogRef: "algorand:ADDR", StatusURL: "https://relying-party.example/.well-known/dnsid/status.json", }}, dnsid.GenerateES256KeyProvider(), dnsid.WithDNSResolver(fakeDNSResolver{records: map[string][]dnsid.TXTRecordRData{ "_dnsid.agent.example": {{Value: record.Serialize(), TTL: time.Minute}}, }}), dnsid.WithHTTPSFetcher(fakeHTTPSFetcher{responses: map[string]json.RawMessage{ record.KeyURI: jwksBytes, record.EntityKeyURI: entityBytes, record.StatusURI: json.RawMessage(`{"state":"ACTIVE","lastTransitionAt":"` + time.Now().UTC().Format(time.RFC3339Nano) + `"}`), }}), dnsid.WithLogRegistry(registry), ) if err != nil { panic(err) }
// Mint a JWT as the agent. issuerProfile := jose.NewFromIdentityManager(issuer, agentKey, jose.Config{}) token, err := issuerProfile.CreateJWT(jose.JWTOptions{ Audience: "relying-party.example", AdditionalClaims: map[string]any{"purpose": "quickstart"}, }) if err != nil { panic(err) }
// Verify it as the relying party. verifierProfile := jose.NewFromIdentityManager(verifier, nil, jose.Config{}) vd, claims, err := verifierProfile.VerifyJWT(context.Background(), token) if err != nil { panic(err) }
fmt.Println("verified domain:", vd.Domain()) fmt.Println("issuer:", claims.Issuer) fmt.Println("audience:", claims.Audiences[0]) fmt.Println("purpose:", claims.Extra["purpose"])}Output
Section titled “Output”verified domain: agent.exampleissuer: agent.exampleaudience: relying-party.examplepurpose: quickstart- type Claims
- type Config
- type JWTOptions
- type Profile
- func New(resolver dnsid.IdentityResolver, localDomain string, kp dnsid.KeyProvider, cfg Config) *Profile
- func NewFromIdentityManager(manager identityManager, kp dnsid.KeyProvider, cfg Config) *Profile
- func NewFromIdentityManagerKeyProvider(manager identityManagerWithKeyProvider, cfg Config) *Profile
- func (p *Profile) CreateJWS(payload []byte) (string, error)
- func (p *Profile) CreateJWT(opts JWTOptions) (string, error)
- func (p *Profile) VerifyJWS(ctx context.Context, compact string, opts …dnsid.VerifyDomainOpts) ([]byte, *dnsid.VerifiedDomain, error)
- func (p *Profile) VerifyJWT(ctx context.Context, tokenStr string, opts …VerifyJWTOptions) (*dnsid.VerifiedDomain, *Claims, error)
- type VerifyJWTOptions
Claims holds the validated claims of a verified DNSid JWT.
type Claims struct { // Issuer is the token's iss claim, normalized to a FQDN. Issuer string
// Subject is the token's sub claim, normalized to a FQDN. The DNSid // JOSE profile requires it to equal Issuer. Subject string
// Audiences is the token's aud claim with each entry normalized to a // FQDN. Audiences []string
// JWTID is the token's jti claim. JWTID string
// IssuedAt is the token's iat claim. IssuedAt time.Time
// Expiry is the token's exp claim. Expiry time.Time
// Extra holds the token's private (non-registered) claims. Extra map[string]any}Config contains JOSE/JWT/JWS profile policy. The zero value applies the profile defaults.
type Config struct { // MaxLifetime caps the validity window (exp - iat) of created and // verified JWTs. Zero means omitted (15 minutes); negatives are invalid. MaxLifetime time.Duration
// ClockSkew is the tolerance applied to time-based claim checks during // verification. Zero means omitted (60 seconds); WithClockSkew(0) // specifies zero tolerance. Skew never extends expiration. ClockSkew time.Duration // contains filtered or unexported fields}func (c Config) WithClockSkew(skew time.Duration) ConfigWithClockSkew specifies tolerance, including explicit zero.
func (c Config) WithMaxLifetime(lifetime time.Duration) ConfigWithMaxLifetime specifies a positive maximum lifetime.
JWTOptions configures JWT creation.
type JWTOptions struct { // Audience is the token's aud claim. It is required and must normalize // to a valid FQDN. Audience string
// Expiry is the requested positive lifetime, capped by Config.MaxLifetime. // A zero struct field means omitted (15 minutes); WithExpiry records // explicit presence and rejects zero. Negative lifetimes are invalid. Expiry time.Duration
// AdditionalClaims holds private claims to embed in the token. The // registered claim names iss, sub, aud, exp, iat, nbf, and jti are // reserved; CreateJWT fails if any of them appear here. AdditionalClaims map[string]any // contains filtered or unexported fields}func (JWTOptions) WithExpiry
Section titled “func (JWTOptions) WithExpiry”func (o JWTOptions) WithExpiry(expiry time.Duration) JWTOptionsWithExpiry specifies an explicit positive lifetime; zero is rejected.
Profile implements the DNSid JOSE profile on top of core DNSid identity verification.
type Profile struct { // contains filtered or unexported fields}func New(resolver dnsid.IdentityResolver, localDomain string, kp dnsid.KeyProvider, cfg Config) *ProfileNew constructs a JOSE profile. localDomain and kp are required for create/sign operations. Invalid lifetime/skew configuration is rejected when used.
func NewFromIdentityManager(manager identityManager, kp dnsid.KeyProvider, cfg Config) *ProfileNewFromIdentityManager constructs a JOSE profile from an IdentityManager-like core manager.
func NewFromIdentityManagerKeyProvider(manager identityManagerWithKeyProvider, cfg Config) *ProfileNewFromIdentityManagerKeyProvider constructs a JOSE profile from a manager that exposes its KeyProvider.
func (*Profile) CreateJWS
Section titled “func (*Profile) CreateJWS”func (p *Profile) CreateJWS(payload []byte) (string, error)CreateJWS creates a compact JWS over payload using this profile’s active key.
func (*Profile) CreateJWT
Section titled “func (*Profile) CreateJWT”func (p *Profile) CreateJWT(opts JWTOptions) (string, error)CreateJWT produces a DNSid JOSE-profile JWT signed by this profile’s active key.
func (*Profile) VerifyJWS
Section titled “func (*Profile) VerifyJWS”func (p *Profile) VerifyJWS(ctx context.Context, compact string, opts ...dnsid.VerifyDomainOpts) ([]byte, *dnsid.VerifiedDomain, error)VerifyJWS verifies compact JWS bytes, passing optional trusted current-peer evidence through core DNSid verification. Payload bytes remain opaque.
func (*Profile) VerifyJWT
Section titled “func (*Profile) VerifyJWT”func (p *Profile) VerifyJWT(ctx context.Context, tokenStr string, opts ...VerifyJWTOptions) (*dnsid.VerifiedDomain, *Claims, error)VerifyJWT verifies a DNSid JOSE-profile JWT through core domain verification.
VerifyJWTOptions configures JWT verification.
type VerifyJWTOptions struct { // ExpectedAudience is the audience that must appear in the token's aud // claim. Empty means the profile's local domain; verification fails if // both are empty. ExpectedAudience string
// ExpectedIssuer, when non-empty, requires the token's iss claim to // match this domain after FQDN normalization. ExpectedIssuer string
// Peer supplies trusted current application-peer evidence, never endpoint certificates. Peer dnsid.VerifyDomainOpts}Generated by gomarkdoc