Entity Auth

Environment (web):

NEXT_PUBLIC_CONVEX_URL=https://<deployment>.convex.cloud
EA_WEBAUTHN_RP_ID=auth.example.com # optional override for native apps
EA_WEBAUTHN_ALLOWED_ORIGINS=https://foo.example,https://bar.example # optional extra origins

API endpoints:

  • POST /api/auth/webauthn/begin/registration
  • POST /api/auth/webauthn/finish/registration
  • POST /api/auth/webauthn/begin/authentication
  • POST /api/auth/webauthn/finish/authentication

JS SDK usage:

import { SDK } from "@entityauth/auth-client";

// Register a passkey for current user (rpId/origins derived server-side)
await SDK.passkeys.register({
  workspaceTenantId: "default",
  userId: "entities:1",
});

// Sign-in with passkey (discoverable)
const result = await SDK.passkeys.signIn({ workspaceTenantId: "default" });
console.log(result.accessToken);

RP ID and origins (web):

  • RP ID is derived from request host as eTLD+1 (e.g., sub.example.co.uk -> example.co.uk).
  • Expected origins are computed as the current origin plus any origin entities linked to the workspace.
  • These are stored on the challenge and enforced at finish.

Swift (EntityKit) usage:

let config = EntityAuthConfig(baseURL: URL(string: "https://api.example.com")!)
let facade = EntityAuthFacade(config: config)
// Register a passkey for the current user via native APIs
let _ = try await facade.registerPasskey(userId: userId, rpId: host, origins: [origin])
// Sign in with a passkey (discoverable)
try await facade.signInWithPasskey(userId: nil, rpId: host, origins: [origin])

Apple AASA and entitlements (native):

  • Keep /.well-known/apple-app-site-association listing bundle IDs.
  • iOS/macOS apps must include Associated Domains with webcredentials:example.com.