agentauth

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jun 28, 2026 License: MIT Imports: 13 Imported by: 0

README

AgentAuth

Go CI Go Lint Go SAST Go Report Card Docs Docs Visualization License

Layered identity composition for AI agents, combining AAuth, ID-JAG, and SPIFFE.

Overview

AgentAuth provides a composition layer for AI agent authentication that properly combines three complementary identity protocols:

Protocol Identity Layer Purpose
AAuth Agent "Which autonomous agent is this? What mission is it executing?"
ID-JAG Human "Which user is this agent acting for?"
SPIFFE Workload "Which workload/service is hosting this?"

These protocols operate at different layers and should be composed, not chosen between.

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        Human Identity                           │
│  OIDC / SAML / Enterprise IdP                                   │
│  ID-JAG (delegated user identity for cross-app access)          │
└──────────────────────────┬──────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                        Agent Identity                           │
│  AAuth Protocol                                                 │
│  agent_id, mission_id, delegation, subagents                    │
│  HTTP Message Signatures, Proof-of-Possession                   │
└──────────────────────────┬──────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                      Workload Identity                          │
│  SPIFFE/SPIRE, mTLS                                             │
│  spiffe://domain/path                                           │
└──────────────────────────┬──────────────────────────────────────┘
                           │
                           ▼
                    Protected Resources

Installation

go get github.com/plexusone/agentauth

Usage

Composed Identity

The core abstraction is ComposedIdentity, which links all three identity layers:

import "github.com/plexusone/agentauth/identity"

// Create a composer with verifiers
composer := identity.NewComposer(
    identity.WithAAuthVerifier(aauthVerifier),
    identity.WithIDJAGVerifier(idjagVerifier),
    identity.WithWorkloadVerifier(spiffeVerifier),
)

// Compose identities from credentials
composed, err := composer.Compose(ctx, identity.ComposeOptions{
    AAuthToken:     aauthToken,
    IDJAGAssertion: idjagAssertion,
    IncludeWorkload: true,
})

// Use composed identity for authorization decisions
fmt.Println(composed.AuditString())
// Output: agent:research-agent for-human:alice@example.com on-workload:spiffe://prod/research binding:bind-xyz
Context Integration
// Store identity in context
ctx = identity.WithContext(ctx, composed)

// Later, retrieve it
if id, ok := identity.FromContext(ctx); ok {
    log.Info("processing request",
        "agent", id.Agent.AgentID,
        "user", id.Human.Subject,
        "workload", id.Workload.SPIFFEID,
    )
}
Storage
import "github.com/plexusone/agentauth/store"

// Create SQLite store
db, err := store.NewSQLite("auth.db")

// Create mission (AAuth)
mission := &store.Mission{
    AgentID:         "research-agent",
    UserID:          "user-123",
    Name:            "Research Task",
    Scopes:          "read:docs write:notes",
    InteractionType: "supervised",
}
err = db.CreateMission(ctx, mission)
Token Verification (Server-Side)

The TokenVerifier provides multi-protocol token verification with action-based routing:

import "github.com/plexusone/agentauth"

// Configure token verification
config := &agentauth.VerifierConfig{
    IDJAGEnabled: true,
    AAuthEnabled: true,
    IDJAGIssuers: map[string]string{
        "https://issuer.example.com": "", // Auto-discovers JWKS
    },
    AAuthIssuers: map[string]string{
        "https://consent.example.com": "",
    },
    SensitiveActions: []string{"write", "delete", "admin"},
}

verifier := agentauth.NewTokenVerifier(config)

// Verify token (tries both protocols)
claims, err := verifier.Verify(ctx, token)

// Verify with action checking (requires AAuth for sensitive actions)
claims, err := verifier.VerifyForAction(ctx, token, "delete:resource")
if err != nil {
    // Returns error if action requires AAuth but token is ID-JAG
}
Hybrid Provider (Protocol Routing)

The HybridProvider routes authorization requests to ID-JAG or AAuth based on policies:

import "github.com/plexusone/agentauth"

// Configure hybrid provider
config := &agentauth.Config{
    Policy: &agentauth.PolicyConfig{
        Default:   agentauth.ProtocolIDJAG, // Use ID-JAG by default
        Sensitive: agentauth.ProtocolAAuth, // Require AAuth for sensitive scopes
        Rules: map[string]agentauth.Protocol{
            "admin:*":  agentauth.ProtocolAAuth,
            "write:*":  agentauth.ProtocolAAuth,
            "read:*":   agentauth.ProtocolIDJAG,
        },
    },
}

provider, err := agentauth.NewHybridProvider(config,
    agentauth.WithIDJAGProvider(idjagProvider),
    agentauth.WithAAuthProvider(aauthProvider),
)

