Skip to main content

COG-3: Authentication Mechanisms

Status: Draft
Version: 2.0
Created: 2025-09-24
Updated: 2026-01-28
Authors: Mike Anderson

:::note Related specifications This document specifies the catalogue of authentication mechanisms a venue may offer (public access, bearer tokens, HTTP Basic, OAuth 2.0, Ed25519 self-issued JWTs, UCAN identity tokens for relayed requests) and how clients use them. For how a specific venue implements identity verification and access control — the middleware verification order, venue-signed tokens, and OAuth provider configuration — see COG-10: Venue Authentication & Access Control. For capability-based authorisation (what an authenticated caller may do), see COG-13: Agent Capabilities. :::

Purpose

Authentication ensures the integrity, security, and controlled access to assets and operations on the grid. This document specifies authentication mechanisms for venues, enabling secure and flexible access control while maintaining venue operators' autonomy over access policies.

Authentication is managed at a per-venue level, allowing venue operators to define and enforce access policies tailored to their specific requirements.

Authentication mechanisms are built on commonly available web standards and, where appropriate, make use of decentralised facilities supported by Convex lattice technology.

Principles

  • Venue autonomy — Each venue operator decides which authentication mechanisms to support and what privileges to grant.
  • Layered security — Multiple mechanisms MAY be supported simultaneously, allowing clients to use whichever is appropriate.
  • Standards-based — All mechanisms use established web and cryptographic standards.
  • Decentralisation-ready — Ed25519 key-based authentication ties into the broader Convex identity model without requiring centralised credential stores.

Specification

1. Public Access (No Authentication)

Venues MAY provide open, public access to grid operations and assets, enabling public services or sharing open-source capabilities without requiring prior authorisation.

Public access is the simplest mode and is appropriate for open data, demo services, and community resources.

Venues SHOULD NOT allow unauthorised users to consume excessive resources.

Venues SHOULD implement rate limiting on public endpoints, e.g. via a reverse proxy or application-level throttling.

2. Bearer Token (API Key)

Venues MAY offer authorisation using bearer tokens (commonly referred to as API keys).

The token MUST be passed by the client with every HTTPS request using the standard Authorization header:

Authorization: Bearer <token>

If the venue offers bearer-token authorisation, it has complete control over what privileges it grants to clients using any particular token. Token provisioning is out of scope for this specification and is managed by the venue operator (e.g. via a management portal, CLI, or out-of-band exchange).

Security considerations

  • Tokens MUST be treated as secrets and MUST NOT be logged, committed to version control, or transmitted over unencrypted channels.
  • Venues SHOULD support token revocation.
  • Venues SHOULD enforce token expiry where appropriate.

3. HTTP Basic Authentication

Venues MAY support HTTP Basic authentication as defined in RFC 7617.

Credentials are transmitted as a Base64-encoded username:password pair in the Authorization header:

Authorization: Basic <base64(username:password)>

Basic authentication MUST only be used over HTTPS to protect credentials in transit.

This mechanism is suitable for simple setups, internal tooling, or development environments where a lightweight credential model is sufficient.

4. OAuth 2.0

Venues MAY allow authentication using OAuth 2.0 with PKCE (RFC 7636).

OAuth enables delegated authorisation, allowing users to authenticate via an external identity provider (e.g. Google, GitHub, or a corporate IdP) without sharing their credentials with the venue.

Flow overview

  1. Client initiates an authorisation request to the venue's OAuth endpoint.
  2. Venue redirects the client to the identity provider for authentication.
  3. On successful authentication, the identity provider returns an authorisation code to the venue callback.
  4. The venue exchanges the code for an access token.
  5. The client uses the access token as a bearer token for subsequent API requests.

Requirements

  • Venues implementing OAuth MUST use PKCE to mitigate authorisation code interception attacks.
  • Access tokens SHOULD be short-lived; refresh tokens MAY be issued for long-lived sessions.
  • Venues MUST validate tokens on every request.

5. Ed25519 Self-Issued JWT

Venues MAY authenticate clients using self-issued JWTs signed with Ed25519 keys. This mechanism aligns with the Convex identity model, where accounts are identified by Ed25519 public keys, and with the W3C did:key method for self-sovereign identity.

The token names a principal in the sub claim and a signing key in the kid header. The venue verifies the signature with the kid key, then checks that the key is authorised for the principal. In the common self-certifying case the principal is a did:key and the authorised key is exactly the key embedded in it — no pre-registration is required, and any entity with an Ed25519 key pair can authenticate. A venue MAY additionally accept subjects it manages itself (named-user DIDs), for which the signing key must be a registered authentication key — see Subjects and authorised keys.

Client identity: did:key

The client's DID is computed from the Ed25519 public key using the did:key method:

  1. Take the 32-byte Ed25519 public key
  2. Prepend the multicodec prefix 0xed01 (Ed25519 public key)
  3. Encode with multibase base58btc (prefix z)
  4. Result: did:key:z6Mk...

This DID is self-certifying — the public key is embedded in the identifier itself, requiring no external resolution.

