Skip to main content
Versine connects to your existing Auth0 tenant or Supabase project as an OpenID Connect (OIDC) provider. Agents sign in through it like any other user. Your app keeps control of accounts, sessions and permissions. Agents connected to Versine sign in as their person. Agents without Versine get a claimable account: a restricted account their person claims within 24 hours. Both use the same button.
Versine supports Auth0 and Supabase.

1. Register the project

Sign in to Console and choose Create project. Have these ready:
  • Auth0 domain: your tenant or custom domain, such as https://example.us.auth0.com.
  • Connection name: such as versine. You’ll use the same name in Auth0.
  • Callback URL: that domain followed by /login/callback, exactly.
  • Webhook URL: an HTTPS endpoint on your server. See step 6.
  • Lifecycle webhook URL: for claimable account events. It can be the same endpoint.
Continuing past Integration saves a draft and creates your credentials. Drafts can’t sign anyone in; choose Finish setup after steps 2–6.
Choose Use my AI assistant when creating the project. Console copies a prompt with the full integration guide and your project’s non-secret settings. Paste it into your coding agent with your repository open. Enter secrets into your auth provider and secret manager yourself.
Under Advanced, optionally add your Terms of Service and Privacy Policy URLs. People accept them in My before their first sign-in, when claiming an account, and again whenever you change a URL. Agents can’t accept for them. Leave both empty to skip this.

2. Connect your auth provider

In Auth0, open Authentication → Enterprise → OpenID Connect and create a connection:
  • Name: the connection name from step 1.
  • Discovery URL: https://auth.versine.com/.well-known/openid-configuration.
  • Client ID and secret: from your Versine project, not your Auth0 application.
  • Type: Back Channel, with client_secret_basic authentication.
  • Scopes: openid profile email.
  • PKCE: S256.
Confirm the callback Auth0 shows matches the one in your project. Then enable the connection for your application on the Applications tab.
Keep S256 PKCE, the default, unless Auth0 can’t use it on this connection. Choose Nonce only if Auth0 sends and validates a fresh nonce and state to Versine instead. PKCE between your app and Auth0 does not protect the separate connection from Auth0 to Versine.

3. Add the sign-in button

Add Are you an agent? to both your login and sign-up pages. Keep your existing sign-in options.
Point the button at Auth0’s login with your Versine connection:
With a server-side SDK, pass connection=versine to its login route. Let the SDK handle state, nonce and PKCE.

4. Connect user accounts

Identify users by Auth0’s verified user ID, such as oidc|versine|<subject>. Use email and name for profile information, not as account identifiers. Versine emails can be unverified (email_verified: false), so never link accounts by email.
Versine adds https://versine.com/claims/provider: "versine" to its profile. Neither provider forwards it into your app’s tokens.
Set it in a post-login Action keyed to the Versine connection:
Treat this as where the sign-in came from, not as a role or permission.
Agree which reads, writes and resources agents may use, and which actions need a person, such as billing, admin and deletion. Enforce it on your backend:
  • Allow the user’s own rights, limited to your agent allowlist.
  • Keep the sign-in source in your server session, not in client parameters.
  • Treat a missing source as an agent, not a person.
  • Keep restrictions through refresh, silent sign-in and account linking.

5. Limit claimable accounts

An agent without Versine signs up with a claimable account. Its email can’t receive mail, and it expires after 24 hours unless its person claims it. In Console, choose the Unclaimed product permissions these accounts get, such as projects:read. The default is none. After each Versine sign-in, look up the account state from your server:
  • 404: a regular Versine user. Continue as in step 4.
  • accountState: "unclaimed": allow only your unclaimed permissions, until claimExpiresAt.
  • Don’t require email verification for unclaimed accounts.
  • With Supabase, keep email out of Unclaimed OIDC scopes (Console does this for you). Supabase refuses sign-ins with an unverified email when email confirmation is on.
  • Save the state in the session. Full access starts with a fresh sign-in after the claim.
See Claimable accounts for the full flow and what to allow.

6. Receive webhooks

Versine sends authorization.completed to your webhook URL after each sign-in, and claimable account events to your lifecycle webhook URL. Webhooks notify your server; they don’t sign anyone in.
  • Verify X-Versine-Signature against the raw body with VERSINE_WEBHOOK_SECRET.
  • Store the event ID with a unique constraint and ignore duplicates.
  • Return exactly 200. Any other status is retried.
  • On claimable.claimed, update the email and end restricted sessions. On claimable.expired, disable the account.
See Webhooks for payloads and a verification example.

7. Test sign-in

  • Connect an agent using the agent setup guide. Ask it to sign in to your app and confirm it reaches a protected page.
  • Try a new user: confirm an account is created. Sign in again and confirm the same account is used.
  • Ask an agent without Versine to sign up. Confirm it gets only your unclaimed permissions.
  • Claim that account from its claim link. Confirm you receive claimable.claimed and the next sign-in reaches the same account with full access.
  • Confirm your server responds 200 to each webhook.
  • Sign out and confirm access is denied.
Check these first:
  • invalid_redirect_uri: match the project’s callback to your provider’s exactly, with no query.
  • invalid_client: use your Versine project’s client ID and secret in your provider, with client_secret_basic.
  • invalid_request: check S256 PKCE, or state and nonce for the nonce profile.
  • The agent is approved but the browser stays signed out: restart from your app’s sign-in button. Approval alone doesn’t create your app’s session.
  • A webhook is marked failed after 204: only 200 counts as delivered.
  • Supabase returns provider_email_needs_verification: remove email from the project’s unclaimed scopes and set email_optional on the Supabase provider.