// Authorization is routed based on scopes
result, err := provider.Authorize(ctx, &agentauth.AuthRequest{
    Resource: "https://api.example.com",
    Scopes:   []string{"read:email"},  // Routes to ID-JAG
})

result, err := provider.Authorize(ctx, &agentauth.AuthRequest{
    Resource: "https://api.example.com",
    Scopes:   []string{"write:profile"},  // Routes to AAuth (requires consent)
})
Agent SDK Client

The client package provides an SDK for agents to authenticate:

import "github.com/plexusone/agentauth/client"

// Create client
c := client.New("https://authz.example.com",
    client.WithPollTimeout(5 * time.Minute),
)

// ID-JAG token exchange (RFC 8693 - automated)
token, err := c.ExchangeIDJAG(ctx, idjagAssertion, "read:email read:profile")

// JWT bearer grant (RFC 7523)
token, err := c.ExchangeJWTBearer(ctx, jwtAssertion, "read:data")

// AAuth flow (human consent required)
result, err := c.RequestAuthorization(ctx, &client.AuthorizationRequest{
    AgentToken:  agentToken,
    UserID:      "user-123",
    Scopes:      "write:profile",
    MissionName: "Update User Profile",
})

if result.Status == "pending" {
    // Direct user to result.ConsentURI for approval
    fmt.Println("Please approve at:", result.ConsentURI)

    // Wait for consent (blocks until approved/denied/timeout)
    token, err := c.WaitForConsent(ctx, result.StatusURI)
}

Package Structure

plexusone/agentauth/
├── identity/          # Layered identity composition
│   ├── types.go       # ComposedIdentity, HumanIdentity, AgentIdentity, WorkloadIdentity
│   └── composer.go    # Identity composer
├── store/             # Storage abstractions
│   ├── interface.go   # Storer interface
│   ├── types.go       # User, Agent, Mission, Token, etc.
│   └── sqlite.go      # SQLite implementation
├── client/            # Agent SDK for authentication
│   └── client.go      # Token exchange, consent flow
├── verifier.go        # Multi-protocol token verifier
├── hybrid.go          # HybridProvider for protocol routing
├── policy.go          # PolicyMatcher for scope-based routing
├── cmd/               # Server binaries
├── lambda/            # AWS Lambda handlers
└── docs/
    └── specs/
        └── ROADMAP.md # Implementation roadmap

Key Concepts

ComposedIdentity

Links all three identity layers with a unique binding:

  • BindingID: Unique identifier for this composed identity
  • BoundAt: When the identities were linked
  • ExpiresAt: Earliest expiration of component identities
  • TraceID: For distributed tracing
Identity Layers
  1. Human Identity (ID-JAG): User the agent acts for
  2. Agent Identity (AAuth): The autonomous agent with its mission
  3. Workload Identity (SPIFFE): Infrastructure hosting the agent
Request Flow
  1. Agent sends request with:

    • AAuth token (agent identity)
    • ID-JAG assertion (human identity)
    • mTLS with SVID (workload identity)
  2. Server composes identities:

    • Verify AAuth token → AgentIdentity
    • Verify ID-JAG assertion → HumanIdentity
    • Extract SPIFFE ID from TLS → WorkloadIdentity
    • Create ComposedIdentity with binding
  3. Authorization decision uses all three:

    • "Agent X acting for Human Y on Workload Z"
    • Full audit trail with all identities linked

License

MIT License

Documentation

Overview

Package agentauth provides a unified authorization layer for AI agents. It abstracts the underlying protocols (ID-JAG, AAuth) and provides policy-based routing to determine which protocol to use for each request.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrConsentRequired indicates human consent is needed.
	ErrConsentRequired = errors.New("human consent required")

	// ErrConsentDenied indicates consent was denied.
	ErrConsentDenied = errors.New("consent denied")

	// ErrConsentTimeout indicates consent polling timed out.
	ErrConsentTimeout = errors.New("consent timeout")

	// ErrUnauthorized indicates authorization failed.
	ErrUnauthorized = errors.New("unauthorized")

	// ErrProviderNotConfigured indicates the required provider is not configured.
	ErrProviderNotConfigured = errors.New("provider not configured")
)

Provider errors.

Functions

func IsJWT

func IsJWT(s string) bool

IsJWT checks if a string looks like a JWT (3 dot-separated parts).

Types

type AAuthConfig

