Why base44 google authentication is not working
Base44 Google authentication is not working for one of three root causes: a custom Google Cloud OAuth 2.0 client that is missing Base44's one callback URI or your app's domain as its JavaScript origin, or whose secret no longer matches the one saved in Base44; an OAuth consent screen left in Testing publishing status while the sign-in asks for more than name, email and profile, which limits sign-ins to up to one hundred listed test users; or a protected route in your own code that decides the user is signed out before base44.auth.me() has answered. The default Google login runs on Base44's own credentials, so the first two apply only once you switch to custom Google OAuth. Identifying which of the three applies takes under two minutes — read the error code Google shows, or note that there is none. The full fix for any of the three ships in under an hour.
Match your Google error code to the cause
Google names the reason in an error code, and each code below points at one cause. Google's docs say requests to its authorization endpoint "may display user-facing error messages instead of the expected authentication and authorization flows," so look for the code on Google's page rather than in your app's URL. Read it before you change a setting.
Error 400: redirect_uri_mismatch
Google's own definition is narrow: "The redirect_uri passed in the authorization request does not match an authorized redirect URI for the OAuth client ID," and the comparison is unforgiving — "Note that the http or https scheme, case, and trailing slash (/) must all match." The part Google's docs cannot tell you is which string a Base44 app sends, and it is not your own domain. A custom Google OAuth client on Base44 takes exactly one Authorized redirect URI, https://app.base44.com/api/apps/auth/callback, and an app SSO provider takes https://app.base44.com/api/apps/{{APP_ID}}/auth/sso/callback with your app ID substituted in (app SSO needs an Enterprise plan, Business or Enterprise, on workspaces created on or after 1 October 2026, or Elite and higher on older workspaces). Your app's own hostname goes in Authorized JavaScript origins, not in the redirect list — putting it in the redirect list in place of Base44's callback produces exactly this error. Google's docs also name a JavaScript origin that is not on the client as a cause, so check that field holds your app's domain. On the default Google login the client is Base44's, so there is nothing of yours to fix in Google Cloud. Base44 also gates custom Google OAuth behind a Builder plan or higher, a connected custom domain, and a billing method on the Google Cloud project, and expects the Data Access scopes openid and https://www.googleapis.com/auth/userinfo.email. Go to Fix 1.
Error 403: access_denied — Testing status plus extra scopes
Google limits a project in Testing publishing status "to up to 100 test users listed in the OAuth consent screen," and "Authorizations by a test user will expire seven days from the time of consent," along with any refresh token issued to them. The part that matters on Base44 is Google's exception: when an app requests only name, email address and profile (the openid, userinfo.email and userinfo.profile scopes), "your users do not need to be in the trusted user list, they will not see a warning message, and their authorizations will not expire after 7 days." Base44's custom setup selects openid and userinfo.email, so Testing status alone should not lock anyone out. If outside accounts get access_denied, read the scope parameter on the failing authorization request: anything beyond name, email and profile brings the Testing limits back, and publishing lifts them, since In production status is "available to any user with a Google Account." If the scopes are basic and only some accounts fail, Google also notes that a Google Workspace may control which third-party apps access its data. Go to Fix 2.
Error 403 on every account outside your company domain
The OAuth client's user type is Internal rather than External. Google's rule: projects associated with a Google Cloud Organization can configure Internal users "to limit authorization requests to members of the organization" — so the client is working exactly as configured and no amount of publishing will admit an outside account. Switch the user type to External, or accept the restriction deliberately. Note that this is only reachable on a custom OAuth client: if your app runs on Base44's default Google login, you do not own the client and cannot set this at all. Go to Fix 2.
Error 401: invalid_client
Spec-defined, and it means what it says — RFC 6749 §5.2 defines invalid_client as "Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)." Google's own error list is blunter: "The OAuth client secret is incorrect." On Base44, check for credential drift before suspecting a code bug: the Client ID or Client Secret stored under Dashboard → Settings → Authentication no longer matches the Google Cloud client, for example because the secret was rotated in Google Cloud and never re-pasted into Base44. Go to Fix 1.
No error at all — the redirect completes and loops back to /login
This is the row Google's documentation structurally cannot write, because nothing on Google's side went wrong. The consent screen finished, Google handed the sign-in back to Base44, and Base44 sent the user to the path your login button passed to loginWithProvider() (/ if it passed none). Then a protected route in your own code checked for a user before base44.auth.me() had answered, found none, and redirected to the login screen. The tell is that a refresh fixes it. Go to Fix 3, then Fix 4.
Sign-in works, but the consent screen still says base44.com
Not a failure. Per Base44's documentation, the base44.com name or badge persists until Google approves your custom project, which can take up to five days after you publish the app and submit it. Nothing to fix; finish the submission and wait.
You shipped a Base44 app with Google sign-in. It worked when you tested it locally. You pushed to production and the first real user reports that clicking Sign in with Google does nothing, or loops back to the login screen, or shows a Google error page. You sign in yourself and it works. You sign in from an incognito window with a different Google account and it fails.
This is a sibling of the white-screen 405: both can end with a protected page that ran before the app knew who was signed in. Google sign-in adds two configuration failure modes that email-and-password login does not have, the OAuth client and the consent screen. Three root causes in total, all fixable in under sixty minutes.
The user-facing damage is severe. Every failed Google sign-in is either a refresh, a switch to email-password if you offer it, or churn. A user who hits a broken OAuth flow may assume the app is broken and leave instead of refreshing. The conversion penalty is invisible until you instrument the sign-in flow and start counting.
What causes base44 google authentication failures
Three distinct root causes, and an app can hit more than one at once.
Misconfigured Google Cloud OAuth client. A custom Google sign-in on Base44 runs against a Google Cloud OAuth 2.0 client that you own; the default Google login uses Base44's credentials instead, so this cause applies once you switch to custom OAuth. Base44's setup guide fills in two fields on that client: Authorized JavaScript origins gets your app's domain, and Authorized redirect URIs gets one entry, https://app.base44.com/api/apps/auth/callback. The guide gives no per-environment variants, so there is no list of localhost, preview and www callbacks to keep in sync. If Base44's callback is missing or mistyped — a trailing slash, http:// instead of https://, your own domain in its place — Google answers the authorization request with redirect_uri_mismatch and the flow stops on Google's error page. If the Client ID or Client Secret saved in Base44 no longer matches the client, the failure is invalid_client.
OAuth consent screen in Testing, with scopes beyond sign-in. Google gives every OAuth app a publishing status: Testing or In production. In Testing, Google limits authorization to up to one hundred test users listed on the consent screen, and everyone else hits an access_denied error — unless the app requests only name, email address and profile (openid, userinfo.email, userinfo.profile), which Google exempts. Base44's custom setup selects openid and userinfo.email, so this cause applies when the sign-in request asks for more than that. It can reach launch because the developer is a listed test user and never tried an outside account. The fix is to drop the scope you do not use or click Publish app. If the extra scope is sensitive or restricted (Drive, Gmail, Calendar), Google requires verification, which is not instant.
A protected route that decides before Base44 answers. This is the Google-flavored variant of the white-screen 405 race we documented at /fix/base44-white-screen-405-after-login. After the user finishes Google's consent screen, Google returns them to Base44, and Base44 sends them on to the path your login button passed to loginWithProvider(). If a protected route on that path decides who is signed in before base44.auth.me() has answered — from component state that starts out empty, say — it sees no user, redirects to /login, and the user lands back at the sign-in screen: what looks externally like a redirect loop. The tell is that a refresh fixes it. Base44's SDK has no auth-state listener to wait on; its own SDK guide says to call me() when you need the user.
Sources: Base44's login and registration guide and SDK auth reference, Google's OAuth 2.0 documentation on redirect URI validation and authorization errors, Google Cloud's help page on app audience and publishing status.
How to confirm base44 google auth failure (reproduction)
Run these in order. Each step rules out a specific failure mode.
-
Open the live app in a clean incognito window. Use a Google account that has no role on the Google Cloud project and is not on the Test users list. Trigger the Google sign-in.
-
Open DevTools, Network tab, with Preserve log enabled before clicking the button. This is critical — without Preserve log, the redirect chain wipes itself from the panel and you cannot see what failed.
-
Note what Google shows. If the flow stops on a Google error page, note the code:
redirect_uri_mismatch,access_deniedorinvalid_client. A redirect URI or client ID failure does not come back as a URL parameter: OAuth's spec says the server "MUST NOT automatically redirect the user-agent to the invalid redirection URI." If there is no Google error and the app loops back to /login, skip to step 7. -
Read the
redirect_uriquery parameter on the authorization request to accounts.google.com. On a custom client it must appear verbatim on the OAuth client's Authorized redirect URIs list. Base44's guide gives the one value to register:https://app.base44.com/api/apps/auth/callback. -
Open the Google Cloud Console. Navigate to APIs and Services → Credentials → the OAuth 2.0 Client ID Base44 is using. Confirm the Authorized redirect URIs list contains Base44's callback exactly, the Authorized JavaScript origins list contains your app's domain, and the Client ID and Client Secret match what is saved in Base44 under Dashboard → Settings → Authentication.
-
Check the scopes and the publishing status. Read the
scopeparameter on the request from step 4, then open the consent screen's Audience and Data Access pages. Testing status limits sign-in to listed test users only when the request asks for more thanopenid,emailandprofile. Anything Google marks Sensitive or Restricted needs verification before you publish. -
Watch what your app does on the way back. After Google, the browser comes back through Base44 and lands on the path your login button passed to
loginWithProvider(). If your app redirects to /login before its request for the signed-in user has completed, a route check is deciding too early. -
Test the same flow with an account on the Test users list. If listed accounts get through and everyone else gets
access_denied, you are in the Testing-status case. If every account fails, look at the OAuth client or the route check. -
Inspect local storage after the failed sign-in. Base44 stores authentication tokens in the browser's localStorage, so open Local storage for your app's origin in DevTools. If a token is present and a refresh signs the user in, the sign-in worked and a route check ran too early. If there is none, the sign-in never completed: go back to the Google error code.
If step three shows redirect_uri_mismatch or invalid_client, jump to the OAuth client fix. If steps six and eight point at Testing status, jump to the consent screen fix. If steps seven and nine point at the route check, jump to the auth gate.
How to fix base44 google authentication not working — step-by-step
Four fixes for three root causes: Fixes 1 and 2 are Google Cloud settings, Fixes 3 and 4 are code. Apply the ones your reproduction pointed to.
Fix 1: Configure the Google Cloud OAuth client correctly
This fix is for custom Google OAuth. On the default Google login, the OAuth client is Base44's, and there is nothing of yours to configure in Google Cloud.
Navigate to console.cloud.google.com and select the project your Base44 app uses. Open APIs and Services → Credentials → the OAuth 2.0 Client ID. You should see two lists, and Base44's setup guide puts one entry in each.
Authorized JavaScript origins holds your app's domain:
https://yourapp.com
Authorized redirect URIs holds Base44's callback, exactly as Base44's guide gives it:
https://app.base44.com/api/apps/auth/callback
Google sends the user back to that callback, not to a path in your app, so there are no per-environment callbacks to register: no localhost, preview or www entries, and your own domain does not belong in this list. Google's matching is exact — "the http or https scheme, case, and trailing slash (/) must all match" — so paste the string rather than retyping it.
While you are on the client, compare its Client ID and Client Secret with what is saved in Base44 under Dashboard → Settings → Authentication. If the secret was rotated in Google Cloud, paste the new one into Base44 and click Update; a stale secret is the invalid_client case.
Save. Google says a change to an OAuth client can take from five minutes to a few hours to take effect. Retry the sign-in. The redirect_uri_mismatch error should be gone.
Fix 2: Publish the OAuth consent screen
In the same Google Cloud project, open the OAuth consent screen's Audience page. Look at Publishing status.
Before you change it, confirm your scopes on the Data Access page and in the scope parameter of the sign-in request. Base44's setup guide selects two:
openid
https://www.googleapis.com/auth/userinfo.email
Both are classified as non-sensitive, and Google exempts an app that requests only name, email address and profile from the Testing limits: its users do not need to be on the test user list. If those are all the request asks for, Testing status is not what is blocking your users; go back to the error code.
If the request asks for any other scope, the Testing limits apply. If that scope is marked Sensitive or Restricted — Drive, Gmail, Calendar — publishing also triggers Google verification, which is not instant and gates a public launch. A basic Base44 sign-in does not need these scopes. Remove anything you do not actually use, then click Publish app.
Once published, the Test users list no longer limits sign-in: Google makes an In production app available to any user with a Google Account.
Fix 3: Gate every protected route on base44.auth.me()
The post-Google redirect loop is the same shape as the white-screen 405 race. The user is back from Google, but a protected route decided who was signed in before Base44 answered, saw no user, and redirected to /login.
The fix is an AuthGate component that does not render its children until base44.auth.me() has answered. There is no auth-state listener or ready promise to wait on: Base44's SDK guide lists onAuthStateChanged() as a hallucinated name and says to call me() when you need the user. me() resolves with the signed-in user, and the same guide shows it failing with a 401 when the token is expired or invalid. The white-screen 405 fix covers the same race after an email-and-password login.
import { useEffect, useState, type ReactNode } from "react";
import { base44 } from "@/api/base44Client";
export function AuthGate({ children }: { children: ReactNode }) {
const [ready, setReady] = useState(false);
useEffect(() => {
let cancelled = false;
async function check() {
try {
// Ask Base44 who is signed in before anything protected renders.
const user = await base44.auth.me();
if (cancelled) return;
if (user) setReady(true);
else base44.auth.redirectToLogin(window.location.href);
} catch {
// me() rejects, with a 401 for an expired or invalid token.
if (!cancelled) base44.auth.redirectToLogin(window.location.href);
}
}
check();
return () => {
cancelled = true;
};
}, []);
if (!ready) return <div className="auth-loading" aria-busy="true" />;
return <>{children}</>;
}
redirectToLogin() sends the user to the app's login page and brings them back to this URL after they sign in. Wrap every route that loads authenticated data, not just the dashboard: any protected page can be the first one to load after a sign-in.
Fix 4: Start sign-in with loginWithProvider() and land on a gated page
The sign-in button is the other half of the race. Base44's SDK starts Google sign-in with one documented call, base44.auth.loginWithProvider('google', fromUrl), where fromUrl is where Base44 sends the user after a successful sign-in (/ if you leave it out). If your button calls signInWithProvider('google') or signInWithGoogle(), it is calling a name Base44's own SDK guide lists as hallucinated; replace it.
import { base44 } from "@/api/base44Client";
// Base44 sends the user to the second argument after a successful sign-in.
export function GoogleSignInButton() {
return (
<button
type="button"
onClick={() => base44.auth.loginWithProvider("google", "/dashboard")}
>
Sign in with Google
</button>
);
}
Do not build an /auth/callback page that reads a code from the URL or polls local storage for a token. Google returns the user to Base44's callback, not to your app, and the SDK stores the token itself; its auth module documents no callback handler and no storage key name. Your job is the landing path: make sure the route behind fromUrl is wrapped in the AuthGate from Fix 3, so the first thing it does on arrival is ask base44.auth.me().
Bonus: the safety net — send 401s back to login
Same idea as Layer 3 of the white-screen 405 fix, built on the SDK's documented error shape. Wrap the SDK calls a protected page makes in a helper that bounces the user back to login when a call fails with a 401, the status Base44's SDK guide shows for an expired or invalid token:
import { base44 } from "@/api/base44Client";
export async function withAuthFallback<T>(call: () => Promise<T>): Promise<T> {
try {
return await call();
} catch (err) {
if ((err as { status?: number } | null)?.status === 401) {
base44.auth.redirectToLogin(window.location.href);
}
throw err;
}
}
// On a protected page:
// const todos = await withAuthFallback(() => base44.entities.Todo.list());
This catches the residual case where Fix 3 and Fix 4 both pass but a token expires mid-session or a future change reopens the race. The user gets bounced to a re-login instead of staring at a white screen with no error.
How long does it take to fix base44 google authentication?
Timeline depends on which root causes are active.
- Fix 1 (OAuth client): Five minutes of console clicks, then Google's propagation, which Google puts at five minutes to a few hours.
- Fix 2 (scopes and consent screen): Two minutes to drop an extra scope or publish. If a sensitive scope stays, the publish triggers Google verification, and that wait is outside your control. A basic sign-in does not need sensitive scopes, so remove them first.
- Fix 3 (AuthGate component): Fifteen to thirty minutes to ship across every protected route. The component itself is small; the work is finding every route that mounts authenticated data.
- Fix 4 (sign-in button and landing path): Fifteen minutes to point the button at
loginWithProvider()with a gated landing path and delete any hand-built callback page.
Verification can take longer than the fixes themselves — you need to confirm the round-trip across at least desktop Chrome, mobile Safari, mobile Chrome, and an incognito window. Anything less and you leave a measurable failure rate in the wild.
After shipping, the first real users start succeeding on Google sign-in immediately — there is no propagation gap once the OAuth client and consent screen are correct.
DIY vs hire decision
DIY this if: Your app is in early production, you can capture the failing sign-in in DevTools, and the error code matches one of the three root causes. Fixes 1 and 2 are pure console configuration — anyone with admin access to the Google Cloud project can ship them in fifteen minutes. Fixes 3 and 4 are client-side code and follow the patterns documented here.
Hire help if: You are seeing the redirect loop on a production app that is converting traffic, you cannot reproduce locally, your team has not shipped an OAuth flow before, or the failure rate is not zero after you have shipped fixes 1 through 4. A specialist who has shipped these fixes before skips the debugging and verifies across the full browser matrix. If that is where you are, a scoped Base44 bug-fix sprint buys the diagnosis and the browser-matrix verification as one fixed-price piece of work.
Need google auth fixed before a launch?
Our fix-sprint diagnoses your Google sign-in failure on the first call, validates the Google Cloud OAuth client configuration, publishes the consent screen with the right scope set, ships the AuthGate, the gated sign-in landing path, and the auth-error safety net, then verifies zero failures across one hundred cold-start sessions on desktop and mobile. Fixed price, forty-eight-hour turnaround.
Start a fix sprint for the Google auth bug
Related problems
- Base44 white screen after login — the 405 fix — the same early route check, after an email-and-password login.
- Base44 SSO bypass and auth vulnerabilities — the SSO-only app vulnerability and what to verify on your own app.
- Base44 RLS out of sync after AI edit — what breaks downstream when the authenticated session lands in your data layer but the row-level security policies were regenerated mid-flight.