Versine supports Auth0 and Supabase.
1. Register the project
Sign in to Console and choose Create project. Have these ready:- Auth0
- Supabase
- 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.
Set up with a coding agent
Set up with a coding agent
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.
Terms of Service and Privacy Policy
Terms of Service and Privacy Policy
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
- Auth0
- Supabase
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_basicauthentication. - Scopes:
openid profile email. - PKCE: S256.
Security profiles
Security profiles
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.- Auth0
- Supabase
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
- Auth0
- Supabase
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.Identify agent sign-ins
Identify agent sign-ins
Versine adds Treat this as where the sign-in came from, not as a role or permission.
https://versine.com/claims/provider: "versine" to its
profile. Neither provider forwards it into your app’s tokens.- Auth0
- Supabase
Set it in a post-login Action keyed to the Versine connection:
Decide what agents can do
Decide what agents can do
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.
Link accounts
Link accounts
Account linking lets a user return through another provider to the same
account. With Auth0, require the user to sign in to both accounts and
consent. Never link by email alone. See Auth0 account linking.
Supabase links verified emails automatically; don’t add your own email-based
linking on top.
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 asprojects: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, untilclaimExpiresAt.- Don’t require email verification for unclaimed accounts.
- With Supabase, keep
emailout 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.
6. Receive webhooks
Versine sendsauthorization.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-Signatureagainst the raw body withVERSINE_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. Onclaimable.expired, disable the account.
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.claimedand the next sign-in reaches the same account with full access. - Confirm your server responds
200to each webhook. - Sign out and confirm access is denied.
Troubleshoot a failed sign-in
Troubleshoot a failed sign-in
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, withclient_secret_basic.invalid_request: check S256 PKCE, orstateand 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: only200counts as delivered. - Supabase returns
provider_email_needs_verification: removeemailfrom the project’s unclaimed scopes and setemail_optionalon the Supabase provider.