type AAuthConfig struct {
	// Enabled enables AAuth authorization.
	Enabled bool `json:"enabled" yaml:"enabled"`

	// AgentID is the AAuth agent identifier (e.g., "aauth:agent@example.com").
	AgentID string `json:"agent_id" yaml:"agent_id"`

	// PersonServer is the Person Server URL.
	PersonServer string `json:"person_server" yaml:"person_server"`

	// PrivateKey is the path/URI to the private key.
	PrivateKey string `json:"private_key" yaml:"private_key"`

	// KeyID is the key identifier.
	KeyID string `json:"key_id,omitempty" yaml:"key_id,omitempty"`

	// Algorithm is the signing algorithm (default: ES256).
	Algorithm string `json:"algorithm,omitempty" yaml:"algorithm,omitempty"`

	// DefaultAudience is the default audience for tokens.
	DefaultAudience []string `json:"default_audience,omitempty" yaml:"default_audience,omitempty"`

	// DefaultInteractionType is the default interaction type.
	DefaultInteractionType string `json:"default_interaction_type,omitempty" yaml:"default_interaction_type,omitempty"`

	// DefaultMissionDuration is the default mission duration.
	DefaultMissionDuration time.Duration `json:"default_mission_duration,omitempty" yaml:"default_mission_duration,omitempty"`
}

AAuthConfig configures the AAuth provider.

func (*AAuthConfig) Validate

func (c *AAuthConfig) Validate() error

Validate validates the AAuth configuration.

type AAuthProvider

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

AAuthProvider implements Provider using AAuth protocol.

func NewAAuthProvider

func NewAAuthProvider(config *AAuthConfig, opts ...AAuthProviderOption) (*AAuthProvider, error)

NewAAuthProvider creates a new AAuth provider.

func (*AAuthProvider) Authorize

func (p *AAuthProvider) Authorize(ctx context.Context, req *AuthRequest) (*AuthResult, error)

Authorize submits a mission proposal and handles consent flow.

func (*AAuthProvider) CheckConsent

func (p *AAuthProvider) CheckConsent(ctx context.Context, statusURI string) (*AuthResult, error)

CheckConsent checks the status of a pending consent request.

func (*AAuthProvider) HTTPClient

func (p *AAuthProvider) HTTPClient(ctx context.Context, req *AuthRequest) (*http.Client, error)

HTTPClient returns an HTTP client with automatic AAuth authorization.

func (*AAuthProvider) InitializeAgent

func (p *AAuthProvider) InitializeAgent(privateKey crypto.PrivateKey) error

InitializeAgent initializes the AAuth agent from config.

func (*AAuthProvider) Protocol

func (p *AAuthProvider) Protocol() Protocol

Protocol returns ProtocolAAuth.

func (*AAuthProvider) Revoke

func (p *AAuthProvider) Revoke(ctx context.Context, token string) error

Revoke revokes an AAuth authorization.

func (*AAuthProvider) SetAgent

func (p *AAuthProvider) SetAgent(agent *aauth.Agent)

SetAgent sets the AAuth agent (for deferred initialization).

func (*AAuthProvider) WaitForConsent

func (p *AAuthProvider) WaitForConsent(ctx context.Context, statusURI string, timeout time.Duration) (*AuthResult, error)

WaitForConsent polls for consent approval with timeout.

type AAuthProviderOption

type AAuthProviderOption func(*AAuthProvider)

AAuthProviderOption configures the AAuthProvider.

func WithAAuthAgent

func WithAAuthAgent(agent *aauth.Agent) AAuthProviderOption

WithAAuthAgent sets the AAuth agent directly.

func WithAAuthConsentMode

func WithAAuthConsentMode(mode ConsentMode) AAuthProviderOption

WithAAuthConsentMode sets the consent flow mode.

func WithAAuthPollConfig

func WithAAuthPollConfig(interval, timeout time.Duration) AAuthProviderOption

WithAAuthPollConfig sets polling configuration.

type ActorClaims

type ActorClaims struct {
	// Subject is the actor's identifier (e.g., user ID).
	Subject string `json:"sub"`

	// Issuer is the actor's identity provider.
	Issuer string `json:"iss,omitempty"`
}

ActorClaims represents the actor in a delegation token.

type AuthRequest

type AuthRequest struct {
	// Scopes are the requested scopes.
	Scopes []string `json:"scopes"`

	// Resource is the target resource (optional).
	Resource string `json:"resource,omitempty"`

	// Audience is the intended audience (optional).
	Audience []string `json:"audience,omitempty"`

	// Subject is the subject being represented (for delegation).
	Subject string `json:"subject,omitempty"`

	// MissionName is a human-readable name for the mission (AAuth).
	MissionName string `json:"mission_name,omitempty"`

	// MissionDescription describes what the agent will do (AAuth).
	MissionDescription string `json:"mission_description,omitempty"`

	// Duration is the requested authorization duration.
	Duration time.Duration `json:"duration,omitempty"`

	// InteractionType is the AAuth interaction type.
	InteractionType string `json:"interaction_type,omitempty"`

	// RedirectURI is the callback URI for consent flow.
	RedirectURI string `json:"redirect_uri,omitempty"`

	// State is an opaque value for CSRF protection.
	State string `json:"state,omitempty"`

	// ForceProtocol overrides policy-based protocol selection.
	ForceProtocol Protocol `json:"force_protocol,omitempty"`

	// Metadata contains additional request metadata.
	Metadata map[string]any `json:"metadata,omitempty"`
}