Subjects and authorised keys

The sub claim names the principal being authenticated. Two subject forms are supported:

  • Self-certifying (did:key) — the DID embeds the public key. The signing key is authorised if and only if it is the key encoded in sub. Works at any venue, with no registration.
  • Venue-managed subject — the DID of a named user managed by the receiving venue. The signing key is authorised if it is one of the subject's active registered authentication keys. Such a subject can authenticate only at the venue that manages it: venues MUST NOT resolve foreign subjects (e.g. another venue's users) through this mechanism — cross-venue caller identity uses the UCAN identity token (§6).

Where a venue maintains an authentication-key registry, the following invariants apply:

  • A subject MAY have multiple active keys (e.g. one per device); keys MAY be added and revoked over time.
  • A key MUST be bound to at most one subject per venue — otherwise a single key could authenticate as two principals.
  • A revoked key MUST NOT be silently reactivated; re-authorising a key requires an explicit new binding.

JWT structure

The client constructs a JWT with the following structure:

Header:

{
"alg": "EdDSA",
"typ": "JWT",
"kid": "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
}

Payload:

{
"iss": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"sub": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"aud": "did:web:venue.example.com",
"iat": 1706367600,
"exp": 1706367900
}
ClaimRequiredDescription
subREQUIREDThe principal: a did:key, or a venue-managed subject DID for which the signing key is registered
issRECOMMENDEDThe principal's DID — MUST equal sub when present (a token naming a different issuer is not self-issued and MUST be rejected by this mechanism); REQUIRED for venue-managed subjects
audRECOMMENDEDVenue DID or URL — prevents replay at a different venue
iatREQUIREDIssued-at timestamp (Unix seconds)
expREQUIREDExpiry timestamp (Unix seconds)
jtiOPTIONALUnique token ID for replay detection

The kid header identifies the signing key. Its canonical form is the key's bare Multikey string (z6Mk...); verifiers SHOULD also accept the did:key:<multikey> and <sub>#<multikey> forms (in the latter, the prefix MUST equal the token's sub). The kid key MUST be authorised for the sub principal as defined in Subjects and authorised keys. Note that kid identifies the key, not the principal — for a venue-managed subject it names a registered key that is distinct from the DID in sub.

Transport

The JWT is sent using the standard Authorization: Bearer header:

Authorization: Bearer eyJhbGciOiJFZERTQSIs...

This reuses the same header as bearer tokens and API keys. The venue distinguishes a self-issued JWT from an opaque token by decoding the JWT and checking for alg: EdDSA with a kid that decodes to an Ed25519 Multikey.

Flow overview

Client Venue
│ │
│ 1. Generate Ed25519 key pair (once) │
│ did:key:z6Mk... = encode(pubkey) │
│ │
│ 2. Create JWT: │
│ iss: did:key:z6Mk... │
│ aud: did:web:venue.example.com │
│ exp: <now + 5min> │
│ Sign with Ed25519 private key │
│ │
│ Authorization: Bearer <JWT> │
│ POST /api/v1/invoke │
│ ───────────────────────────────────────────▶ │
│ │
│ 3. Decode JWT, resolve signing key from kid
│ 4. Verify JWT signature with that key
│ 5. Check key is authorised for sub
│ 6. Validate iss = sub, exp, aud, iat
│ 7. (Optional) Resolve Convex account
│ │
│ 200 OK │
│ ◀─────────────────────────────────────────── │

Venue verification

