Security basics
"Unsupported provider: provider is not enabled" in Supabase
"Unsupported provider: provider is not enabled" means Google sign-in is off in your Supabase project. How to turn it on, and fix redirect_uri_mismatch.

In short
- "Unsupported provider: provider is not enabled" means the Supabase project your app sent the person to has Google sign-in switched off. Turn it on under Authentication, Sign In / Providers, in that same project.
- Google then checks a list of its own. Your Supabase callback URL has to be on your OAuth client's Authorized redirect URIs, letter for letter, or Google answers redirect_uri_mismatch.
- The Client Secret goes into the Supabase dashboard and nowhere else. Your app's code never needs it.
You add a "Sign in with Google" button to your app and press it. Instead of Google's account picker, your browser shows this:
{"code":400,"error_code":"validation_failed","msg":"Unsupported provider: provider is not enabled"}
The address bar shows your Supabase project, something like
https://abcdefghij.supabase.co/auth/v1/authorize?provider=google&redirect_to=….
You built the app with Lovable, Bolt, v0, Cursor, Claude Code or Replit, the
button came with the code, and nothing in that code looks wrong.
"Unsupported provider: provider is not enabled" means Supabase Auth, the part of
Supabase that signs people in, has Google switched off in the project your app
talks to. The fix is one switch and two values you get from Google. After that,
Google checks a list of its own, and that list is where the next error,
redirect_uri_mismatch, comes from.
The trap is in that second list. The address that feels right for it is your own app's, and Google never uses it, because Google never sends anyone to your app.
What does "Unsupported provider: provider is not enabled" mean?
It means Supabase refused to start a Google sign-in, because Google is switched off in the project that received the request.
Signing in with Google is a round trip through two front desks. Your app sends the person to Supabase's desk. Supabase sends them on to Google's desk to prove who they are, Google sends them back to Supabase, and Supabase sends them home to your app, signed in. Each desk sends people only where its own settings allow. This message is Supabase's desk saying its Google counter is closed.
In Supabase Auth's
source,
a request to /auth/v1/authorize first looks the provider up, and any problem
with it comes back as a 400 with the code validation_failed and
Unsupported provider: in front of the reason. provider is not enabled is
the first thing that lookup checks.
So Google never saw the request, and nothing in Google's console will explain it. Your app never sees the error either: Supabase's JavaScript library sends the whole browser to that address, so the page that fails belongs to Supabase, and your app's console stays empty.
The same message appears for GitHub, Apple or any other provider that is switched off, and the switch is in the same place. Apps on Lovable's built-in backend are set up differently: Lovable's authentication docs list Google as "managed by Lovable with no setup, or your own Google Cloud OAuth credentials." This post is for apps on your own Supabase project, whichever tool built them.
Is it the right Supabase project?
Check that before you change anything, because the error page names the project that answered.
The address on the error page starts with your project's reference, the string
of letters before .supabase.co. Open your Supabase dashboard and look at its
own address bar: the same reference follows /project/. If the two differ, your
app talks to another project, such as one a builder created for you or a copy
you made for testing. That is the project where Google has to be switched on.
How to fix "Unsupported provider: provider is not enabled"
Create an OAuth client in Google, then switch Google on in Supabase with the two values it gives you. Supabase's Google sign-in guide has the steps; here they are in the order the two consoles ask for them.
In Supabase, copy the callback URL first. Go to Authentication, then
Sign In / Providers, and open Google. The panel shows a Callback URL with
a Copy button. It looks like https://<project-ref>.supabase.co/auth/v1/callback.
In Google Cloud, create the client. On the Clients page of the Google Auth Platform, create an OAuth client ID of the type Web application.
- Under Authorized JavaScript origins, add your app's address, such as
https://yourapp.com. - Under Authorized redirect URIs, paste the callback URL you copied from Supabase.
- Press Create, and copy the Client ID and the Client Secret straight away. Google's help page on OAuth clients says you "will only be able to view and download the full client secret once, at the time of its creation."
Back in Supabase, switch it on. Turn on Enable Sign in with Google, paste the Client ID into Client IDs and the secret into Client Secret (for OAuth), and save. The dashboard will not save Google switched on without a Client ID, but it does save with the secret field empty. That field's own description says the secret is for "the OAuth flow on the web", and a button in a web app is exactly that flow.
Then press your button again. If the message still starts with "Unsupported provider", its ending says what is left:
| The message ends in | What it means | What to change |
|---|---|---|
provider is not enabled | Google is off in the project that answered | Switch it on in that project |
missing OAuth client ID | Google is on with no Client ID saved | Paste the Client ID |
missing OAuth secret | Google is on and the secret field is empty | Paste the secret, or press Add Secret on the client in Google if you no longer have it |
Provider … could not be found | Your code asks for a provider Supabase does not have | Use google as the provider in signInWithOAuth |
Why Google then says redirect_uri_mismatch
Because your callback URL is not on the client's list, written exactly as Supabase sends it.
This is the second desk. When Supabase starts the sign-in, it hands the person to
Google with a note saying where to send them back: your project's callback URL.
Google checks that note against Authorized redirect URIs on the client you
created. Its
OAuth documentation
describes the failure in one line: "The redirect_uri passed in the
authorization request does not match an authorized redirect URI for the OAuth
client ID."
The match is exact. The same page says "the http or https scheme, case, and
trailing slash ('/') must all match." So an entry ending in /auth/v1/callback/,
with a slash at the end, will not match the address Supabase sends.
Your own app's address does nothing on this list. Google sends people back to
Supabase, so the only address it ever checks is Supabase's callback. Your app's
address belongs on the other desk's list, Supabase's Redirect URLs, which decides
where Supabase sends people at the very end. When that list is wrong, people
come back signed in on localhost:3000 instead, and
that has a page of its own.
After you save, give Google a little time. Its help page on OAuth clients says "It may take 5 minutes to a few hours for changes made to these settings to take effect."
Where the Client Secret belongs
In the Supabase dashboard, and nowhere else. Your app's code never needs it.
The Client ID is public: it travels in the address of Google's sign-in page,
where anyone can read it. The Client Secret is what proves to Google that a
request comes from your side, and in this setup only Supabase holds it. When your
app calls signInWithOAuth, the library sends the browser to Supabase, and
Supabase Auth is the one that talks to Google with the secret.
So if your builder put the secret into your app's code, or into a variable whose
name starts with VITE_ or NEXT_PUBLIC_, it is in every visitor's browser.
Those variables are public by design.
Google's help page is plain about it: "Never add client secrets directly in your
code or check them into version control systems such as Git or Subversion."
Replace it on the client's page in Google's console: press Add Secret, paste
the new secret into Supabase, then Disable the old one and delete it. Take
the old value out of your code as well.
Checking what your live app hands to visitors does not need the builder open. Our free scan reads your live app the way a visitor's browser does and reports the secret keys it recognises, along with tables that answer anyone and missing headers. It takes about 20 seconds and needs no account: scan your app.
Looking after the app people now sign in to
Once people sign in with Google, their accounts live in your Supabase project, and the app they sign in to changes with every deploy.
Reeve Monitor keeps checking your live app:
- whether it is up, every 60 seconds
- all nine checks every hour, on up to three apps, including secret keys in the code your app sends to visitors
- a message when a result changes, so a key that ships in a later deploy reaches you without you going to look
- a monthly report, in plain language, of what it saw
Reeve Care keeps a copy of your Supabase database, accounts included:
- an encrypted copy on a schedule, on Reeve's own storage in the EU, outside your Supabase account
- the auth schema, where Supabase keeps each user and the Google identity they signed in with, so they come back with everything else
- each copy verified before it counts, by counting the rows in every table
- your uploaded files as well, once you connect a Storage credential
- a one-click restore, with a safety copy of the current state taken first
- everything Monitor does
What to do now
What to do
- Read the project reference on the error page, and switch Google on in that project under Authentication, Sign In / Providers.
- Create a Web application client in Google, with your Supabase callback URL under Authorized redirect URIs, exactly as Supabase shows it.
- Paste the Client ID and the Client Secret into the Google panel in Supabase, and save.
- If Google answers redirect_uri_mismatch, compare the two addresses letter for letter, then allow a few minutes for Google's change to apply.
- Keep the Client Secret in Supabase only. If it ever went into your app's code, add a new one in Google and disable the old.
If people get through Google and then land on the wrong page, the redirect settings post picks up from there. The 10-minute security checklist covers what else to look at before launch.
FAQ
Why does Google sign-in open a page of JSON with validation_failed?
Your app sent the browser to your Supabase project's /auth/v1/authorize address, and Supabase answered there instead of passing the person on to Google. The page reads {"code":400,"error_code":"validation_failed","msg":"Unsupported provider: provider is not enabled"}. Your app never receives that answer, which is why its console shows nothing. Switch Google on under Authentication, Sign In / Providers.
I switched Google on and still get the error. Why?
Usually your app talks to a different Supabase project from the one you changed. The address on the error page starts with the project's reference, the letters before .supabase.co; compare it with the reference in your dashboard's address bar. If they match, read the end of the message: "missing OAuth secret" means the Client Secret field is still empty.
What goes in Authorized redirect URIs for Supabase?
Your project's callback URL, https://<project-ref>.supabase.co/auth/v1/callback, copied from the Google entry on the Sign In / Providers page. Google sends people back to Supabase, and Supabase sends them on to your app, so your app's own address belongs on Supabase's Redirect URLs list instead.
Do I have to publish my Google app or add test users?
Not for a sign-in that asks only for name, email address and profile, which is all Supabase asks Google for unless your code adds scopes. Google's page on app audiences says the users of such an app do not need to be on the test user list. Ask for more, such as access to Drive, and the testing limits apply.
I use a custom domain for Supabase. Which callback URL does Google need?
Both. Supabase's custom domain guide says to add the custom domain's callback, such as https://api.example.com/auth/v1/callback, in the provider's own console, in addition to the project's supabase.co callback.