AuthRequest contains the parameters for an authorization request.

type AuthResult

type AuthResult struct {
	// Status is the authorization status.
	Status AuthStatus `json:"status"`

	// Protocol indicates which protocol was used.
	Protocol Protocol `json:"protocol"`

	// Token is the access token (if approved).
	Token string `json:"token,omitempty"`

	// TokenType is the token type (e.g., "Bearer", "DPoP").
	TokenType string `json:"token_type,omitempty"`

	// ExpiresAt is when the token expires.
	ExpiresAt time.Time `json:"expires_at,omitempty"`

	// Scopes are the granted scopes.
	Scopes []string `json:"scopes,omitempty"`

	// ConsentURI is the URI for human consent (if pending).
	ConsentURI string `json:"consent_uri,omitempty"`

	// StatusURI is the URI to poll for consent status.
	StatusURI string `json:"status_uri,omitempty"`

	// PollInterval is the recommended polling interval.
	PollInterval time.Duration `json:"poll_interval,omitempty"`

	// Message is a human-readable message.
	Message string `json:"message,omitempty"`

	// Metadata contains protocol-specific metadata.
	Metadata map[string]any `json:"metadata,omitempty"`
}

AuthResult contains the result of an authorization request.

func (*AuthResult) IsApproved

func (r *AuthResult) IsApproved() bool

IsApproved returns true if authorization was granted.

func (*AuthResult) IsPending

func (r *AuthResult) IsPending() bool

IsPending returns true if human consent is pending.

type AuthStatus

type AuthStatus string

AuthStatus represents the status of an authorization request.

const (
	StatusApproved AuthStatus = "approved"
	StatusPending  AuthStatus = "pending"
	StatusDenied   AuthStatus = "denied"
	StatusExpired  AuthStatus = "expired"
)

Authorization statuses.

type CacheConfig

type CacheConfig struct {
	// Enabled enables token caching.
	Enabled bool `json:"enabled" yaml:"enabled"`

	// TTL is the cache TTL (default: token expiry - 1 minute).
	TTL time.Duration `json:"ttl,omitempty" yaml:"ttl,omitempty"`

	// MaxSize is the maximum cache size.
	MaxSize int `json:"max_size,omitempty" yaml:"max_size,omitempty"`
}

CacheConfig configures token caching.

type Config

type Config struct {
	// AgentID is the agent's identifier.
	AgentID string `json:"agent_id" yaml:"agent_id"`

	// Policy defines authorization routing rules.
	Policy *Policy `json:"policy" yaml:"policy"`

	// IDJAG is the ID-JAG provider configuration.
	IDJAG *IDJAGConfig `json:"idjag,omitempty" yaml:"idjag,omitempty"`

	// AAuth is the AAuth provider configuration.
	AAuth *AAuthConfig `json:"aauth,omitempty" yaml:"aauth,omitempty"`

	// Consent configures the consent flow.
	Consent *ConsentConfig `json:"consent,omitempty" yaml:"consent,omitempty"`

	// Cache configures token caching.
	Cache *CacheConfig `json:"cache,omitempty" yaml:"cache,omitempty"`
}

Config is the main configuration for the agentauth package.

func DefaultConfig

func DefaultConfig(agentID string) *Config

DefaultConfig returns a default configuration.

func (*Config) Validate

func (c *Config) Validate() error

Validate validates the configuration.

type ConsentConfig

type ConsentConfig struct {
	// Mode is the consent flow mode.
	Mode ConsentMode `json:"mode" yaml:"mode"`

	// RedirectURI is the callback URI for redirect flow.
	RedirectURI string `json:"redirect_uri,omitempty" yaml:"redirect_uri,omitempty"`

	// ListenAddr is the address for the callback server (redirect flow).
	ListenAddr string `json:"listen_addr,omitempty" yaml:"listen_addr,omitempty"`

	// PollInterval is the polling interval for deferred flow.
	PollInterval time.Duration `json:"poll_interval,omitempty" yaml:"poll_interval,omitempty"`

	// PollTimeout is the maximum time to wait for consent.
	PollTimeout time.Duration `json:"poll_timeout,omitempty" yaml:"poll_timeout,omitempty"`

	// ShowQRCode shows a QR code for the consent URI (CLI).
	ShowQRCode bool `json:"show_qr_code,omitempty" yaml:"show_qr_code,omitempty"`

	// OpenBrowser automatically opens the consent URI in a browser.
	OpenBrowser bool `json:"open_browser,omitempty" yaml:"open_browser,omitempty"`

	// OnConsentRequired is called when consent is required.
	// Allows custom UI handling.
	OnConsentRequired func(consentURI string) `json:"-" yaml:"-"`
}

