+
+
+
+
+
+
+
+
Blog/Guides

AgentID with Supabase Auth: What Breaks and Why

BPBinoy Perera

What goes wrong after adding AgentID to Supabase Auth as a custom OIDC provider, and why: comma-separated scopes, the custom:agentid identifier, the three-provider limit on free projects, the claims allowlist for owner claims, what a missing owner claim means, and ES256 when you verify tokens yourself.

Guide
Guides
AgentID
supabase
troubleshooting
TL;DR

Adding agent sign-in to Supabase is a short setup, and most of what goes wrong afterwards traces back to four settings: how scopes are typed, what the provider is called, which claims Supabase keeps, and whether the agent may share its owner. This post maps each symptom to its cause, so you can tell a misconfiguration from a sign-in that is working as designed.

You add AI agent sign-in to Supabase by registering AgentID, the sign-in for AI agents from AgentMail, as a custom OpenID Connect (OIDC) provider in Supabase Auth. Once that works, the problems people hit come from four settings: the scope format, the provider identifier, the claims allowlist, and the owner permission on the agent's side.

None of them breaks the button. That is what makes them easy to miss. A sign-in completes, a user row appears, and only later does someone notice the agent has no name, or that the owner's email the product was built around never arrived. Each of those has a specific cause, and most have a one-line fix. This post walks through them in the order people usually find them, then covers what changes if your app verifies AgentID's tokens itself instead of leaving that to Supabase.

Why does AgentID work in Supabase but not look the way you expected?

AgentID works in Supabase as soon as the provider is enabled, but a working sign-in and the sign-in you designed are not the same thing. The Supabase guide is the setup reference and gets you to the first; this post covers the gap between the two. Here are the symptoms in one place:

SymptomCauseFix
Only the agent's ID and email come backThe scopes field was left empty, so the issuer fell back to openid emailType the scopes you need, separated by commas
A fourth custom provider can't be addedFree Supabase projects allow three custom providersRemove an unused custom provider; the limit is Supabase's, not AgentID's
Your sign-in code can't find the providerThe identifier was typed with its prefix, or the code calls a different nameThe provider is custom:agentid; type only agentid in the field
Owner claims are missing from the userSupabase drops custom claims that are not allowlistedAllowlist owner_sub, owner_name and owner_email
The sign-in waits instead of finishingThe app asked for owner data and the agent's key can't share itNothing on your side; the organization owner approves the sign-in
The allowlist isn't available on a self-hosted instanceSupabase Auth older than 2.192.0Upgrade Supabase Auth

The rest of this post explains the three causes that need more than a one-line fix. If you are still choosing where to put the button, adding a Sign in with AgentID button covers that side.

Why does Supabase want scopes separated by commas?

Supabase wants commas because its scopes field takes a comma-separated list, even though scopes in the OIDC request itself are space-delimited. AgentID's own reference lists them with spaces, which is where the mismatch creeps in. In Supabase, type them with commas.

The field matters more than it looks, because an empty one isn't an error. With no scopes, AgentID falls back to openid email, so the agent signs in with a stable subject and a verified address and nothing else. There is no name, no preferred_username and, most importantly for per-owner limits, no owner_sub, because all three come with the profile scope.

A useful starting set for most apps is openid,email,profile. Add owner_profile and owner_email only if the product needs the name and address of the person who owns the agent, because they put a real person's name and address in your database.

Where did the owner claims go?

Supabase threw them away. AgentID sent them, but Supabase keeps only the claims it knows about unless you add the rest to its claims allowlist, and there is no dashboard field for that. It is a one-time call from your server with the service role key, and the owner claims step in the guide has the exact code. After the next sign-in, the allowlisted claims appear under user_metadata.custom_claims.

Two details catch people here. The allowlist only keeps what AgentID actually sent, so owner_sub still needs profile, and owner_name and owner_email still need the owner scopes. And AgentID omits claims it didn't grant rather than sending them empty, so code that reads these fields should test whether they are present instead of expecting a null.

If you run Supabase yourself, the allowlist needs Supabase Auth 2.192.0 or later. On an older version the claims stay missing no matter what you allowlist.

What does a missing owner claim actually mean?

A missing owner claim means one of three things, and only one of them is a bug. The first is an open client: apps that skip registration and use a URL as their client ID never receive the owner's name or email. The Supabase setup creates a registered application, so this usually applies only if someone switched clients.

The second is the scopes. If the app didn't request owner_email, the token doesn't carry it, and if it didn't request profile, there is no owner_sub either. The third is the allowlist from the previous section, which is the actual bug.

What never happens is a registered app that requested owner_email receiving a finished sign-in without it. When the agent's AgentMail API key lacks the Provider: Share Owner permission, the agent can't finish the sign-in alone, and the organization owner approves it from their AgentMail account. From Supabase's side the sign-in simply takes longer, and when it completes the owner is there.

What changes if you verify AgentID tokens yourself?

If your app verifies AgentID's tokens itself rather than relying on Supabase, it has to accept ES256, because that is the only algorithm the issuer signs with. Libraries that assume RS256 reject valid tokens, which looks like a broken integration and is really a missing setting. The full set of values your library reads is in SSO for AI agents with OpenID Connect.

Check the signature against https://auth.agentid.com/v0/jwks.json, confirm iss is https://auth.agentid.com, and confirm aud is your exact client ID, which for a registered application is the ID the console issued rather than a URL. The published keys keep stable IDs and an overlap window, so rotation doesn't invalidate tokens in flight. Tokens last 10 minutes, and the full claim list is in the AgentID docs.

If you are on Clerk as well, the same questions come out differently there, and AgentID with Clerk covers that version. For the agent's side of the sign-in, the AgentID page on AgentMail explains how an agent gets an identity in the first place.

AgentID gives your agent a verified identity and its own email address. Free for apps to add.

FAQ

Let your agent sign in. Give it an AgentID and its own email address.