Venues MUST perform the following validation steps:

  1. Decode the JWT and verify alg is EdDSA
  2. Resolve the signing key from the kid header (bare Multikey, did:key:<multikey>, or <sub>#<multikey> with the prefix equal to sub)
  3. Verify the JWT signature using that key
  4. Verify the key is authorised for the sub principal — for a did:key subject it MUST equal the key encoded in sub; for a venue-managed subject it MUST be an active registered authentication key of that subject
  5. If iss is present, validate that it equals sub (REQUIRED for venue-managed subjects)
  6. Validate exp > now (reject expired tokens)
  7. Validate iat <= now + clock_skew (reject tokens issued in the future)
  8. If aud is present, validate it matches the venue's own DID or URL; venues MAY require aud (audience policy)
  9. Validate exp - iat <= max_lifetime (reject tokens with excessively long validity)

Recommended validation parameters:

ParameterRecommended value
Clock skew tolerance30 seconds
Maximum token lifetime (exp - iat)5 minutes

Token lifetime

Tokens SHOULD be short-lived (recommended 5 minutes; the reference SDK's default is 300 seconds). Since the client holds the private key, generating a new JWT is effectively free (Ed25519 signing takes microseconds). Refresh tokens are unnecessary — when a token expires, the client simply signs a new one.

Optional Convex account resolution

After verifying the JWT signature, a venue MAY look up the Ed25519 public key on the Convex network to resolve a Convex account:

  1. Extract the 32-byte Ed25519 public key from the did:key
  2. Query the Convex network for accounts whose controller key matches
  3. If found — associate the request with the Convex account (e.g. #1337)
  4. If not found — the client is authenticated by did:key alone

This resolution is a venue-side decision. The client does not need to be aware of it. A venue not connected to the Convex network simply authenticates by did:key without account resolution.

Security considerations

  • Private keys MUST NOT leave the client and MUST NOT be transmitted over the network.
  • The exp and aud claims provide replay protection without server-side state.
  • Venues SHOULD reject tokens where exp - iat exceeds the maximum lifetime, preventing clients from creating excessively long-lived tokens.
  • For high-security environments, venues MAY track jti values within the token's validity window to detect replay of the exact same token.
  • This mechanism integrates naturally with Convex account keys, enabling on-chain identity verification.

6. UCAN Identity Token (Relayed Requests)

Venues MAY accept a caller identity from the request's ucans proof channel when the transport itself is unauthenticated. This is the identity mechanism for relayed cross-venue requests: an intermediary venue forwards the caller's tokens, and the receiving venue verifies the caller's own signature — placing no trust in the relay.

The proof channel

UCAN tokens accompany a request in the proof channel, separate from operation input — input is data and is persisted into job records (COG-8), so a credential there would leak into durable history. The channel has three carriers, all verified identically at ingress:

CarrierFormUse
Request body ucans fieldJSON array of UCAN JWT stringsRequests with a body (e.g. POST /api/v1/invoke)
X-Covia-Ucans headerThe same JWT strings, comma-separatedBody-less requests (e.g. job observation GETs)
Authorization: BearerA single UCAN JWTWhen the bearer slot is not carrying another token type

Encoding rules for the header:

  • Entries are separated by commas; whitespace around entries MUST be tolerated (each entry is trimmed) and empty entries ignored. A JWT cannot contain a comma, so the separation is unambiguous.
  • Senders SHOULD emit a single header line. (An intermediary that combines repeated lines with commas per HTTP field semantics yields a parseable value, but receivers read one line.)
  • Ordering carries no meaning: each token is self-contained — delegation chains travel nested in the token's prf field, so a single leaf JWT is a complete chain.
  • Tokens that fail verification are discarded at ingress; a discarded token never fails the request by itself (the absence of required authority does).
  • Venues MAY bound the number and size of tokens they accept.

Senders attach tokens explicitly from their own proof state — nothing relies on passive header propagation across hops (COG-15).

Identity tokens

An identity token is a UCAN with:

FieldValue
issThe caller's DID (signs the token)
audThe receiving venue's DID
attEmpty — the token grants nothing; it is pure proof of identity
expShort-lived expiry

The empty attenuation list makes the token unambiguous: it cannot be dual-used as a grant. The audience binding makes it unusable at any other venue.

Verification rules:

  1. The token MUST pass standard UCAN verification (signature, temporal bounds).
  2. The token's aud MUST equal the receiving venue's DID.
  3. The token's att MUST be empty.
  4. The mechanism applies only when the transport carries no Authorization identity — an authenticated transport peer (e.g. a relaying venue acting as itself) is the caller regardless of forwarded tokens.
  5. Two identity tokens with different issuers are ambiguous: the request MUST be rejected.

On success the caller is the token's iss, with the same standing as any authenticated identity (capability proofs audienced to it apply; the public-access ceiling does not).

Client SDK Support

The Covia SDKs provide a generic authentication interface that supports all mechanisms described above.

MechanismPython SDKJava SDK
Public (no auth)DefaultDefault
Bearer tokenBearerAuth(token)Supported
HTTP BasicBasicAuth(user, pass)Supported
OAuth 2.0PlannedSupported
Ed25519 JWTEd25519AuthSupported

Python SDK example

from covia import Grid
from covia.auth import BearerAuth, BasicAuth

# Public access (no auth)
venue = Grid.connect("https://venue.covia.ai")

# Bearer token
venue = Grid.connect("https://venue.covia.ai", auth=BearerAuth("my-token"))

# HTTP Basic
venue = Grid.connect("https://venue.covia.ai", auth=BasicAuth("user", "pass"))
# Ed25519 self-issued JWT (requires: pip install covia[signing])
from covia.auth import Ed25519Auth

# Generate a new identity — audience is auto-set from Grid.connect()
auth = Ed25519Auth.generate()
print(auth.did) # did:key:z6Mk...
venue = Grid.connect("did:web:venue.covia.ai", auth=auth)

# Or from a known seed (deterministic key)
auth = Ed25519Auth.from_seed(seed_bytes)
venue = Grid.connect("did:web:venue.covia.ai", auth=auth)

Custom authentication providers can be implemented by subclassing covia.auth.Auth:

from covia.auth import Auth

class ApiKeyAuth(Auth):
def __init__(self, key: str) -> None:
self._key = key

def apply(self, headers: dict[str, str]) -> None:
headers["X-Api-Key"] = self._key

Venue Discovery

Venues SHOULD advertise their supported authentication mechanisms via the A2A agent card (/.well-known/agent-card.json) using the securitySchemes field. This allows clients to discover the required authentication method before making API calls.

References