ConsentConfig configures the consent flow.

type ConsentHandler

type ConsentHandler interface {
	// StartConsent initiates a consent flow.
	// Returns the consent URI for the user to visit.
	StartConsent(ctx context.Context, req *AuthRequest) (consentURI string, state string, err error)

	// HandleCallback handles the consent callback.
	HandleCallback(ctx context.Context, code, state string) (*AuthResult, error)

	// ServeHTTP handles HTTP callbacks (implements http.Handler).
	ServeHTTP(w http.ResponseWriter, r *http.Request)
}

ConsentHandler handles interactive consent flows.

type ConsentMode

type ConsentMode string

ConsentMode defines how consent is handled.

const (
	// ConsentModeRedirect uses OAuth-style redirect flow.
	ConsentModeRedirect ConsentMode = "redirect"

	// ConsentModeDeferred uses polling-based deferred consent.
	ConsentModeDeferred ConsentMode = "deferred"

	// ConsentModeDevice uses device authorization flow.
	ConsentModeDevice ConsentMode = "device"
)

Consent modes.

type HybridProvider

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

HybridProvider routes authorization requests to the appropriate provider based on policy configuration.

func NewHybridProvider

func NewHybridProvider(config *Config, opts ...HybridProviderOption) (*HybridProvider, error)

NewHybridProvider creates a new hybrid provider.

func (*HybridProvider) Authorize

func (h *HybridProvider) Authorize(ctx context.Context, req *AuthRequest) (*AuthResult, error)

Authorize routes the request to the appropriate provider based on policy.

func (*HybridProvider) CheckConsent

func (h *HybridProvider) CheckConsent(ctx context.Context, statusURI string) (*AuthResult, error)

CheckConsent delegates to the appropriate provider.

func (*HybridProvider) ClearCache

func (h *HybridProvider) ClearCache()

ClearCache clears the token cache.

func (*HybridProvider) GetProviderForScopes

func (h *HybridProvider) GetProviderForScopes(scopes []string) (Protocol, Provider)

GetProviderForScopes returns which provider would be used for the given scopes.

func (*HybridProvider) HTTPClient

func (h *HybridProvider) HTTPClient(ctx context.Context, req *AuthRequest) (*http.Client, error)

HTTPClient returns an HTTP client with automatic authorization.

func (*HybridProvider) PolicyMatcher

func (h *HybridProvider) PolicyMatcher() *PolicyMatcher

PolicyMatcher returns the policy matcher for inspection.

func (*HybridProvider) Protocol

func (h *HybridProvider) Protocol() Protocol

Protocol returns the hybrid protocol identifier.

func (*HybridProvider) Revoke

func (h *HybridProvider) Revoke(ctx context.Context, token string) error

Revoke revokes an authorization.

func (*HybridProvider) WaitForConsent

func (h *HybridProvider) WaitForConsent(ctx context.Context, statusURI string, timeout time.Duration) (*AuthResult, error)

WaitForConsent polls for consent approval.

type HybridProviderOption

type HybridProviderOption func(*HybridProvider)

HybridProviderOption configures the HybridProvider.

func WithAAuthProvider

func WithAAuthProvider(p Provider) HybridProviderOption

WithAAuthProvider sets the AAuth provider.

func WithIDJAGProvider

func WithIDJAGProvider(p Provider) HybridProviderOption

WithIDJAGProvider sets the ID-JAG provider.

type IDJAGConfig

type IDJAGConfig struct {
	// Enabled enables ID-JAG authorization.
	Enabled bool `json:"enabled" yaml:"enabled"`

	// Issuer is the assertion issuer (agent's identity).
	Issuer string `json:"issuer" yaml:"issuer"`

	// TokenEndpoint is the authorization server's token endpoint.
	TokenEndpoint string `json:"token_endpoint" yaml:"token_endpoint"`

	// PrivateKey is the path/URI to the private key for signing.
	// Supports: file path, vault URI (op://, bw://), env:// prefix.
	PrivateKey string `json:"private_key" yaml:"private_key"`

	// KeyID is the key identifier.
	KeyID string `json:"key_id,omitempty" yaml:"key_id,omitempty"`

	// Algorithm is the signing algorithm (default: ES256).
	Algorithm string `json:"algorithm,omitempty" yaml:"algorithm,omitempty"`

	// DefaultAudience is the default audience for assertions.
	DefaultAudience []string `json:"default_audience,omitempty" yaml:"default_audience,omitempty"`

	// AssertionTTL is the assertion lifetime (default: 5m).
	AssertionTTL time.Duration `json:"assertion_ttl,omitempty" yaml:"assertion_ttl,omitempty"`
}

IDJAGConfig configures the ID-JAG provider.

