Skip to main content

Overview

Dashboard authentication uses WebAuthn (passkeys) and JWT session cookies to authenticate namespace owners. This allows owners to manage services, approve authorization requests, and configure their namespace through the Sigilum dashboard.
Dashboard auth is only needed for namespace owner management operations. Services authenticate using API keys (Bearer tokens), and agents use signed request headers.

Authentication Flow

The authentication flow follows the WebAuthn standard with passkeys:

Signup

Get Signup Options

GET /v1/auth/signup/options
endpoint
Request WebAuthn challenge and options for creating a new account.
Query Parameters:
namespace
string
required
Desired namespace (must be available)
Response:
challenge
string
Base64-encoded WebAuthn challenge
rp
object
Relying party information (name and ID)
user
object
User information for credential creation
pubKeyCredParams
array
Supported credential algorithms (ES256, EdDSA)
Example:
curl https://api.sigilum.id/v1/auth/signup/options?namespace=acme

Create Account

POST /v1/auth/signup
endpoint
Complete account creation with signed WebAuthn credential.
Request Body:
namespace
string
required
Namespace to register
passkey_name
string
Optional name for the passkey (e.g., “MacBook Pro”)
credential
object
required
WebAuthn credential response from navigator.credentials.create()
Response: Returns 201 Created with session cookie set. The Set-Cookie header contains the JWT session token.
After signup, the namespace is reserved and a DID document is created at did:sigilum:{namespace}.

Login

Get Login Options

GET /v1/auth/login/options
endpoint
Request WebAuthn challenge for authentication.
Query Parameters:
namespace
string
required
Namespace to authenticate
Response:
challenge
string
Base64-encoded WebAuthn challenge
allowCredentials
array
List of credential IDs allowed for this namespace

Authenticate

POST /v1/auth/login
endpoint
Complete authentication with signed WebAuthn assertion.
Request Body:
namespace
string
required
Namespace to authenticate
credential
object
required
WebAuthn assertion response from navigator.credentials.get()
Response: Returns 200 OK with session cookie set.

Session Management

Get Current User

GET /v1/auth/me
endpoint
Retrieve information about the currently authenticated user.
Authentication: Cookie-based session Response:
namespace
string
Authenticated namespace
settings
object
User settings and preferences
created_at
string
Account creation timestamp

Logout

POST /v1/auth/logout
endpoint
End the current session and clear the session cookie.
Authentication: Cookie-based session Response: Returns 200 OK with Set-Cookie header clearing the session.

Passkey Management

Get Passkey Options

GET /v1/auth/passkeys/options
endpoint
Request WebAuthn options for adding a new passkey to the account.
Authentication: Cookie-based session Response: WebAuthn credential creation options

Add Passkey

POST /v1/auth/passkeys
endpoint
Add a new passkey to the authenticated account.
Request Body:
passkey_name
string
Name for the new passkey (e.g., “iPhone”, “YubiKey”)
credential
object
required
WebAuthn credential response
Response: Returns the created passkey object (201 Created)

List Passkeys

GET /v1/auth/passkeys
endpoint
List all passkeys associated with the account.
Response:
passkeys
array

Rename Passkey

PATCH /v1/auth/passkeys/{id}
endpoint
Update the name of a passkey.
Request Body:
name
string
required
New passkey name

Delete Passkey

DELETE /v1/auth/passkeys/{id}
endpoint
Remove a passkey from the account.
Ensure you have at least one passkey remaining before deleting. Otherwise, you will be locked out of your account.

Account Settings

Update Settings

PATCH /v1/auth/settings
endpoint
Update account settings and preferences.
Request Body:
email_notifications
boolean
Enable or disable email notifications
webhook_failures_notify
boolean
Receive notifications for webhook delivery failures

Delete Account

DELETE /v1/auth/account
endpoint
Permanently delete the namespace and all associated data.
This action is irreversible. All services, API keys, authorization requests, and webhooks will be permanently deleted.
Authentication: Requires reauthentication (recent passkey verification)

Session Cookies

Session cookies are HTTP-only, secure, and have the following properties:
  • Name: sigilum_session
  • Duration: 7 days (configurable via GATEWAY_AUTH_SESSION_HOURS)
  • SameSite: Lax
  • Secure: true (HTTPS only)
The cookie contains a signed JWT with the namespace claim:
{
  "namespace": "acme",
  "iat": 1234567890,
  "exp": 1235172690
}

Security Considerations

WebAuthn provides strong cryptographic authentication:
  • Phishing resistant: Credentials are bound to the origin
  • No shared secrets: Private keys never leave the authenticator
  • Replay protection: Each authentication uses a unique challenge
  • Attestation: Optional device attestation for high-security scenarios
Sessions are protected with:
  • HTTP-only cookies: JavaScript cannot access tokens
  • Secure flag: Transmitted only over HTTPS
  • SameSite: CSRF protection
  • JWT signing: HMAC-SHA256 with server secret
  • Expiration: Automatic session timeout
Authentication endpoints have strict rate limits:
  • Signup: 5 attempts per IP per hour
  • Login: 10 attempts per namespace per hour
  • Failed attempts trigger exponential backoff

Browser Integration Example

Complete signup flow using the WebAuthn browser API:
// Step 1: Get signup options
const optionsResponse = await fetch(
  'https://api.sigilum.id/v1/auth/signup/options?namespace=acme'
);
const options = await optionsResponse.json();

// Step 2: Create credential
const credential = await navigator.credentials.create({
  publicKey: {
    challenge: Uint8Array.from(atob(options.challenge), c => c.charCodeAt(0)),
    rp: options.rp,
    user: options.user,
    pubKeyCredParams: options.pubKeyCredParams,
    authenticatorSelection: {
      authenticatorAttachment: 'platform',
      userVerification: 'required'
    }
  }
});

// Step 3: Complete signup
const signupResponse = await fetch('https://api.sigilum.id/v1/auth/signup', {
  method: 'POST',
  credentials: 'include', // Include cookies
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    namespace: 'acme',
    passkey_name: 'MacBook Pro',
    credential: {
      id: credential.id,
      rawId: btoa(String.fromCharCode(...new Uint8Array(credential.rawId))),
      response: {
        clientDataJSON: btoa(String.fromCharCode(...new Uint8Array(credential.response.clientDataJSON))),
        attestationObject: btoa(String.fromCharCode(...new Uint8Array(credential.response.attestationObject)))
      },
      type: credential.type
    }
  })
});

// Session cookie is now set
console.log('Authenticated!');

Next Steps

Services Management

Create services and generate API keys

Authorizations

Approve agent authorization requests

Namespaces

View authorization requests for your namespace

Dashboard

Use the web dashboard instead of API calls

Build docs developers (and LLMs) love