veyns· developers

Integrate veyns

veyns is a standard OpenID Connect provider: Authorization Code + PKCE (S256), a token endpoint, refresh rotation, revocation, and logout, with ID tokens signed ES256 by default so any OIDC library verifies them. The drop-in SDK adds the human-check widget, the sign-in button, and signed action approvals on top of the same protocol.

Register your application in the console first: apps belong to your veyns account, and requests are only served for your registered origins and redirect URIs.

Option A: any OpenID Connect library

Point your library at the discovery document and use the code flow with PKCE. Client type is public (no client secret); subjects are pairwise.

issuer:        __ORIGIN__
discovery:     __ORIGIN__/.well-known/openid-configuration
flow:          authorization_code + PKCE (S256)
client_id:     from the console
redirect_uri:  exactly as registered
scopes:        openid login
id_token alg:  ES256 (default) or ML-DSA-44 (opt-in)

Option B: the drop-in SDK

<script src="__ORIGIN__/veyns.js" defer></script>

<!-- human check, where a captcha would sit -->
<div class="veyns-widget" data-client-id="your_app"
     data-callback="onVeynsVerified"></div>

<!-- passwordless sign-in -->
<div class="veyns-signin" data-client-id="your_app"
     data-callback="onVeynsSignin"></div>

<script>
  function onVeynsSignin({ claims, tokens }) {
    // claims.sub is the account key, private to your app.
    // tokens.refresh_token continues the session server-side.
  }
</script>

Approvals bind a signature to one exact action; the consent screen shows the statement verbatim and the token carries its digest:

const { claims } = await veyns.approve({
  statement: "Transfer $450.00 to Omar K.",
  details: { amount: "450.00", currency: "USD", to: "omar-k" }
}, { clientId: "your_app" });
// claims.veyns_action.digest is bound to exactly this action.

The SDK runs the same code + PKCE flow internally (popup, response_mode=web_message) and verifies every token against the JWKS before your callback fires.

ID token claims

ClaimMeaning
iss / audThe issuer and your client id.
subPairwise account key: stable for your app, meaningless anywhere else. No wallet key, device id, or biometric-derived value ever appears in a token.
nonce, iat, exp, auth_timeStandard OIDC; ID tokens live 5 minutes.
veyns_presencetrue: a person completed the ceremony.
veyns_intentpresence, login, or action. Check it matches what you asked for.
veyns_levelVA1: device wallet + server-verified screen-lock check (WebAuthn, user verification required). Palm hardware raises this when it ships.
veyns_actionApprovals only: { statement, digest }, digest = SHA-256 over canonical JSON of { statement, details } (keys sorted, no whitespace). Recompute and compare before executing anything.

Verify on your server

Treat browser results as UX. Before trusting a token server-side, verify it against the JWKS like any OIDC token (ES256 works with every JWT library), check iss, aud, exp, nonce, and for approvals compare veyns_action.digest against your own canonical digest of the action you intend to execute.

Endpoints

EndpointPurpose
GET /.well-known/openid-configurationDiscovery.
GET /jwks.jsonIssuer keys: ES256 (EC P-256) and ML-DSA-44 (AKP, JOSE PQC draft).
GET /authorizeCode flow entry; renders the ceremony from a server-side transaction, so the consent screen only ever shows the registered application name.
POST /tokenauthorization_code (+PKCE) and refresh_token grants. Refresh tokens rotate; reuse revokes the family.
GET /userinfoBearer access token → sub and presence claims.
POST /revokeRFC 7009 revocation.
GET /logoutEnds the veyns session on the browser; optional post_logout_redirect_uri.
POST /v1/clientsApp registration (requires a signed-in developer; use the console).

The trust model

An account owns one or more device wallets. Every ceremony requires two proofs the service verifies independently: the wallet's ML-DSA-44 signature over a server-built envelope (protocol version, client, intent, action digest, transaction lifetime), and a WebAuthn assertion with user verification, checked against the credential registered at enrollment. Accounts survive lost devices via one-time recovery codes and device linking, and individual devices can be revoked from the account page.

Sandbox boundaries

This is a sandbox deployment: storage is file-backed with hourly backups, registration is open to any veyns account, wallets are software keys (palm hardware raises the assurance level when it ships), and quotas default to 10,000 tokens per app per day. The protocol surface above is the production contract. Plain-language policies: security, privacy, terms.