func (*IDJAGConfig) Validate

func (c *IDJAGConfig) Validate() error

Validate validates the ID-JAG configuration.

type IDJAGProvider

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

IDJAGProvider implements Provider using ID-JAG protocol.

func NewIDJAGProvider

func NewIDJAGProvider(config *IDJAGConfig, opts ...IDJAGProviderOption) (*IDJAGProvider, error)

NewIDJAGProvider creates a new ID-JAG provider.

func (*IDJAGProvider) Authorize

func (p *IDJAGProvider) Authorize(ctx context.Context, req *AuthRequest) (*AuthResult, error)

Authorize creates an assertion and exchanges it for an access token.

func (*IDJAGProvider) CheckConsent

func (p *IDJAGProvider) CheckConsent(ctx context.Context, statusURI string) (*AuthResult, error)

CheckConsent is not used by ID-JAG (no human consent flow).

func (*IDJAGProvider) HTTPClient

func (p *IDJAGProvider) HTTPClient(ctx context.Context, req *AuthRequest) (*http.Client, error)

HTTPClient returns an HTTP client with automatic ID-JAG authorization.

func (*IDJAGProvider) Protocol

func (p *IDJAGProvider) Protocol() Protocol

Protocol returns ProtocolIDJAG.

func (*IDJAGProvider) Revoke

func (p *IDJAGProvider) Revoke(ctx context.Context, token string) error

Revoke revokes a token (if supported by the authorization server).

func (*IDJAGProvider) SetPrivateKey

func (p *IDJAGProvider) SetPrivateKey(key crypto.PrivateKey)

SetPrivateKey sets the private key (for deferred initialization).

func (*IDJAGProvider) WaitForConsent

func (p *IDJAGProvider) WaitForConsent(ctx context.Context, statusURI string, timeout time.Duration) (*AuthResult, error)

WaitForConsent is not used by ID-JAG.

type IDJAGProviderOption

type IDJAGProviderOption func(*IDJAGProvider)

IDJAGProviderOption configures the IDJAGProvider.

func WithIDJAGHTTPClient

func WithIDJAGHTTPClient(client *http.Client) IDJAGProviderOption

WithIDJAGHTTPClient sets a custom HTTP client.

func WithIDJAGPrivateKey

func WithIDJAGPrivateKey(key crypto.PrivateKey) IDJAGProviderOption

WithIDJAGPrivateKey sets the private key directly.

type Policy

type Policy struct {
	// Mode is the overall policy mode.
	Mode PolicyMode `json:"mode" yaml:"mode"`

	// DefaultProtocol is used when no scope policy matches (hybrid mode).
	DefaultProtocol Protocol `json:"default_protocol" yaml:"default_protocol"`

	// ScopePolicies define per-scope authorization rules.
	ScopePolicies []ScopePolicy `json:"scope_policies,omitempty" yaml:"scope_policies,omitempty"`

	// SensitiveScopes always require AAuth/human consent.
	// Shorthand for adding AAuth policies for each scope.
	SensitiveScopes []string `json:"sensitive_scopes,omitempty" yaml:"sensitive_scopes,omitempty"`

	// AutoScopes always use ID-JAG/automatic authorization.
	// Shorthand for adding ID-JAG policies for each scope.
	AutoScopes []string `json:"auto_scopes,omitempty" yaml:"auto_scopes,omitempty"`
}

Policy defines authorization policies for scope routing.

func DefaultPolicy

func DefaultPolicy() *Policy

DefaultPolicy returns a sensible default policy.

type PolicyMatcher

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

PolicyMatcher matches scopes to policies.

func NewPolicyMatcher

func NewPolicyMatcher(policy *Policy) *PolicyMatcher

NewPolicyMatcher creates a new policy matcher.

func (*PolicyMatcher) GetScopePolicy

func (m *PolicyMatcher) GetScopePolicy(scope string) *ScopePolicy

GetScopePolicy returns the policy for a specific scope.

func (*PolicyMatcher) Match

func (m *PolicyMatcher) Match(scopes []string) Protocol

Match returns the protocol for a set of scopes. If any scope requires AAuth, AAuth is returned. If all scopes match auto policies, IDJAG is returned.

func (*PolicyMatcher) RequiresConsent

func (m *PolicyMatcher) RequiresConsent(scopes []string) bool

RequiresConsent returns true if any scope requires human consent.

func (*PolicyMatcher) SplitByProtocol

func (m *PolicyMatcher) SplitByProtocol(scopes []string) (auto, human []string)

SplitByProtocol splits scopes into auto and human-required groups.

type PolicyMode

type PolicyMode string

PolicyMode determines how authorization requests are routed.

