Documentation
¶
Overview ¶
Package agentauth lets AI agents authenticate to the app with their own keys and act for a user under capabilities the user granted. It is a Go port of better-auth's agent-auth plugin, which implements the Agent Auth Protocol (agentauthprotocol.com).
Two kinds of caller hold keys. A host is the runtime an agent lives in (an MCP client, a CLI, a desktop app); it signs "host+jwt" tokens and registers agents. An agent has its own Ed25519 (or P-256) key pair and signs a short "agent+jwt" for every request. A user approves an agent and its capabilities with a user code (the device_authorization method), and the agent then calls the execute endpoint, which checks its grants and the grants' constraints before the app's ExecuteFunc runs.
The protocol endpoints are served by Plugin.Handler in the protocol's JSON shape; each one is a self-served auth operation underneath (auth.OpInfo .SelfServed), so it runs the same pipeline as every other operation: rate limits, hooks, tracing. The user's operations (approving an agent, creating a host) are ordinary operations every transport mounts under /agentauth.
Security rules, each pinned by a test: a JWT's typ, signature, audience, expiry and age are checked, and the algorithm comes from the stored key, never from the token; every JWT carries a jti that authenticates once, recorded in the database so the rule holds across servers; a revoked, pending, rejected or expired agent authenticates nothing; a capability executes only under an active, unexpired grant whose constraints allow the arguments; a user code is compared as a SHA-256 digest in constant time.
Index ¶
- Constants
- Variables
- type AgentSession
- type AgentStatus
- type AgentStatusView
- type Approval
- type ApprovalHints
- type ApprovalMethodContext
- type ApprovalMethodFunc
- type ApprovalStatus
- type ApprovalStrength
- type ApproveRequest
- type ApproveResult
- type AutonomousUserFunc
- type Bearer
- type CIBAAuthorizeRequest
- type CIBAAuthorizeResult
- type Capability
- type CapabilityList
- type CapabilityRequest
- type CapabilityView
- type ClaimRequest
- type ClaimResult
- type Claims
- type Configuration
- type Constraint
- type Constraints
- type CreateHostRequest
- type CreateHostResult
- type DescribeCapabilityRequest
- type EnrollHostRequest
- type EnrollHostResult
- type Event
- type EventFunc
- type ExecuteFunc
- type ExecuteRequest
- type ExecuteResult
- type Execution
- type GrantStatus
- type GrantView
- type HeadersFunc
- type HostCapabilitiesContext
- type HostCapabilitiesFunc
- type HostStatus
- type InputField
- type IntrospectGrant
- type IntrospectRequest
- type Introspection
- type ListCapabilitiesRequest
- type Mode
- type OpenAPIHandlerOptions
- type OpenAPIOptions
- type OperationFilter
- type OperationInfo
- type Option
- func AbsoluteLifetime(d time.Duration) Option
- func AgentMaxLifetime(d time.Duration) Option
- func AgentSessionTTL(d time.Duration) Option
- func AllowDynamicHostRegistration() Option
- func AllowJWKSURLs() Option
- func AllowedKeyAlgorithms(algs ...string) Option
- func ApprovalMethods(methods ...string) Option
- func AutonomousUser(fn AutonomousUserFunc) Option
- func BlockedCapabilities(names ...string) Option
- func Capabilities(caps ...Capability) Option
- func DefaultHostCapabilities(names ...string) Option
- func DefaultHostCapabilitiesFunc(fn HostCapabilitiesFunc) Option
- func DeviceAuthorizationPage(u string) Option
- func EnrollmentTokenTTL(d time.Duration) Option
- func FromOpenAPISpec(spec []byte, o OpenAPIOptions) ([]Option, error)
- func Issuer(iss string) Option
- func JWKSClient(c *http.Client) Option
- func JWTMaxAge(d time.Duration) Option
- func MaxAgentsPerUser(n int) Option
- func Modes(modes ...Mode) Option
- func OnEvent(fn EventFunc) Option
- func OnExecute(fn ExecuteFunc) Option
- func ProofOfPresence(v PresenceVerifier) Option
- func ProviderDescription(d string) Option
- func ProviderName(name string) Option
- func RequireAuthForCapabilities() Option
- func ResolveApprovalMethod(fn ApprovalMethodFunc) Option
- func TrustProxy() Option
- type PendingApproval
- type PendingApprovals
- type Plugin
- func (p *Plugin) ApproveCapability(ctx context.Context, in ApproveRequest) (ApproveResult, error)
- func (p *Plugin) CIBAAuthorize(ctx context.Context, in CIBAAuthorizeRequest) (CIBAAuthorizeResult, error)
- func (p *Plugin) Claim(ctx context.Context, in ClaimRequest) (ClaimResult, error)
- func (p *Plugin) Configuration(ctx context.Context) (Configuration, error)
- func (p *Plugin) CreateHost(ctx context.Context, in CreateHostRequest) (CreateHostResult, error)
- func (p *Plugin) DataHooks() auth.DataHooks
- func (p *Plugin) DescribeCapability(ctx context.Context, in DescribeCapabilityRequest) (CapabilityView, error)
- func (p *Plugin) EnrollHost(ctx context.Context, in EnrollHostRequest) (EnrollHostResult, error)
- func (p *Plugin) Execute(ctx context.Context, in ExecuteRequest) (ExecuteResult, error)
- func (p *Plugin) Handler(opts ...authhttp.Option) http.Handler
- func (p *Plugin) Init(a *auth.Auth) error
- func (p *Plugin) Introspect(ctx context.Context, in IntrospectRequest) (Introspection, error)
- func (p *Plugin) IssuerURL() string
- func (p *Plugin) ListCapabilities(ctx context.Context, in ListCapabilitiesRequest) (CapabilityList, error)
- func (p *Plugin) Name() string
- func (p *Plugin) OperationHooks() []auth.OperationHook
- func (p *Plugin) Operations() []auth.Operation
- func (p *Plugin) OptionErr() error
- func (p *Plugin) PendingApprovalsFor(ctx context.Context) (PendingApprovals, error)
- func (p *Plugin) RateLimits() []auth.RateRule
- func (p *Plugin) Reactivate(ctx context.Context, in ReactivateRequest) (AgentStatusView, error)
- func (p *Plugin) Register(ctx context.Context, in RegisterRequest) (RegisterResult, error)
- func (p *Plugin) RequestCapability(ctx context.Context, in RequestCapabilityRequest) (RequestCapabilityResult, error)
- func (p *Plugin) Revoke(ctx context.Context, in RevokeRequest) (RevokeResult, error)
- func (p *Plugin) RevokeCapability(ctx context.Context, in RevokeCapabilityRequest) (RevokeCapabilityResult, error)
- func (p *Plugin) RevokeHost(ctx context.Context, in RevokeHostRequest) (RevokeHostResult, error)
- func (p *Plugin) RotateAgentKey(ctx context.Context, in RotateAgentKeyRequest) (RotateAgentKeyResult, error)
- func (p *Plugin) RotateHostKey(ctx context.Context, in RotateHostKeyRequest) (RotateHostKeyResult, error)
- func (p *Plugin) Session(ctx context.Context, b Bearer) (AgentSession, error)
- func (p *Plugin) Status(ctx context.Context, in StatusRequest) (AgentStatusView, error)
- func (p *Plugin) Sweep(ctx context.Context, cutoff time.Time) (int64, error)
- func (p *Plugin) Tables() []sqlb.Table
- func (p *Plugin) TypedMigrations(engine string, t auth.SQLTypes) ([]auth.Migration, error)
- func (p *Plugin) UpdateAgent(ctx context.Context, in UpdateAgentRequest) (UpdateAgentResult, error)
- func (p *Plugin) UpdateHost(ctx context.Context, in UpdateHostRequest) (UpdateHostResult, error)
- func (p *Plugin) UserTables() []auth.UserTable
- func (p *Plugin) Validate(*auth.Config) error
- func (p *Plugin) VerifyAgentRequest(r *http.Request, opts ...authhttp.Option) (AgentSession, error)
- type PresenceChallenge
- type PresenceResponse
- type PresenceVerifier
- type Primitive
- type PublicKey
- type ReactivateRequest
- type RegisterRequest
- type RegisterResult
- type RequestCapabilityRequest
- type RequestCapabilityResult
- type RevokeCapabilityRequest
- type RevokeCapabilityResult
- type RevokeHostRequest
- type RevokeHostResult
- type RevokeRequest
- type RevokeResult
- type RotateAgentKeyRequest
- type RotateAgentKeyResult
- type RotateHostKeyRequest
- type RotateHostKeyResult
- type SessionAgent
- type SessionGrant
- type SessionHost
- type SessionUser
- type StatusRequest
- type StrengthFunc
- type UpdateAgentRequest
- type UpdateAgentResult
- type UpdateHostRequest
- type UpdateHostResult
Constants ¶
const ( EndpointConfiguration auth.EndpointID = "agentauth.configuration" EndpointRegister auth.EndpointID = "agentauth.register" EndpointSession auth.EndpointID = "agentauth.session" EndpointRevoke auth.EndpointID = "agentauth.revoke" EndpointStatus auth.EndpointID = "agentauth.status" EndpointIntrospect auth.EndpointID = "agentauth.introspect" EndpointListCapabilities auth.EndpointID = "agentauth.list_capabilities" EndpointDescribeCapability auth.EndpointID = "agentauth.describe_capability" EndpointRequestCapability auth.EndpointID = "agentauth.request_capability" EndpointExecute auth.EndpointID = "agentauth.execute" EndpointRotateHostKey auth.EndpointID = "agentauth.rotate_host_key" EndpointApproveCapability auth.EndpointID = "agentauth.approve_capability" EndpointCreateHost auth.EndpointID = "agentauth.create_host" EndpointCIBAAuthorize auth.EndpointID = "agentauth.ciba_authorize" EndpointPendingApprovals auth.EndpointID = "agentauth.pending_approvals" EndpointRevokeHost auth.EndpointID = "agentauth.revoke_host" EndpointRevokeCapability auth.EndpointID = "agentauth.revoke_capability" EndpointClaim auth.EndpointID = "agentauth.claim" EndpointUpdateAgent auth.EndpointID = "agentauth.update_agent" EndpointReactivate auth.EndpointID = "agentauth.reactivate" EndpointRotateAgentKey auth.EndpointID = "agentauth.rotate_agent_key" EndpointUpdateHost auth.EndpointID = "agentauth.update_host" EndpointEnrollHost auth.EndpointID = "agentauth.enroll_host" )
Operation ids. The self-served ones are served by Handler at the protocol paths; the others by every transport, under /agentauth.
const ( PathConfiguration = "/agent-configuration" PathRegister = "/agent/register" PathSession = "/agent/session" PathRevoke = "/agent/revoke" PathStatus = "/agent/status" PathIntrospect = "/agent/introspect" PathListCapabilities = "/capability/list" PathDescribeCapability = "/capability/describe" PathRequestCapability = "/agent/request-capability" PathExecute = "/capability/execute" PathRotateHostKey = "/host/rotate-key" // PathCIBAAuthorize is the CIBA backchannel authentication endpoint // (protocol section 9.2), called with a host JWT. PathCIBAAuthorize = "/agent/ciba/authorize" // PathRevokeHost revokes a host and every agent under it (protocol // section 6.10), with a host JWT or a signed-in owner. PathRevokeHost = "/host/revoke" // PathRevokeCapability revokes capabilities of one agent without // revoking the agent. PathRevokeCapability = "/agent/revoke-capability" // PathClaim starts the claim of an autonomous agent (protocol section // 3.4), with a host JWT. PathClaim = "/agent/claim" // PathReactivate reactivates an expired agent (protocol section 6.6), // with a host JWT. PathReactivate = "/agent/reactivate" // PathRotateAgentKey replaces an agent's key (protocol section 6.8), // with a host JWT. PathRotateAgentKey = "/agent/rotate-key" // PathEnrollHost binds a key to a host created for enrollment // (protocol section 3.2), with the one-time enrollment token. PathEnrollHost = "/host/enroll" // WellKnownConfiguration is the discovery document's well-known path // (protocol section 5.1), served at the root of the issuer's host. WellKnownConfiguration = "/.well-known/agent-configuration" )
Protocol paths, under the issuer's path. They are better-auth's.
const ( // MethodDeviceAuthorization: the agent shows the user a code and a // URL, and the signed-in user enters the code on the app's approval // page. MethodDeviceAuthorization = "device_authorization" // MethodCIBA: client-initiated backchannel authentication, in poll // mode. The request is addressed to a known user, who sees it in the // pending_approvals list (the app may notify them from the // approval.created event) and answers it by its approval id; the agent // polls /agent/status. MethodCIBA = "ciba" )
Approval methods (protocol section 9).
const ( ActionApprove = "approve" ActionDeny = "deny" )
Approval actions.
const ( AlgEd25519 = "Ed25519" AlgP256 = "P-256" )
Key algorithms, by JWK curve name as the protocol names them.
const ( // DefaultJWTMaxAge is the oldest an agent or host JWT may be, from iat. DefaultJWTMaxAge = 60 * time.Second // DefaultAgentSessionTTL is the sliding idle lifetime of an agent: each // authenticated request extends it. DefaultAgentSessionTTL = time.Hour // DefaultAgentMaxLifetime caps an agent's life from its activation. DefaultAgentMaxLifetime = 24 * time.Hour // DefaultMaxAgentsPerUser is how many active agents one user may have. DefaultMaxAgentsPerUser = 25 // DefaultDeviceAuthorizationPage is where the approval answer sends the // user; the app serves the page. DefaultDeviceAuthorizationPage = "/device/capabilities" // DefaultApprovalTTL is how long a user code is valid. DefaultApprovalTTL = 5 * time.Minute // DefaultApprovalInterval is the polling interval the agent is told. DefaultApprovalInterval = 5 * time.Second // DefaultPresenceTTL is how long a WebAuthn approval challenge stays // valid, better-auth's challenge cache lifetime. DefaultPresenceTTL = 5 * time.Minute )
Defaults. Each has an option; the values are better-auth's.
const ( OpEq = "eq" OpMin = "min" OpMax = "max" OpIn = "in" OpNotIn = "not_in" )
Constraint operators, protocol section 2.13.
const ( EventAgentCreated = "agent.created" EventAgentRevoked = "agent.revoked" EventHostCreated = "host.created" EventHostKeyRotated = "host.key_rotated" EventCapabilityRequested = "capability.requested" EventCapabilityApproved = "capability.approved" EventCapabilityDenied = "capability.denied" EventApprovalCreated = "approval.created" EventApprovalApproved = "approval.approved" EventApprovalDenied = "approval.denied" EventCapabilityExecuted = "capability.executed" EventHostRevoked = "host.revoked" EventCapabilityRevoked = "capability.revoked" EventAgentClaimed = "agent.claimed" EventAgentUpdated = "agent.updated" EventAgentReactivated = "agent.reactivated" EventAgentKeyRotated = "agent.key_rotated" EventHostUpdated = "host.updated" EventHostEnrolled = "host.enrolled" EventHostReactivated = "host.reactivated" // Execution statuses of a capability.executed event. ExecutionSuccess = "success" ExecutionError = "error" // Actor types. ActorUser = "user" ActorAgent = "agent" // ActorHost is a host acting with its own JWT, as when it revokes // itself. ActorHost = "host" )
Event types, better-auth's AgentAuthEvent names for what this plugin does.
const ( // DefaultJWKSCacheTTL is how long fetched keys are used before the URL // is fetched again. DefaultJWKSCacheTTL = 5 * time.Minute // DefaultJWKSRefetchInterval is the shortest time between two fetches // of one URL caused by a kid the cached keys do not have. DefaultJWKSRefetchInterval = 30 * time.Second )
JWKS defaults. Each is better-auth's jwks-cache value except the refetch interval, which better-auth does not have: it refetches on every unknown kid, so a stream of tokens naming made-up kids makes the server fetch the URL once per token.
const ( TypeHostJWT = "host+jwt" TypeAgentJWT = "agent+jwt" )
JWT types, protocol sections 4.2 and 4.5. A host token can never be presented as an agent token, nor the reverse.
const ( // TableNameHost holds hosts: the runtimes (an MCP client, a CLI, a // desktop app) that hold a key and register agents. TableNameHost = "auth_agent_host" TableAliasHost = "aah" // TableNameAgent holds agents, each with its own public key. TableNameAgent = "auth_agent" TableAliasAgent = "aag" // TableNameGrant holds capability grants, one row per capability and // constraint scope. TableNameGrant = "auth_agent_grant" TableAliasGrant = "aagr" // TableNameApproval holds pending device-authorization requests. TableNameApproval = "auth_agent_approval" TableAliasApproval = "aaap" // TableNameJTI records spent JWT ids until they expire, so each agent or // host JWT authenticates once on every server sharing the database. TableNameJTI = "auth_agent_jti" TableAliasJTI = "aajt" )
The plugin's tables. No foreign keys (ADR-0002): UserTables names the user columns, so auth.DeleteUser removes a user's hosts, agents, grants and approval requests.
const ( ColID = "id" ColName = "name" ColUserID = "user_id" ColHostID = "host_id" ColAgentID = "agent_id" ColStatus = "status" ColPublicKey = "public_key" ColKid = "kid" ColActivatedAt = "activated_at" ColExpiresAt = "expires_at" ColLastUsedAt = "last_used_at" ColCreatedAt = "created_at" ColUpdatedAt = "updated_at" )
Column names shared by several tables.
const ( // ColDefaultCapabilities is a host's capability budget, a JSON array: // capabilities its agents receive without asking a user. ColDefaultCapabilities = "default_capabilities" // ColMode is an agent's mode, ModeDelegated or ModeAutonomous. ColMode = "mode" // ColMetadata is an agent's JSON object of display metadata, or NULL. ColMetadata = "metadata" // ColCapability is the capability a grant covers. ColCapability = "capability" // ColConstraints is a grant's JSON constraint object, or NULL for an // unrestricted grant. ColConstraints = "constraints" ColGrantedBy = "granted_by" ColDeniedBy = "denied_by" ColReason = "reason" // ColMethod is an approval request's method, MethodDeviceAuthorization or // MethodCIBA. ColMethod = "method" // ColCapabilities is an approval request's capabilities, space-joined. ColCapabilities = "capabilities" // ColUserCodeHash is the SHA-256 of the normalized user code. ColUserCodeHash = "user_code_hash" // ColLoginHint is a CIBA request's login hint, as the agent sent it. ColLoginHint = "login_hint" // ColBindingMessage is the message shown to the user with a request. ColBindingMessage = "binding_message" // ColInterval is the polling interval in seconds the agent was told. ColInterval = "interval_seconds" // ColKind is what an approval request asks for: NULL for capabilities // (and the agent's registration), ApprovalKindClaim for the claim of an // autonomous agent. Approving a claim transfers the agent to the user, // so the two must never be confused. ColKind = "kind" // ColJWKSURL is the https URL of a host's or an agent's JWKS, used // instead of a stored key under AllowJWKSURLs: the signing key is the // one whose kid the JWT's header names. ColJWKSURL = "jwks_url" // ColEnrollmentHash is the SHA-256 of a host's one-time enrollment // token, NULL once the host enrolled (or for a host created with a key). ColEnrollmentHash = "enrollment_token_hash" // ColEnrollmentExpiresAt is when the enrollment token stops working. ColEnrollmentExpiresAt = "enrollment_token_expires_at" )
Columns of one table each.
const ApprovalKindClaim = "claim"
ApprovalKindClaim marks an approval request that claims an autonomous agent (ColKind).
const DefaultEnrollmentTokenTTL = time.Hour
DefaultEnrollmentTokenTTL is how long a host's enrollment token works, better-auth's enrollmentTokenTTL.
const PluginName = "agentauth"
PluginName is the plugin's permanent identity, and the segment its user operations are served under.
const WarnJWKSURLs = "" /* 161-byte string literal not displayed */
WarnJWKSURLs is what Init logs at every start under AllowJWKSURLs.
Variables ¶
var ( ErrInvalidRequest = auth.NewError("agentauth.invalid_request", http.StatusBadRequest, "Malformed request, missing required fields, or invalid parameter types.") ErrInvalidJWT = auth.NewError("agentauth.invalid_jwt", http.StatusUnauthorized, "JWT is invalid, expired, or signature failed.") ErrJTIReplay = auth.NewError("agentauth.jti_replay", http.StatusUnauthorized, "JWT has already been used.") ErrRequestBindingMismatch = auth.NewError("agentauth.request_binding_mismatch", http.StatusUnauthorized, "Request binding does not match the JWT.") ErrInvalidPublicKey = auth.NewError("agentauth.invalid_public_key", http.StatusBadRequest, "Public key is invalid or malformed.") ErrUnsupportedAlgorithm = auth.NewError("agentauth.unsupported_algorithm", http.StatusBadRequest, "Key algorithm is not in the server's supported set.") ErrUnsupportedMode = auth.NewError("agentauth.unsupported_mode", http.StatusBadRequest, "Requested mode is not supported by this server.") ErrAuthenticationRequired = auth.NewError("agentauth.authentication_required", http.StatusUnauthorized, "An agent JWT, a host JWT or a signed-in user is required.") ErrAgentNotFound = auth.NewError("agentauth.agent_not_found", http.StatusNotFound, "Agent not found.") ErrAgentRevoked = auth.NewError("agentauth.agent_revoked", http.StatusForbidden, "Agent has been revoked.") ErrAgentPending = auth.NewError("agentauth.agent_pending", http.StatusForbidden, "Agent is still pending approval.") ErrAgentRejected = auth.NewError("agentauth.agent_rejected", http.StatusForbidden, "Agent registration was denied.") ErrAgentClaimed = auth.NewError("agentauth.agent_claimed", http.StatusForbidden, "Agent has been claimed and is no longer active.") ErrAgentExpired = auth.NewError("agentauth.agent_expired", http.StatusUnauthorized, "Agent session has expired.") ErrAbsoluteLifetimeExceeded = auth.NewError("agentauth.absolute_lifetime_exceeded", http.StatusForbidden, "Agent's absolute lifetime has elapsed.") ErrAgentExists = auth.NewError("agentauth.agent_exists", http.StatusConflict, "An agent with this public key is already registered.") ErrAgentLimitReached = auth.NewError("agentauth.agent_limit_reached", http.StatusBadRequest, "Maximum number of active agents per user reached.") ErrAutonomousOwnerRequired = auth.NewError("agentauth.autonomous_owner_required", http.StatusUnauthorized, "Autonomous agents require an owner to be resolved.") ErrHostNotFound = auth.NewError("agentauth.host_not_found", http.StatusNotFound, "Host not found.") ErrHostRevoked = auth.NewError("agentauth.host_revoked", http.StatusForbidden, "Host has been revoked.") ErrHostAlreadyLinked = auth.NewError("agentauth.host_already_linked", http.StatusConflict, "Host is already linked to a different user.") ErrDynamicHostRegistration = auth.NewError("agentauth.dynamic_host_registration_disabled", http.StatusForbidden, "Dynamic host registration is disabled: enable AllowDynamicHostRegistration, or create the host first with the create_host operation.") ErrInvalidCapabilities = auth.NewError("agentauth.invalid_capabilities", http.StatusBadRequest, "One or more requested capability names don't exist.") ErrCapabilityBlocked = auth.NewError("agentauth.capability_blocked", http.StatusBadRequest, "One or more requested capabilities are blocked by server policy.") ErrCapabilityNotFound = auth.NewError("agentauth.capability_not_found", http.StatusNotFound, "Capability does not exist.") ErrAlreadyGranted = auth.NewError("agentauth.already_granted", http.StatusConflict, "All requested capabilities are already granted.") ErrCapabilityNotGranted = auth.NewError("agentauth.capability_not_granted", http.StatusForbidden, "Agent does not have an active grant for this capability.") ErrGrantRevoked = auth.NewError("agentauth.grant_revoked", http.StatusForbidden, "Capability grant has been revoked.") ErrConstraintViolated = auth.NewError("agentauth.constraint_violated", http.StatusForbidden, "One or more capability constraints were violated.") ErrUnknownConstraintOperator = auth.NewError("agentauth.unknown_constraint_operator", http.StatusBadRequest, "Constraint contains an unrecognized operator.") ErrExecuteNotConfigured = auth.NewError("agentauth.execute_not_configured", http.StatusNotImplemented, "Server has not configured a capability execution handler.") ErrApprovalNotFound = auth.NewError("agentauth.capability_request_not_found", http.StatusNotFound, "Capability request not found.") ErrApprovalResolved = auth.NewError("agentauth.capability_request_already_resolved", http.StatusPreconditionFailed, "Capability request has already been resolved.") ErrApprovalOwnerMismatch = auth.NewError("agentauth.capability_request_owner_mismatch", http.StatusForbidden, "Capability request does not belong to this user.") ErrInvalidUserCode = auth.NewError("agentauth.invalid_user_code", http.StatusForbidden, "The user code is missing or does not match.") ErrApprovalExpired = auth.NewError("agentauth.approval_expired", http.StatusForbidden, "The approval request has expired.") ErrEnrollmentTokenInvalid = auth.NewError("agentauth.enrollment_token_invalid", http.StatusUnauthorized, "The enrollment token is invalid or was already used.") ErrEnrollmentTokenExpired = auth.NewError("agentauth.enrollment_token_expired", http.StatusUnauthorized, "The enrollment token has expired.") ErrJWKSURLsDisabled = auth.NewError("agentauth.jwks_url_disabled", http.StatusBadRequest, "This server does not accept JWKS URLs; send a public key.") ErrInvalidJWKSURL = auth.NewError("agentauth.invalid_jwks_url", http.StatusBadRequest, "The JWKS URL must be a public https URL.") )
Errors. The part after "agentauth." is the protocol's error code, which Handler answers as {"error": code, "message": message}.
var ( ErrBadIssuer = errors.New("agentauth: Issuer is an absolute https URL (http only for a loopback host) with no query or fragment") ErrBadAlgorithm = errors.New("agentauth: AllowedKeyAlgorithms names only Ed25519 and P-256, and at least one") ErrBadMode = errors.New("agentauth: Modes names only delegated and autonomous, and at least one") ErrBadDuration = errors.New("agentauth: JWTMaxAge and EnrollmentTokenTTL are positive, and no lifetime is negative") ErrBadCapability = errors.New("agentauth: a capability has a unique, non-empty name without whitespace, an absolute location URL when it has one, and a known approval strength") ErrBadApproval = errors.New("agentauth: ApprovalMethods names only ciba and device_authorization, and at least one") ErrNoPresence = errors.New("agentauth: a capability needs WebAuthn approval, so ProofOfPresence must be set") )
Configuration errors, returned by auth.New.
var ( ErrWebAuthnNotEnrolled = auth.NewError("agentauth.webauthn_not_enrolled", http.StatusForbidden, "No passkeys registered. Register a passkey before approving capabilities that require proof of physical presence.") ErrWebAuthnFailed = auth.NewError("agentauth.webauthn_verification_failed", http.StatusForbidden, "WebAuthn verification failed.") )
Errors of the presence check.
var ( TableHost = sqlb.Table{Name: TableNameHost, Alias: TableAliasHost} HostID = sqlb.Col[string](TableHost, ColID) HostName = sqlb.Col[*string](TableHost, ColName) HostUser = sqlb.Col[*string](TableHost, ColUserID) HostDefaultCaps = sqlb.Col[string](TableHost, ColDefaultCapabilities) HostPublicKey = sqlb.Col[string](TableHost, ColPublicKey) HostKid = sqlb.Col[string](TableHost, ColKid) HostStatusCol = sqlb.Col[string](TableHost, ColStatus) HostActivated = sqlb.Col[*time.Time](TableHost, ColActivatedAt) HostExpires = sqlb.Col[*time.Time](TableHost, ColExpiresAt) HostLastUsed = sqlb.Col[*time.Time](TableHost, ColLastUsedAt) HostCreated = sqlb.Col[time.Time](TableHost, ColCreatedAt) HostUpdated = sqlb.Col[time.Time](TableHost, ColUpdatedAt) HostJWKSURL = sqlb.Col[*string](TableHost, ColJWKSURL) HostEnrollHash = sqlb.Col[[]byte](TableHost, ColEnrollmentHash) HostEnrollUntil = sqlb.Col[*time.Time](TableHost, ColEnrollmentExpiresAt) TableAgent = sqlb.Table{Name: TableNameAgent, Alias: TableAliasAgent} AgentID = sqlb.Col[string](TableAgent, ColID) AgentName = sqlb.Col[string](TableAgent, ColName) AgentUser = sqlb.Col[*string](TableAgent, ColUserID) AgentHost = sqlb.Col[string](TableAgent, ColHostID) AgentStatusCol = sqlb.Col[string](TableAgent, ColStatus) AgentMode = sqlb.Col[string](TableAgent, ColMode) AgentPublicKey = sqlb.Col[string](TableAgent, ColPublicKey) AgentKid = sqlb.Col[*string](TableAgent, ColKid) AgentLastUsed = sqlb.Col[*time.Time](TableAgent, ColLastUsedAt) AgentActivated = sqlb.Col[*time.Time](TableAgent, ColActivatedAt) AgentExpires = sqlb.Col[*time.Time](TableAgent, ColExpiresAt) AgentMetadata = sqlb.Col[*string](TableAgent, ColMetadata) AgentCreated = sqlb.Col[time.Time](TableAgent, ColCreatedAt) AgentUpdated = sqlb.Col[time.Time](TableAgent, ColUpdatedAt) AgentJWKSURL = sqlb.Col[*string](TableAgent, ColJWKSURL) TableGrant = sqlb.Table{Name: TableNameGrant, Alias: TableAliasGrant} GrantID = sqlb.Col[string](TableGrant, ColID) GrantAgent = sqlb.Col[string](TableGrant, ColAgentID) GrantCapability = sqlb.Col[string](TableGrant, ColCapability) GrantConstraints = sqlb.Col[*string](TableGrant, ColConstraints) GrantGrantedBy = sqlb.Col[*string](TableGrant, ColGrantedBy) GrantDeniedBy = sqlb.Col[*string](TableGrant, ColDeniedBy) GrantReason = sqlb.Col[*string](TableGrant, ColReason) GrantStatusCol = sqlb.Col[string](TableGrant, ColStatus) GrantExpires = sqlb.Col[*time.Time](TableGrant, ColExpiresAt) GrantCreated = sqlb.Col[time.Time](TableGrant, ColCreatedAt) GrantUpdated = sqlb.Col[time.Time](TableGrant, ColUpdatedAt) TableApproval = sqlb.Table{Name: TableNameApproval, Alias: TableAliasApproval} ApprovalID = sqlb.Col[string](TableApproval, ColID) ApprovalMethod = sqlb.Col[string](TableApproval, ColMethod) ApprovalAgent = sqlb.Col[string](TableApproval, ColAgentID) ApprovalHost = sqlb.Col[*string](TableApproval, ColHostID) ApprovalUser = sqlb.Col[*string](TableApproval, ColUserID) ApprovalCapabilities = sqlb.Col[string](TableApproval, ColCapabilities) ApprovalStatusCol = sqlb.Col[string](TableApproval, ColStatus) ApprovalCodeHash = sqlb.Col[[]byte](TableApproval, ColUserCodeHash) ApprovalLoginHint = sqlb.Col[*string](TableApproval, ColLoginHint) ApprovalBinding = sqlb.Col[*string](TableApproval, ColBindingMessage) ApprovalInterval = sqlb.Col[int64](TableApproval, ColInterval) ApprovalKind = sqlb.Col[*string](TableApproval, ColKind) ApprovalExpires = sqlb.Col[time.Time](TableApproval, ColExpiresAt) ApprovalCreated = sqlb.Col[time.Time](TableApproval, ColCreatedAt) ApprovalUpdated = sqlb.Col[time.Time](TableApproval, ColUpdatedAt) TableJTI = sqlb.Table{Name: TableNameJTI, Alias: TableAliasJTI} JTIID = sqlb.Col[string](TableJTI, ColID) JTIExpires = sqlb.Col[time.Time](TableJTI, ColExpiresAt) )
Typed tables and columns.
var ApprovalMethodValues = []string{MethodCIBA, MethodDeviceAuthorization}
ApprovalMethodValues is every approval method, and the default of ApprovalMethods, better-auth's default order.
var ApprovalStrengthValues = []ApprovalStrength{StrengthNone, StrengthSession, StrengthWebAuthn}
ApprovalStrengthValues is every strength.
var ErrBadOpenAPI = errors.New("agentauth: the OpenAPI document is not valid JSON with unique operationIds")
ErrBadOpenAPI is a spec the OpenAPI adapter cannot read.
var ErrUpstream = errors.New("agentauth: upstream API error")
ErrUpstream wraps an upstream answer that was not a success.
var ModeValues = []Mode{ModeDelegated, ModeAutonomous}
ModeValues is every mode, and the default of Modes.
Functions ¶
This section is empty.
Types ¶
type AgentSession ¶
type AgentSession struct {
Type Mode `json:"type"`
AgentID string `json:"agentId"`
UserID *string `json:"userId"`
Agent SessionAgent `json:"agent"`
Host *SessionHost `json:"host"`
User SessionUser `json:"user"`
}
AgentSession is an authenticated agent request, better-auth's AgentSession: the agent, its effective grants (the active, unexpired ones, narrowed to the JWT's capabilities claim when it has one), its host and the user it acts for.
func (AgentSession) HasGrant ¶
func (s AgentSession) HasGrant(capability string) (SessionGrant, bool)
HasGrant reports whether the session holds an effective grant of capability, for an app route that serves a capability with a Location. Constraints are the route's to enforce, with Constraints.Validate.
type AgentStatus ¶
type AgentStatus string
AgentStatus is an agent's lifecycle state.
const ( AgentActive AgentStatus = "active" AgentPending AgentStatus = "pending" AgentExpired AgentStatus = "expired" AgentRevoked AgentStatus = "revoked" AgentRejected AgentStatus = "rejected" AgentClaimed AgentStatus = "claimed" )
Agent states.
type AgentStatusView ¶
type AgentStatusView struct {
AgentID string `json:"agent_id"`
Name string `json:"name"`
HostID string `json:"host_id"`
Status AgentStatus `json:"status"`
Grants []GrantView `json:"agent_capability_grants"`
Mode Mode `json:"mode"`
UserID *string `json:"user_id"`
ActivatedAt *string `json:"activated_at"`
CreatedAt *string `json:"created_at"`
LastUsedAt *string `json:"last_used_at"`
ExpiresAt *string `json:"expires_at"`
}
AgentStatusView is an agent's status and grants.
type Approval ¶
type Approval struct {
Method string `json:"method"`
// DeviceCode is the approval request's id.
DeviceCode string `json:"device_code,omitempty"`
VerificationURI string `json:"verification_uri,omitempty"`
VerificationURIComplete string `json:"verification_uri_complete,omitempty"`
// UserCode is shown to the user, who types it on the approval page.
UserCode string `json:"user_code,omitempty"`
ExpiresIn int64 `json:"expires_in"`
Interval int64 `json:"interval"`
}
Approval tells the agent how the user approves it: for device authorization RFC 8628's shape; for CIBA only the method, the lifetime and the polling interval, since the request reaches the user directly.
type ApprovalHints ¶
type ApprovalHints struct {
PreferredMethod string `json:"preferred_method,omitempty"`
LoginHint string `json:"login_hint,omitempty"`
BindingMessage string `json:"binding_message,omitempty"`
}
ApprovalHints are the request fields that steer an approval, protocol section 9: the agent's preferred method, the CIBA login hint and the message shown to the user.
type ApprovalMethodContext ¶
type ApprovalMethodContext struct {
// UserID is the user the approval is for, nil when nobody owns the
// agent or its host yet (only device authorization can serve that).
UserID *string
AgentName string
HostID string
Capabilities []string
// PreferredMethod is the agent's preferred_method, possibly empty.
PreferredMethod string
// SupportedMethods is ApprovalMethods.
SupportedMethods []string
}
ApprovalMethodContext is what an ApprovalMethodFunc chooses from, better-auth's resolveApprovalMethod context.
type ApprovalMethodFunc ¶
type ApprovalMethodFunc func(ctx context.Context, mc ApprovalMethodContext) (string, error)
ApprovalMethodFunc chooses the approval method of one request, better-auth's resolveApprovalMethod. A method outside SupportedMethods, or CIBA for a request with no user, falls back to device authorization.
type ApprovalStatus ¶
type ApprovalStatus string
ApprovalStatus is an approval request's state.
const ( ApprovalPending ApprovalStatus = "pending" ApprovalApproved ApprovalStatus = "approved" ApprovalDenied ApprovalStatus = "denied" )
Approval request states.
const ApprovalWebAuthnRequired ApprovalStatus = "webauthn_required"
ApprovalWebAuthnRequired is ApproveResult.Status when the approval waits for a WebAuthn assertion: nothing was approved, and WebAuthn carries the challenge to answer.
type ApprovalStrength ¶
type ApprovalStrength string
ApprovalStrength is what a user must show to approve a capability.
const ( // StrengthNone marks a capability that needs no user interaction; it // is informational, as in better-auth: the host's budget is what // grants without asking. StrengthNone ApprovalStrength = "none" // StrengthSession needs a signed-in user (device authorization or // CIBA). The default. StrengthSession ApprovalStrength = "session" // StrengthWebAuthn needs a WebAuthn assertion with user verification // on top of the session: proof that a person, not an agent driving // the browser, approved. Needs ProofOfPresence. StrengthWebAuthn ApprovalStrength = "webauthn" )
Approval strengths.
type ApproveRequest ¶
type ApproveRequest struct {
// AgentID names the agent; ApprovalID names one approval request
// instead (the CIBA inbox's approval_id). One of them is required.
AgentID string `json:"agent_id,omitempty"`
ApprovalID string `json:"approval_id,omitempty"`
// UserCode is the code the agent showed the user.
UserCode string `json:"user_code,omitempty"`
// Action is ActionApprove or ActionDeny.
Action string `json:"action"`
// Capabilities narrows an approval to these names; the rest are
// denied. Empty approves every pending capability.
Capabilities []string `json:"capabilities,omitempty"`
// TTLSeconds overrides the approved grants' lifetime.
TTLSeconds int64 `json:"ttl,omitempty"`
Reason string `json:"reason,omitempty"`
// WebAuthn answers the challenge of an earlier ApprovalWebAuthnRequired
// result.
WebAuthn *PresenceResponse `json:"webauthn_response,omitempty"`
}
ApproveRequest is a signed-in user's answer to a pending agent or capability request. A device authorization request needs its user code; a CIBA request is answered by the user it was addressed to; with neither pending, only the agent's or host's owner may answer.
type ApproveResult ¶
type ApproveResult struct {
Status ApprovalStatus `json:"status"`
AgentID string `json:"agent_id"`
Added []string `json:"added"`
WebAuthn *PresenceChallenge `json:"webauthn,omitempty"`
// Claimed reports an approved claim (Claim): the user now owns the
// agent, which is AgentClaimed.
Claimed bool `json:"claimed,omitempty"`
}
ApproveResult is the outcome. Status ApprovalWebAuthnRequired approved nothing yet: answer WebAuthn and call again.
type AutonomousUserFunc ¶
type AutonomousUserFunc func(ctx context.Context, hostID, agentID string) (*SessionUser, error)
AutonomousUserFunc names the user an autonomous agent on an unclaimed host acts as, better-auth's resolveAutonomousUser. Nil, or a nil user, refuses the agent with ErrAutonomousOwnerRequired.
type Bearer ¶
type Bearer struct {
Token string `json:"-"`
// Method is the HTTP method, URL the request URL without its query.
Method string `json:"-"`
URL string `json:"-"`
// BodySHA256 is the base64url SHA-256 of the raw request body.
BodySHA256 string `json:"-"`
}
Bearer is the JWT an agent or host presented, and the request it came with, for the request-binding claims (htm, htu, ath). Handler fills it from the Authorization header; a Go caller sets Token, and Method, URL and BodySHA256 when the token is bound to a request.
type CIBAAuthorizeRequest ¶
type CIBAAuthorizeRequest struct {
Bearer
// LoginHint names the user by any sign-in identifier (an email, a
// phone number, a username); only a verified one matches.
LoginHint string `json:"login_hint"`
Capabilities []string `json:"capabilities,omitempty"`
// BindingMessage is shown to the user beside the request.
BindingMessage string `json:"binding_message,omitempty"`
AgentID string `json:"agent_id"`
}
CIBAAuthorizeRequest is a host's backchannel authentication request (protocol section 9.2): ask the user named by LoginHint to approve the host's agent AgentID. Bearer is the host's JWT.
type CIBAAuthorizeResult ¶
type CIBAAuthorizeResult struct {
AuthReqID string `json:"auth_req_id"`
ExpiresIn int64 `json:"expires_in"`
Interval int64 `json:"interval"`
}
CIBAAuthorizeResult is the request's handle. Its shape is the same whether or not LoginHint named a user, so it never reveals who has an account.
type Capability ¶
type Capability struct {
// Name is the identifier agents request and execute. Unique.
Name string `json:"name"`
// Description says what it does, for the agent and the approving user.
Description string `json:"description"`
// Location is the absolute URL where the capability executes when it is
// not the execute endpoint; an agent JWT for it names it as aud.
Location string `json:"location,omitempty"`
// Input and Output are JSON Schemas of the arguments and of the result.
Input json.RawMessage `json:"input,omitempty"`
Output json.RawMessage `json:"output,omitempty"`
// RequiredConstraints are argument fields an agent must constrain when
// it requests the capability (protocol section 2.13).
RequiredConstraints []string `json:"-"`
// GrantTTL is how long a grant of it lasts; zero never expires.
GrantTTL time.Duration `json:"-"`
// ApprovalStrength is what approving it takes (protocol section
// 8.11); empty is StrengthSession.
ApprovalStrength ApprovalStrength `json:"approval_strength,omitempty"`
}
Capability is one thing an agent may do, protocol section 4.
func FromOpenAPI ¶
func FromOpenAPI(spec []byte) ([]Capability, error)
FromOpenAPI derives capabilities from an OpenAPI 3.x document, one per operation with an operationId, better-auth's fromOpenAPI: the name is the operationId, the description its description or summary, the input schema its parameters and JSON body, the output schema its 200 or 201 JSON answer.
type CapabilityList ¶
type CapabilityList struct {
Capabilities []CapabilityView `json:"capabilities"`
HasMore bool `json:"has_more"`
NextCursor string `json:"next_cursor,omitempty"`
}
CapabilityList is one page of the catalogue.
type CapabilityRequest ¶
type CapabilityRequest struct {
Name string `json:"name"`
Constraints Constraints `json:"constraints,omitempty"`
}
CapabilityRequest is one requested capability: a bare name, or an object with a name and the constraints the agent proposes for its grant.
func (*CapabilityRequest) UnmarshalJSON ¶
func (r *CapabilityRequest) UnmarshalJSON(b []byte) error
UnmarshalJSON accepts "name" or {"name": ..., "constraints": {...}}. The parameter is the JSON boundary the standard library mandates.
type CapabilityView ¶
type CapabilityView struct {
Name string `json:"name"`
Description string `json:"description"`
Location string `json:"location,omitempty"`
Input json.RawMessage `json:"input,omitempty"`
Output json.RawMessage `json:"output,omitempty"`
InputFields []InputField `json:"input_fields,omitempty"`
// ApprovalStrength is the capability's, when it sets one.
ApprovalStrength ApprovalStrength `json:"approval_strength,omitempty"`
// GrantStatus is "granted" or "not_granted" for an authenticated
// caller, and empty otherwise.
GrantStatus string `json:"grant_status,omitempty"`
}
CapabilityView is a catalogue entry as an agent sees it.
type ClaimRequest ¶
type ClaimRequest struct {
Bearer
AgentID string `json:"agent_id"`
ApprovalHints
}
ClaimRequest starts the claim of an autonomous agent, protocol section 3.4: a host (Bearer, a host JWT; under AllowDynamicHostRegistration a new host registers itself here, as at /agent/register) asks a user to take over the agent AgentID, typically one the user found on a resource the agent made.
type ClaimResult ¶
type ClaimResult struct {
AgentID string `json:"agent_id"`
HostID string `json:"host_id"`
Name string `json:"name"`
Mode Mode `json:"mode"`
Status AgentStatus `json:"status"`
Grants []GrantView `json:"agent_capability_grants"`
Approval *Approval `json:"approval"`
}
ClaimResult is the agent to be claimed and the approval the user must give: the user code to enter on the device authorization page.
type Claims ¶
type Claims struct {
Issuer string `json:"iss"`
Subject string `json:"sub"`
Audience audience `json:"aud"`
ExpiresAt int64 `json:"exp"`
IssuedAt int64 `json:"iat"`
ID string `json:"jti"`
// Capabilities narrows an agent JWT to these capabilities (protocol
// section 5.3); nil means every grant.
Capabilities []string `json:"capabilities"`
// Htm, Htu and Ath bind the token to one request: its method, its URL
// without the query, and the base64url SHA-256 of its body.
Htm string `json:"htm"`
Htu string `json:"htu"`
Ath string `json:"ath"`
// AgentPublicKey is the key of the agent a host JWT registers.
AgentPublicKey *PublicKey `json:"agent_public_key"`
// AgentJWKSURL is, instead of AgentPublicKey, the https URL the
// registered agent's keys are fetched from (AllowJWKSURLs).
AgentJWKSURL string `json:"agent_jwks_url"`
// HostPublicKey is the host's own key, for dynamic registration.
HostPublicKey *PublicKey `json:"host_public_key"`
// HostName names the host for display.
HostName string `json:"host_name"`
}
Claims are the claims an agent or host JWT carries. Only a verified token produces trusted Claims.
type Configuration ¶
type Configuration struct {
Version string `json:"version"`
ProviderName string `json:"provider_name"`
Description string `json:"description"`
Issuer string `json:"issuer"`
DefaultLocation string `json:"default_location"`
Algorithms []string `json:"algorithms"`
Modes []Mode `json:"modes"`
ApprovalMethods []string `json:"approval_methods"`
Endpoints map[string]string `json:"endpoints"`
}
Configuration is the discovery document, protocol section 5.1.
type Constraint ¶
type Constraint struct {
Eq *Primitive
Min *float64
Max *float64
In []Primitive
NotIn []Primitive
// Unknown holds operators the protocol does not define.
Unknown map[string]json.RawMessage
// contains filtered or unexported fields
}
Constraint is one argument's rule: a bare primitive is shorthand for eq; an object names operators. Unknown operators are kept, so they are stored as the agent sent them and refused at execution with ErrUnknownConstraintOperator, as in better-auth.
func (Constraint) MarshalJSON ¶
func (c Constraint) MarshalJSON() ([]byte, error)
MarshalJSON writes the constraint in the form it was read.
func (*Constraint) UnmarshalJSON ¶
func (c *Constraint) UnmarshalJSON(b []byte) error
UnmarshalJSON reads a bare primitive or an operator object. The parameter is the JSON boundary the standard library mandates.
type Constraints ¶
type Constraints map[string]Constraint
Constraints scope a grant: each key is an argument name, each value the rule the argument must satisfy, such as {"amount": {"max": 1000}, "currency": {"in": ["USD", "EUR"]}}. Nil is an unrestricted grant.
func (Constraints) Covers ¶
func (cs Constraints) Covers(req Constraints) bool
Covers reports whether a grant scoped by cs already allows everything a request scoped by req would, better-auth's constraintsCover: an unrestricted grant covers everything, a restricted one never covers an unrestricted request, and otherwise each requested field must be within the existing rule on it.
func (Constraints) Validate ¶
func (cs Constraints) Validate(args map[string]any) error
Validate checks args against the constraints: ErrUnknownConstraintOperator when a rule names an operator the protocol does not define (checked first, as better-auth does), ErrConstraintViolated when an argument breaks a rule. A missing argument breaks every rule on it.
type CreateHostRequest ¶
type CreateHostRequest struct {
Name string `json:"name,omitempty"`
PublicKey PublicKey `json:"public_key"`
JWKSURL string `json:"jwks_url,omitempty"`
DefaultCapabilities []string `json:"default_capabilities,omitempty"`
}
CreateHostRequest creates a host for the signed-in user, protocol section 3.2: the host's key, and the budget its agents receive without asking. Instead of a key the host may name a JWKS URL (AllowJWKSURLs); with neither, the host is created for enrollment and a device binds its key later with the returned token (EnrollHost).
type CreateHostResult ¶
type CreateHostResult struct {
HostID string `json:"host_id"`
DefaultCapabilities []string `json:"default_capabilities"`
Status HostStatus `json:"status"`
EnrollmentToken string `json:"enrollment_token,omitempty"`
EnrollmentTokenExpiresAt *time.Time `json:"enrollment_token_expires_at,omitempty"`
// Reactivated is true when the call took over or reactivated an
// existing host with the same key (the host.reactivated event).
Reactivated bool `json:"-"`
}
CreateHostResult is the created host. EnrollmentToken is set only for a host created for enrollment, and only in this answer: the server keeps its SHA-256.
type DescribeCapabilityRequest ¶
DescribeCapabilityRequest names one capability, protocol section 6.2.1.
type EnrollHostRequest ¶
type EnrollHostRequest struct {
Token string `json:"token"`
PublicKey PublicKey `json:"public_key"`
Name string `json:"name,omitempty"`
}
EnrollHostRequest binds a device's key to a host created for enrollment (CreateHost with neither a key nor a JWKS URL), protocol section 3.2. Token is the one-time enrollment token CreateHost returned.
type EnrollHostResult ¶
type EnrollHostResult struct {
HostID string `json:"host_id"`
Name *string `json:"name"`
DefaultCapabilities []string `json:"default_capabilities"`
Status HostStatus `json:"status"`
}
EnrollHostResult is the enrolled host.
type Event ¶
type Event struct {
Type string
ActorID string
ActorType string
AgentID string
HostID string
// Capability, Arguments, Status, Duration and Error describe a
// capability.executed event.
Capability string
Arguments map[string]any
Status string
Duration time.Duration
Error string
// Capabilities are the capabilities a request, approval or denial
// named.
Capabilities []string
// ApprovalID, Method, UserID and BindingMessage describe an
// approval.created event: the request, its approval method, the user
// it waits for (nil when nobody owns the agent yet) and the message to
// show. A CIBA request reaches its user only through the app, so this
// event is where the app sends the notification.
ApprovalID string
Method string
UserID *string
BindingMessage string
}
Event is one audit event, better-auth's AgentAuthEvent: who did what to which agent or host. The capability.executed fields are set only on that type.
type EventFunc ¶
EventFunc receives events. It runs after the commit, in the background (auth.WithBackground), and its panics and slowness never reach the request, better-auth's emit that never throws.
type ExecuteFunc ¶
ExecuteFunc runs a capability for an agent, better-auth's onExecute. The plugin has checked the agent and the grant before it is called. Its result is sent to the agent as {"data": result}; it is any because each capability's result has its own shape and goes straight to the JSON encoder. An *auth.Error it returns reaches the agent as it is; any other error is an internal error.
func OpenAPIHandler ¶
func OpenAPIHandler(spec []byte, o OpenAPIHandlerOptions) (ExecuteFunc, error)
OpenAPIHandler returns an ExecuteFunc that proxies each capability to its OpenAPI operation, better-auth's createOpenAPIHandler: path parameters are escaped into the path, query and header parameters set, the other arguments sent as the JSON body (not for GET or HEAD). A JSON answer is returned verbatim, any other as text; a 202's body is returned as it is. An answer that is neither 2xx is ErrUpstream, which reaches the agent as an internal error.
type ExecuteRequest ¶
type ExecuteRequest struct {
Bearer
Capability string `json:"capability"`
// Arguments are the capability's arguments, as JSON decoded them.
Arguments map[string]any `json:"arguments,omitempty"`
}
ExecuteRequest runs a capability, protocol section 6.11. Bearer is the agent's JWT.
type ExecuteResult ¶
type ExecuteResult struct {
// Data is whatever ExecuteFunc returned, for the JSON encoder.
Data any `json:"data"`
}
ExecuteResult is the capability's result, better-auth's sync answer.
type Execution ¶
type Execution struct {
Capability Capability
Arguments map[string]any
Session AgentSession
// GrantID is the grant that authorized the call.
GrantID string
// ConsumeGrant spends the grant, for a single-use capability such as a
// payment: it becomes GrantConsumed and authorizes nothing more.
ConsumeGrant func(ctx context.Context) error
}
Execution is what ExecuteFunc receives.
type GrantStatus ¶
type GrantStatus string
GrantStatus is a capability grant's state.
const ( GrantActive GrantStatus = "active" GrantPending GrantStatus = "pending" GrantDenied GrantStatus = "denied" GrantRevoked GrantStatus = "revoked" GrantConsumed GrantStatus = "consumed" )
Grant states. GrantConsumed is a single-use grant spent by Execution.ConsumeGrant.
type GrantView ¶
type GrantView struct {
Capability string `json:"capability"`
Status GrantStatus `json:"status"`
GrantedBy *string `json:"granted_by,omitempty"`
Constraints Constraints `json:"constraints,omitempty"`
ExpiresAt *string `json:"expires_at,omitempty"`
Description string `json:"description,omitempty"`
Input json.RawMessage `json:"input,omitempty"`
Output json.RawMessage `json:"output,omitempty"`
Reason *string `json:"reason,omitempty"`
}
GrantView is a grant as the protocol shows it, section 5.3.
type HeadersFunc ¶
HeadersFunc returns the headers a proxied call carries upstream, such as the user's access token there, better-auth's resolveHeaders. They win over header parameters taken from the arguments, so an agent can never replace the credentials.
type HostCapabilitiesContext ¶
type HostCapabilitiesContext struct {
// Mode is the registering agent's mode; empty when a user creates or
// claims the host.
Mode Mode
// UserID is the host's owner, nil for a host nobody owns yet.
UserID *string
// HostID is empty for a host about to be created.
HostID string
HostName string
}
HostCapabilitiesContext is what a HostCapabilitiesFunc decides from, better-auth's DefaultHostCapabilitiesContext.
type HostCapabilitiesFunc ¶
type HostCapabilitiesFunc func(ctx context.Context, hc HostCapabilitiesContext) ([]string, error)
HostCapabilitiesFunc computes a host's budget per host, the function form of better-auth's defaultHostCapabilities.
type HostStatus ¶
type HostStatus string
HostStatus is a host's lifecycle state.
const ( HostActive HostStatus = "active" HostPending HostStatus = "pending" HostRevoked HostStatus = "revoked" // HostPendingEnrollment is a host created without a key, waiting for // a device to enroll with its one-time token (EnrollHost). It // authenticates nothing. HostPendingEnrollment HostStatus = "pending_enrollment" )
Host states.
type InputField ¶
type InputField struct {
Name string `json:"name"`
Type json.RawMessage `json:"type,omitempty"`
Description json.RawMessage `json:"description,omitempty"`
}
InputField is one argument of a capability, from its input schema.
type IntrospectGrant ¶
type IntrospectGrant struct {
Capability string `json:"capability"`
Status GrantStatus `json:"status"`
}
IntrospectGrant is a grant in an introspection answer.
type IntrospectRequest ¶
type IntrospectRequest struct {
Token string `json:"token"`
}
IntrospectRequest asks whether an agent JWT is valid, protocol section 6.10, for a resource server that received one.
type Introspection ¶
type Introspection struct {
Active bool `json:"active"`
AgentID string `json:"agent_id,omitempty"`
HostID string `json:"host_id,omitempty"`
UserID *string `json:"user_id,omitempty"`
Grants []IntrospectGrant `json:"agent_capability_grants,omitempty"`
Mode Mode `json:"mode,omitempty"`
ExpiresAt *string `json:"expires_at,omitempty"`
}
Introspection is the answer: Active false and nothing else for any token that would not authenticate.
type ListCapabilitiesRequest ¶
type ListCapabilitiesRequest struct {
Bearer
Cursor string `json:"cursor,omitempty"`
Limit int `json:"limit,omitempty"`
}
ListCapabilitiesRequest lists the catalogue, protocol section 6.2. Bearer is optional: with an agent JWT each entry says whether the agent holds it, with a host JWT whether the host's budget covers it.
type OpenAPIHandlerOptions ¶
type OpenAPIHandlerOptions struct {
// BaseURL is the upstream API's base URL; each operation's path is
// appended to it. Required.
BaseURL string
// Headers adds headers to every upstream request.
Headers HeadersFunc
// Client sends the requests; nil is http.DefaultClient.
Client *http.Client
}
OpenAPIHandlerOptions configures OpenAPIHandler.
type OpenAPIOptions ¶
type OpenAPIOptions struct {
OpenAPIHandlerOptions
// HostCapabilities picks the default host budget among the
// operations; nil leaves the budget to other options.
HostCapabilities OperationFilter
// Strength assigns each capability's approval strength.
Strength StrengthFunc
// Location is set on every capability, for an API whose agents call
// it directly rather than through the execute endpoint.
Location string
}
OpenAPIOptions configures FromOpenAPISpec.
type OperationFilter ¶
type OperationFilter func(ctx context.Context, op OperationInfo, hc HostCapabilitiesContext) (bool, error)
OperationFilter decides per operation, better-auth's defaultHostCapabilities filter forms: AllOperations is its true, OperationsWithMethod its method and method-list forms, and any other function its callback, which also receives the host's context.
func OperationsWithMethod ¶
func OperationsWithMethod(methods ...string) OperationFilter
OperationsWithMethod selects the operations of the given HTTP methods, in any case, such as "GET" and "HEAD" for read-only access.
type OperationInfo ¶
type OperationInfo struct {
// Name is the operationId, the capability's name.
Name string
// Method is the HTTP method, upper case.
Method string
Description string
}
OperationInfo is one OpenAPI operation as a filter sees it, better-auth's OpenAPICapabilityInfo.
type Option ¶
type Option func(*Plugin)
Option configures the plugin; pass options to New.
func AbsoluteLifetime ¶
AbsoluteLifetime refuses an agent this long after its creation, whatever happened since. Zero (the default) disables it.
func AgentMaxLifetime ¶
AgentMaxLifetime overrides DefaultAgentMaxLifetime; zero disables it.
func AgentSessionTTL ¶
AgentSessionTTL overrides DefaultAgentSessionTTL; zero disables it.
func AllowDynamicHostRegistration ¶
func AllowDynamicHostRegistration() Option
AllowDynamicHostRegistration lets an unknown host register agents with a host JWT that carries its own public key. A significant trust decision, off by default: without it, a host must first be created by a signed-in user (create_host).
func AllowJWKSURLs ¶
func AllowJWKSURLs() Option
AllowJWKSURLs lets a host (CreateHost, UpdateHost) or an agent (the agent_jwks_url claim of a registering host JWT) name an https JWKS URL instead of a stored public key, better-auth's jwks_url: a JWT is then checked against the key whose kid its header names, fetched from the URL and cached (DefaultJWKSCacheTTL). Off by default, because the server then makes outbound requests to URLs a user or a host chose, and whoever can change the document at that URL can sign for the host or agent: Init logs WarnJWKSURLs at every start. The default client fetches https only, refuses private, loopback, link-local and CGNAT addresses after DNS resolution, follows no redirect and reads at most 1 MiB in 5 seconds.
func AllowedKeyAlgorithms ¶
AllowedKeyAlgorithms narrows the key algorithms agents and hosts may use, by JWK curve name. The default is Ed25519 only, as in better-auth.
func ApprovalMethods ¶
ApprovalMethods narrows ApprovalMethodValues: the methods discovery lists and requests may use. Without MethodCIBA the CIBA endpoint answers invalid_request.
func AutonomousUser ¶
func AutonomousUser(fn AutonomousUserFunc) Option
AutonomousUser sets the AutonomousUserFunc.
func BlockedCapabilities ¶
BlockedCapabilities can never be granted. A trailing ".*" blocks a family.
func Capabilities ¶
func Capabilities(caps ...Capability) Option
Capabilities is the catalogue agents may request. With a catalogue, a request for a name outside it is refused (ErrInvalidCapabilities); with none, any name is accepted, as in better-auth.
func DefaultHostCapabilities ¶
DefaultHostCapabilities is the budget a dynamically registered or claimed host receives, and a host created without default_capabilities: capabilities its agents get without asking a user.
func DefaultHostCapabilitiesFunc ¶
func DefaultHostCapabilitiesFunc(fn HostCapabilitiesFunc) Option
DefaultHostCapabilitiesFunc computes the budget per host instead of DefaultHostCapabilities' fixed list. Its names are checked against the catalogue like any other.
func DeviceAuthorizationPage ¶
DeviceAuthorizationPage overrides DefaultDeviceAuthorizationPage: a path on the issuer's origin or an absolute URL. The page receives agent_id and code, and posts them to the approve_capability operation.
func EnrollmentTokenTTL ¶
EnrollmentTokenTTL overrides DefaultEnrollmentTokenTTL.
func FromOpenAPISpec ¶
func FromOpenAPISpec(spec []byte, o OpenAPIOptions) ([]Option, error)
FromOpenAPISpec derives the plugin's options from an OpenAPI 3.x document, better-auth's createFromOpenAPI: ProviderName and ProviderDescription from its info, the Capabilities, an OnExecute that proxies to the upstream API, and, with HostCapabilities, the default host budget. Pass them to New before any option that should override them:
opts, err := agentauth.FromOpenAPISpec(spec, agentauth.OpenAPIOptions{...})
p := agentauth.New(append(opts, agentauth.Issuer(iss))...)
func Issuer ¶
Issuer is the base URL of the protocol endpoints and the JWT audience, such as "https://app.example.com/api/agent". Empty (the default) is the app's auth.WithBaseURL.
func JWKSClient ¶
JWKSClient replaces the guarded client AllowJWKSURLs fetches with, the one escape hatch: for a JWKS on a private network, or a test server. The replacement is trusted as it is; it should keep a timeout and refuse redirects.
func MaxAgentsPerUser ¶
MaxAgentsPerUser overrides DefaultMaxAgentsPerUser; zero disables it.
func OnExecute ¶
func OnExecute(fn ExecuteFunc) Option
OnExecute runs capabilities for the execute endpoint. Without it the endpoint answers ErrExecuteNotConfigured, and capabilities with a Location run on the app's own routes, which verify the agent with Plugin.VerifyAgentRequest.
func ProofOfPresence ¶
func ProofOfPresence(v PresenceVerifier) Option
ProofOfPresence enables WebAuthn-gated approvals with v, better-auth's proofOfPresence: a capability with StrengthWebAuthn, a first agent on a pending host, and new capabilities for an active agent then need a passkey assertion on top of the signed-in session. Registering a new agent under an already approved host needs the session only.
func ProviderDescription ¶
ProviderDescription is the discovery document's description.
func ProviderName ¶
ProviderName and ProviderDescription fill the discovery document.
func RequireAuthForCapabilities ¶
func RequireAuthForCapabilities() Option
RequireAuthForCapabilities makes listing and describing capabilities need an agent or host JWT.
func ResolveApprovalMethod ¶
func ResolveApprovalMethod(fn ApprovalMethodFunc) Option
ResolveApprovalMethod installs an ApprovalMethodFunc. The default takes the agent's preferred_method when it is supported, and device authorization otherwise, as better-auth's default does.
func TrustProxy ¶
func TrustProxy() Option
TrustProxy builds the URL a token's htu claim is compared with from X-Forwarded-Proto and X-Forwarded-Host, for a server behind a reverse proxy that terminates TLS, better-auth's trustProxy. Off by default: enable it only when the proxy overwrites both headers. The accepted audiences never come from the request, so this cannot widen them.
type PendingApproval ¶
type PendingApproval struct {
ApprovalID string `json:"approval_id"`
Method string `json:"method"`
AgentID string `json:"agent_id"`
AgentName *string `json:"agent_name"`
BindingMessage *string `json:"binding_message"`
Capabilities []string `json:"capabilities"`
// CapabilityConstraints and CapabilityReasons are the agent's pending
// grants' constraints and reasons, by capability.
CapabilityConstraints map[string]Constraints `json:"capability_constraints"`
CapabilityReasons map[string]string `json:"capability_reasons"`
ExpiresIn int64 `json:"expires_in"`
CreatedAt time.Time `json:"created_at"`
}
PendingApproval is one request waiting for the signed-in user, the CIBA pending list's entry.
type PendingApprovals ¶
type PendingApprovals struct {
Requests []PendingApproval `json:"requests"`
}
PendingApprovals is the signed-in user's pending requests, newest first.
type Plugin ¶
type Plugin struct {
// contains filtered or unexported fields
}
Plugin is the Agent Auth provider. Build it with New.
func (*Plugin) ApproveCapability ¶
func (p *Plugin) ApproveCapability(ctx context.Context, in ApproveRequest) (ApproveResult, error)
ApproveCapability answers a pending request for the signed-in user. It needs a fresh sign-in, as better-auth's freshSessionWindow does.
func (*Plugin) CIBAAuthorize ¶
func (p *Plugin) CIBAAuthorize(ctx context.Context, in CIBAAuthorizeRequest) (CIBAAuthorizeResult, error)
CIBAAuthorize creates a CIBA approval request for the host that signed in.Token.
func (*Plugin) Claim ¶
func (p *Plugin) Claim(ctx context.Context, in ClaimRequest) (ClaimResult, error)
Claim records a claim request, better-auth's claimAgent. A signed-in user approving it with ApproveCapability (its user code) becomes the agent's owner: the agent becomes AgentClaimed, which authenticates nothing more, and its host, when nobody owns it, becomes the user's.
func (*Plugin) Configuration ¶
func (p *Plugin) Configuration(ctx context.Context) (Configuration, error)
Configuration returns the discovery document.
func (*Plugin) CreateHost ¶
func (p *Plugin) CreateHost(ctx context.Context, in CreateHostRequest) (CreateHostResult, error)
CreateHost creates a host owned by the signed-in user, or reactivates the user's host with the same key.
func (*Plugin) DataHooks ¶
DataHooks delete a user's agents before the user (deleteUserAgents), which UserTables alone would leave behind.
func (*Plugin) DescribeCapability ¶
func (p *Plugin) DescribeCapability(ctx context.Context, in DescribeCapabilityRequest) (CapabilityView, error)
DescribeCapability returns one catalogue entry with its schemas.
func (*Plugin) EnrollHost ¶
func (p *Plugin) EnrollHost(ctx context.Context, in EnrollHostRequest) (EnrollHostResult, error)
EnrollHost enrolls a device as a host, better-auth's enrollHost: a user creates the host in the app (and its budget), hands the token to the device, and the device enrolls with its own key, so the private key never leaves the device. The token works once, for EnrollmentTokenTTL.
func (*Plugin) Execute ¶
func (p *Plugin) Execute(ctx context.Context, in ExecuteRequest) (ExecuteResult, error)
Execute runs a capability for the agent that signed in.Token.
func (*Plugin) Handler ¶
Handler serves the protocol endpoints at their paths under the issuer, and the discovery document at /.well-known/agent-configuration: mount it at the root of the issuer's host. opts are the authhttp options the app's auth handler uses, so revoking by a signed-in user reads the same session. Every endpoint calls its operation through the pipeline; an unknown path answers 404.
func (*Plugin) Introspect ¶
func (p *Plugin) Introspect(ctx context.Context, in IntrospectRequest) (Introspection, error)
Introspect checks an agent JWT and spends its jti, as better-auth does.
func (*Plugin) IssuerURL ¶
IssuerURL is the issuer the plugin serves under: Issuer, or the base URL.
func (*Plugin) ListCapabilities ¶
func (p *Plugin) ListCapabilities(ctx context.Context, in ListCapabilitiesRequest) (CapabilityList, error)
ListCapabilities returns a page of the catalogue.
func (*Plugin) OperationHooks ¶
func (p *Plugin) OperationHooks() []auth.OperationHook
OperationHooks turns operation results into events: After for each success, Finally for an execution that failed. Nothing without OnEvent.
func (*Plugin) Operations ¶
Operations lists every operation; the self-served ones are wired but mounted only by Handler.
func (*Plugin) OptionErr ¶
OptionErr is every error the options recorded, such as auth.ErrNilOption naming an option given nil; auth.New refuses to start while it is not nil (auth.OptionChecker).
func (*Plugin) PendingApprovalsFor ¶
func (p *Plugin) PendingApprovalsFor(ctx context.Context) (PendingApprovals, error)
PendingApprovalsFor lists the signed-in user's pending approval requests, better-auth's /agent/ciba/pending: what the app's approval inbox shows.
func (*Plugin) RateLimits ¶
RateLimits limits EnrollHost per IP.
func (*Plugin) Reactivate ¶
func (p *Plugin) Reactivate(ctx context.Context, in ReactivateRequest) (AgentStatusView, error)
Reactivate brings an expired agent back, better-auth's reactivateAgent, and answers its status in Status's shape. Its capabilities decay to the host's budget: every grant it held is revoked and the budget granted again, so a capability a user approved on top of the budget must be asked for again. An agent that has not expired is answered as it is; a revoked, rejected, claimed or pending one, or one past its AbsoluteLifetime, is refused.
func (*Plugin) Register ¶
func (p *Plugin) Register(ctx context.Context, in RegisterRequest) (RegisterResult, error)
Register registers an agent under the host that signed in.Token.
func (*Plugin) RequestCapability ¶
func (p *Plugin) RequestCapability(ctx context.Context, in RequestCapabilityRequest) (RequestCapabilityResult, error)
RequestCapability requests capabilities for the agent that signed in.Token.
func (*Plugin) Revoke ¶
func (p *Plugin) Revoke(ctx context.Context, in RevokeRequest) (RevokeResult, error)
Revoke revokes an agent and every grant it holds.
func (*Plugin) RevokeCapability ¶
func (p *Plugin) RevokeCapability(ctx context.Context, in RevokeCapabilityRequest) (RevokeCapabilityResult, error)
RevokeCapability revokes every active or pending grant of the named capabilities, under every constraint scope, better-auth's revokeCapability. Executing a revoked capability then answers ErrGrantRevoked, and the host's budget does not grant it again.
func (*Plugin) RevokeHost ¶
func (p *Plugin) RevokeHost(ctx context.Context, in RevokeHostRequest) (RevokeHostResult, error)
RevokeHost revokes a host and every agent under it, with their grants, better-auth's revokeHost.
func (*Plugin) RotateAgentKey ¶
func (p *Plugin) RotateAgentKey(ctx context.Context, in RotateAgentKeyRequest) (RotateAgentKeyResult, error)
RotateAgentKey replaces an active agent's key, better-auth's rotateKey: the old key stops working at once. An agent that fetched its keys from a JWKS URL has a stored key from then on.
func (*Plugin) RotateHostKey ¶
func (p *Plugin) RotateHostKey(ctx context.Context, in RotateHostKeyRequest) (RotateHostKeyResult, error)
RotateHostKey replaces the key of the host that signed in.Token; the old key stops working at once. better-auth renames the host to the new key's thumbprint; this port keeps the host id, because agents and grants name it, and records the new key's kid instead.
func (*Plugin) Session ¶
Session authenticates an agent JWT and returns the agent's session, better-auth's getAgentSession. Every call spends the token's jti.
func (*Plugin) Status ¶
func (p *Plugin) Status(ctx context.Context, in StatusRequest) (AgentStatusView, error)
Status returns an agent's status. A host polls it while its agent waits for approval.
func (*Plugin) TypedMigrations ¶
TypedMigrations creates the tables for engine. A spent JWT id is a primary key, so a second insert of the same one fails on every engine.
func (*Plugin) UpdateAgent ¶
func (p *Plugin) UpdateAgent(ctx context.Context, in UpdateAgentRequest) (UpdateAgentResult, error)
UpdateAgent updates an agent's name or metadata, better-auth's updateAgent. The metadata is what AgentSession.Agent.Metadata carries to the app's routes.
func (*Plugin) UpdateHost ¶
func (p *Plugin) UpdateHost(ctx context.Context, in UpdateHostRequest) (UpdateHostResult, error)
UpdateHost renames a host, replaces its key or JWKS URL, or replaces its budget. A new key stops the old one at once, as RotateHostKey does.
func (*Plugin) UserTables ¶
UserTables names every user column, so DeleteUser removes the user's hosts, agents, the grants they gave and their approval requests.
func (*Plugin) Validate ¶
Validate checks the issuer, the algorithms, the modes, the lifetimes and the catalogue.
func (*Plugin) VerifyAgentRequest ¶
VerifyAgentRequest authenticates the agent JWT of a request to one of the app's own routes, such as a capability with a Location: better-auth's verifyAgentRequest. It spends the token's jti. The route checks AgentSession.HasGrant, and enforces the grant's constraints itself.
type PresenceChallenge ¶
type PresenceChallenge struct {
Ceremony string `json:"ceremony"`
Options json.RawMessage `json:"webauthn_options"`
}
PresenceChallenge is the WebAuthn challenge of an approval.
type PresenceResponse ¶
type PresenceResponse struct {
Ceremony string `json:"ceremony"`
Credential json.RawMessage `json:"credential"`
}
PresenceResponse answers a PresenceChallenge: its ceremony, and the JSON the browser's PublicKeyCredential serializes to.
type PresenceVerifier ¶
type PresenceVerifier interface {
// PresenceEnrolled reports whether userID has a passkey to prove
// presence with.
PresenceEnrolled(ctx context.Context, userID string) (bool, error)
// BeginPresence starts an assertion over userID's passkeys with user
// verification required, and returns its single-use ceremony handle
// and the options for navigator.credentials.get.
BeginPresence(ctx context.Context, userID, scope string) (ceremony string, options json.RawMessage, err error)
// VerifyPresence spends the ceremony and checks the assertion: one of
// userID's passkeys, begun for scope, with the user verified.
VerifyPresence(ctx context.Context, userID, scope, ceremony string, credential json.RawMessage) error
}
PresenceVerifier runs the WebAuthn ceremony that proves a person, not an agent driving the browser, approved a request (protocol section 8.11). plugin/passkey's Plugin implements it; the interface keeps the WebAuthn library out of this module. scope binds a ceremony to one approval, so an assertion made for one agent never approves another.
type Primitive ¶
type Primitive struct {
// contains filtered or unexported fields
}
Primitive is a JSON string, number or boolean: the values a constraint compares against.
func (Primitive) MarshalJSON ¶
MarshalJSON writes the primitive as its JSON type.
func (*Primitive) UnmarshalJSON ¶
UnmarshalJSON accepts a string, a number or a boolean; anything else is not a primitive.
type PublicKey ¶
type PublicKey struct {
KeyType string `json:"kty"`
Curve string `json:"crv,omitempty"`
X string `json:"x,omitempty"`
Y string `json:"y,omitempty"`
KeyID string `json:"kid,omitempty"`
}
PublicKey is a public key in JWK form, as agents and hosts send it: OKP with crv Ed25519 and x, or EC with crv P-256, x and y.
func (PublicKey) Thumbprint ¶
Thumbprint is the key's RFC 7638 thumbprint: the base64url SHA-256 of its required members in lexicographic order.
type ReactivateRequest ¶
ReactivateRequest reactivates an expired agent, protocol section 6.6: a host JWT, and the agent of that host.
type RegisterRequest ¶
type RegisterRequest struct {
Bearer
Name string `json:"name"`
Capabilities []CapabilityRequest `json:"capabilities,omitempty"`
Reason string `json:"reason,omitempty"`
// Mode defaults to ModeDelegated.
Mode Mode `json:"mode,omitempty"`
HostName string `json:"host_name,omitempty"`
// ForceApproval sends every capability to the user, even those in the
// host's budget.
ForceApproval bool `json:"force_approval,omitempty"`
// ApprovalHints steer the approval when one is needed.
ApprovalHints
}
RegisterRequest registers an agent, protocol section 6.3. Bearer is a host JWT whose agent_public_key claim is the new agent's key.
type RegisterResult ¶
type RegisterResult struct {
AgentID string `json:"agent_id"`
HostID string `json:"host_id"`
Name string `json:"name"`
Mode Mode `json:"mode"`
Status AgentStatus `json:"status"`
Grants []GrantView `json:"agent_capability_grants"`
// Approval is set when the agent or a capability waits for a user.
Approval *Approval `json:"approval,omitempty"`
}
RegisterResult is the registered agent.
type RequestCapabilityRequest ¶
type RequestCapabilityRequest struct {
Bearer
Capabilities []CapabilityRequest `json:"capabilities"`
Reason string `json:"reason,omitempty"`
// ApprovalHints steer the approval when one is needed.
ApprovalHints
}
RequestCapabilityRequest asks for more capabilities, protocol section 6.4. Bearer is the agent's JWT.
type RequestCapabilityResult ¶
type RequestCapabilityResult struct {
AgentID string `json:"agent_id"`
Status AgentStatus `json:"status"`
Grants []GrantView `json:"agent_capability_grants"`
Approval *Approval `json:"approval,omitempty"`
}
RequestCapabilityResult is the requested grants, and the approval when some wait for a user.
type RevokeCapabilityRequest ¶
type RevokeCapabilityRequest struct {
Bearer
AgentID string `json:"agent_id,omitempty"`
Capabilities []string `json:"capabilities"`
}
RevokeCapabilityRequest revokes capabilities of one agent without revoking the agent: by the agent itself (an agent JWT), its host (a host JWT) or the signed-in user who owns it.
type RevokeCapabilityResult ¶
type RevokeCapabilityResult struct {
AgentID string `json:"agent_id"`
Revoked []string `json:"revoked"`
GrantIDs []string `json:"grant_ids"`
}
RevokeCapabilityResult names the capabilities that had a grant to revoke, and the grants revoked. A capability with nothing to revoke is left out, so a repeated call answers empty lists.
type RevokeHostRequest ¶
RevokeHostRequest revokes a host, protocol section 6.10: the host itself with its JWT (HostID optional, and when given it must name that host), or the signed-in user who owns it (HostID required).
type RevokeHostResult ¶
type RevokeHostResult struct {
HostID string `json:"host_id"`
Status HostStatus `json:"status"`
AgentsRevoked int `json:"agents_revoked"`
}
RevokeHostResult is the revoked host and how many agents it took with it.
type RevokeRequest ¶
RevokeRequest revokes an agent, protocol section 6.6: by the agent itself (an agent JWT, AgentID optional), by its host (a host JWT), or by the signed-in user who owns the agent or its host.
type RevokeResult ¶
type RevokeResult struct {
AgentID string `json:"agent_id"`
Status AgentStatus `json:"status"`
}
RevokeResult is the revoked agent.
type RotateAgentKeyRequest ¶
type RotateAgentKeyRequest struct {
Bearer
AgentID string `json:"agent_id"`
PublicKey PublicKey `json:"public_key"`
}
RotateAgentKeyRequest replaces an agent's key, protocol section 6.8: a host JWT, the agent of that host and its new key.
type RotateAgentKeyResult ¶
type RotateAgentKeyResult struct {
AgentID string `json:"agent_id"`
Status AgentStatus `json:"status"`
// HostID is the host that rotated the key, for the agent.key_rotated
// event; not part of the protocol's answer.
HostID string `json:"-"`
}
RotateAgentKeyResult is the agent after rotation.
type RotateHostKeyRequest ¶
RotateHostKeyRequest replaces a host's key, protocol section 6.8. Bearer is a host JWT signed by the current key.
type RotateHostKeyResult ¶
type RotateHostKeyResult struct {
HostID string `json:"host_id"`
Status HostStatus `json:"status"`
}
RotateHostKeyResult is the host after rotation.
type SessionAgent ¶
type SessionAgent struct {
ID string `json:"id"`
Name string `json:"name"`
Mode Mode `json:"mode"`
CapabilityGrants []SessionGrant `json:"capabilityGrants"`
HostID string `json:"hostId"`
CreatedAt time.Time `json:"createdAt"`
ActivatedAt *time.Time `json:"activatedAt"`
Metadata json.RawMessage `json:"metadata"`
}
SessionAgent is the agent of a session.
type SessionGrant ¶
type SessionGrant struct {
Capability string `json:"capability"`
Constraints Constraints `json:"constraints"`
GrantedBy *string `json:"grantedBy"`
Status GrantStatus `json:"status"`
}
SessionGrant is one effective grant of an agent session.
type SessionHost ¶
type SessionHost struct {
ID string `json:"id"`
UserID *string `json:"userId"`
Status string `json:"status"`
}
SessionHost is the host of a session.
type SessionUser ¶
SessionUser is the user an agent acts for.
type StatusRequest ¶
StatusRequest asks for an agent's status, protocol section 6.5: with an agent JWT for itself, or a host JWT and the AgentID of one of its agents.
type StrengthFunc ¶
type StrengthFunc func(op OperationInfo) ApprovalStrength
StrengthFunc assigns an approval strength per operation, better-auth's approvalStrength forms: StrengthForAll and StrengthByMethod, or any function.
func StrengthByMethod ¶
func StrengthByMethod(m map[string]ApprovalStrength) StrengthFunc
StrengthByMethod maps HTTP methods to strengths, such as {"GET": StrengthSession, "POST": StrengthWebAuthn}; a method it does not name keeps the default.
func StrengthForAll ¶
func StrengthForAll(s ApprovalStrength) StrengthFunc
StrengthForAll gives every operation s.
type UpdateAgentRequest ¶
type UpdateAgentRequest struct {
AgentID string `json:"agent_id"`
Name *string `json:"name,omitempty"`
Metadata json.RawMessage `json:"metadata,omitempty"`
}
UpdateAgentRequest renames an agent or replaces its metadata, for the signed-in user who owns it. A nil Name or empty Metadata leaves that field as it is; Metadata is a JSON object whose values are strings, numbers, booleans or null, and {} clears it.
type UpdateAgentResult ¶
type UpdateAgentResult struct {
AgentID string `json:"agent_id"`
Name string `json:"name"`
Metadata json.RawMessage `json:"metadata"`
UpdatedAt time.Time `json:"updated_at"`
}
UpdateAgentResult is the agent as stored after the update.
type UpdateHostRequest ¶
type UpdateHostRequest struct {
HostID string `json:"host_id"`
Name *string `json:"name,omitempty"`
PublicKey *PublicKey `json:"public_key,omitempty"`
JWKSURL *string `json:"jwks_url,omitempty"`
DefaultCapabilities []string `json:"default_capabilities,omitempty"`
}
UpdateHostRequest changes a host the signed-in user owns, better-auth's updateHost. A nil field is left as it is. PublicKey and JWKSURL replace how the host signs; at most one of them is given.
type UpdateHostResult ¶
type UpdateHostResult struct {
HostID string `json:"id"`
Name *string `json:"name"`
DefaultCapabilities []string `json:"default_capabilities"`
JWKSURL *string `json:"jwks_url"`
Status HostStatus `json:"status"`
UpdatedAt time.Time `json:"updated_at"`
}
UpdateHostResult is the host after the update.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package agentclient is the agent side of the Agent Auth Protocol: a Go program (an agent runtime, a CLI, an MCP server) that holds a host key discovers a provider, registers agents, waits for the user's approval, and executes capabilities with short-lived, request-bound JWTs.
|
Package agentclient is the agent side of the Agent Auth Protocol: a Go program (an agent runtime, a CLI, an MCP server) that holds a host key discovers a provider, registers agents, waits for the user's approval, and executes capabilities with short-lived, request-bound JWTs. |