const (
	// PolicyModeAuto uses ID-JAG for all requests (no human interaction).
	PolicyModeAuto PolicyMode = "auto"

	// PolicyModeHuman uses AAuth for all requests (always human consent).
	PolicyModeHuman PolicyMode = "human"

	// PolicyModeHybrid routes based on scope policies.
	PolicyModeHybrid PolicyMode = "hybrid"
)

Policy modes.

type Protocol

type Protocol string

Protocol identifies the authorization protocol.

const (
	// ProtocolIDJAG uses ID-JAG for policy-based automatic authorization.
	ProtocolIDJAG Protocol = "idjag"

	// ProtocolAAuth uses AAuth for human consent-based authorization.
	ProtocolAAuth Protocol = "aauth"
)

Supported protocols.

func DetectTokenProtocol

func DetectTokenProtocol(token string) Protocol

DetectTokenProtocol attempts to detect the protocol from token claims. Returns empty string if unable to determine.

type Provider

type Provider interface {
	// Authorize requests authorization for the given scopes.
	// Returns AuthResult with token if approved, or consent info if pending.
	Authorize(ctx context.Context, req *AuthRequest) (*AuthResult, error)

	// CheckConsent checks the status of a pending consent request.
	CheckConsent(ctx context.Context, statusURI string) (*AuthResult, error)

	// WaitForConsent polls for consent approval with timeout.
	WaitForConsent(ctx context.Context, statusURI string, timeout time.Duration) (*AuthResult, error)

	// Revoke revokes an existing authorization.
	Revoke(ctx context.Context, token string) error

	// Protocol returns the protocol this provider implements.
	Protocol() Protocol

	// HTTPClient returns an HTTP client that automatically adds authorization.
	HTTPClient(ctx context.Context, req *AuthRequest) (*http.Client, error)
}

Provider is the interface for authorization providers.

type ScopePolicy

type ScopePolicy struct {
	// Pattern is the scope pattern to match.
	// Supports wildcards: "calendar:*", "admin:**", "email:read"
	Pattern string `json:"pattern" yaml:"pattern"`

	// Protocol is the protocol to use for matching scopes.
	Protocol Protocol `json:"protocol" yaml:"protocol"`

	// RequireConsent forces human consent even for ID-JAG.
	RequireConsent bool `json:"require_consent,omitempty" yaml:"require_consent,omitempty"`

	// InteractionType is the AAuth interaction type for this scope.
	InteractionType string `json:"interaction_type,omitempty" yaml:"interaction_type,omitempty"`

	// MaxDuration is the maximum authorization duration for this scope.
	MaxDuration string `json:"max_duration,omitempty" yaml:"max_duration,omitempty"`

	// Description describes what this scope allows.
	Description string `json:"description,omitempty" yaml:"description,omitempty"`

	// Priority determines matching order (higher = checked first).
	Priority int `json:"priority,omitempty" yaml:"priority,omitempty"`
}

ScopePolicy defines how a scope pattern should be authorized.

type TokenClaims

type TokenClaims struct {
	// Protocol indicates which protocol verified this token.
	Protocol Protocol `json:"protocol"`

	// Issuer is the token issuer.
	Issuer string `json:"iss"`

	// Subject is the token subject (agent ID).
	Subject string `json:"sub"`

	// Audience is the token audience.
	Audience []string `json:"aud"`

	// Scopes are the granted scopes (space-separated in token).
	Scopes []string `json:"scopes"`

	// ExpiresAt is when the token expires.
	ExpiresAt time.Time `json:"exp"`

	// IssuedAt is when the token was issued.
	IssuedAt time.Time `json:"iat"`

	// Actor contains delegation information (who the agent acts for).
	Actor *ActorClaims `json:"act,omitempty"`

	// Raw contains the raw claims map for protocol-specific data.
	Raw map[string]any `json:"raw,omitempty"`
}

TokenClaims represents verified token claims.

func (*TokenClaims) HasAnyScope

func (c *TokenClaims) HasAnyScope(scopes ...string) bool

HasAnyScope checks if the claims include any of the specified scopes.

func (*TokenClaims) HasScope

func (c *TokenClaims) HasScope(scope string) bool

HasScope checks if the claims include a specific scope.

type TokenRefresher

type TokenRefresher interface {
	// Refresh refreshes an expired or expiring token.
	Refresh(ctx context.Context, token string) (*AuthResult, error)

	// NeedsRefresh returns true if the token should be refreshed.
	NeedsRefresh(expiresAt time.Time) bool
}

TokenRefresher handles token refresh.

type TokenVerifier

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

TokenVerifier verifies tokens and enforces action-based policies.

func NewTokenVerifier

func NewTokenVerifier(config *VerifierConfig) *TokenVerifier

NewTokenVerifier creates a new hybrid token verifier.

func (*TokenVerifier) AddAAuthIssuer

func (v *TokenVerifier) AddAAuthIssuer(issuerURL, jwksURL string)

AddAAuthIssuer adds a trusted AAuth issuer.

func (*TokenVerifier) AddIDJAGIssuer

func (v *TokenVerifier) AddIDJAGIssuer(issuerURL, jwksURL string)

AddIDJAGIssuer adds a trusted ID-JAG issuer.

func (*TokenVerifier) GetRequiredProtocol

func (v *TokenVerifier) GetRequiredProtocol(action string) Protocol

GetRequiredProtocol returns the required protocol for an action.

func (*TokenVerifier) IsSensitiveAction

func (v *TokenVerifier) IsSensitiveAction(action string) bool

IsSensitiveAction returns true if the action requires AAuth.

func (*TokenVerifier) Verify

func (v *TokenVerifier) Verify(ctx context.Context, token string) (*TokenClaims, error)

Verify verifies a token without action checking. Returns the claims if valid.

func (*TokenVerifier) VerifyForAction

func (v *TokenVerifier) VerifyForAction(ctx context.Context, token, action string) (*TokenClaims, error)

VerifyForAction verifies a token and checks if it's valid for the given action. Returns an error if the token protocol doesn't match the action's required protocol.

type VerifierConfig

type VerifierConfig struct {
	// IDJAGEnabled enables ID-JAG token verification.
	IDJAGEnabled bool `json:"idjag_enabled" yaml:"idjag_enabled"`

	// IDJAGIssuers maps issuer URLs to JWKS URLs for ID-JAG verification.
	// If JWKS URL is empty, defaults to {issuer}/.well-known/jwks.json
	IDJAGIssuers map[string]string `json:"idjag_issuers" yaml:"idjag_issuers"`

	// IDJAGAudience is the expected audience for ID-JAG tokens.
	IDJAGAudience string `json:"idjag_audience" yaml:"idjag_audience"`

	// AAuthEnabled enables AAuth token verification.
	AAuthEnabled bool `json:"aauth_enabled" yaml:"aauth_enabled"`

	// AAuthIssuers maps issuer URLs to JWKS URLs for AAuth verification.
	// If JWKS URL is empty, defaults to {issuer}/.well-known/jwks.json
	AAuthIssuers map[string]string `json:"aauth_issuers" yaml:"aauth_issuers"`

	// AAuthAudience is the expected audience for AAuth tokens.
	AAuthAudience string `json:"aauth_audience" yaml:"aauth_audience"`

	// ActionPolicy routes actions to protocols.
	// Key is the action name (e.g., "chat", "write", "delete").
	// Value is the required protocol for that action.
	ActionPolicy map[string]Protocol `json:"action_policy" yaml:"action_policy"`

	// DefaultProtocol is used when no action policy matches.
	// Defaults to ProtocolIDJAG (automatic).
	DefaultProtocol Protocol `json:"default_protocol" yaml:"default_protocol"`

	// SensitiveActions require AAuth (human consent).
	// These override ActionPolicy.
	SensitiveActions []string `json:"sensitive_actions" yaml:"sensitive_actions"`

	// CacheTTL is how long to cache JWKS keys.
	CacheTTL time.Duration `json:"cache_ttl" yaml:"cache_ttl"`
}

VerifierConfig configures the hybrid token verifier.

func DefaultVerifierConfig

func DefaultVerifierConfig() *VerifierConfig

DefaultVerifierConfig returns a sensible default configuration.

Directories

Path Synopsis
Package client provides a Go SDK for agents to interact with AgentAuth servers.
Package client provides a Go SDK for agents to interact with AgentAuth servers.
cmd
agentauth-server command
Command agentauth-server runs a unified authorization server that combines the AAuth Person Server (human consent) and the ID-JAG Authorization Server (automated token exchange) into a single deployable binary.
Command agentauth-server runs a unified authorization server that combines the AAuth Person Server (human consent) and the ID-JAG Authorization Server (automated token exchange) into a single deployable binary.
examples
agentauth-demo command
Command agentauth-demo demonstrates the agentauth server with both ID-JAG (automated) and AAuth (human consent) authorization flows.
Command agentauth-demo demonstrates the agentauth server with both ID-JAG (automated) and AAuth (human consent) authorization flows.
omniagent-aauth/peopleserver command
Command peopleserver runs the AIStandardsIO PeopleServer for the OmniAgent demo.
Command peopleserver runs the AIStandardsIO PeopleServer for the OmniAgent demo.
Package identity provides layered identity composition for AI agents.
Package identity provides layered identity composition for AI agents.
lambda
peopleserver command
Package main provides an AWS Lambda handler for the AIStandardsIO PeopleServer.
Package main provides an AWS Lambda handler for the AIStandardsIO PeopleServer.
Package store provides storage abstractions for agent authorization.
Package store provides storage abstractions for agent authorization.

Jump to

Keyboard shortcuts

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