Google sign in not working with a separate backend (fastify) with nextjs frontend #2041

Closed
opened 2026-03-13 09:22:44 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @mahabubsaki on GitHub (Sep 29, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  • Create a nextjs frontend
  • Connect with fastify backend
  • Try to implement google auth

Current vs. Expected behavior

Followed all the instructions from docs.

When I sign in with google it redirects to [Frontend URL]/api/auth/callback/google

When I change the Authorized redirect URIs to [Backend URL]/api/auth/callback/google, I get Access blocked: test’s request is invalid

What version of Better Auth are you using?

1.3.11

System info

{
  "system": {
    "platform": "win32",
    "arch": "x64",
    "version": "Windows 10 Pro",
    "release": "10.0.19045",
    "cpuCount": 12,
    "cpuModel": "AMD Ryzen 5 5600G with Radeon Graphics         ",
    "totalMemory": "19.90 GB",
    "freeMemory": "2.35 GB"
  },
  "node": {
    "version": "v22.19.0",
    "env": "development"
  },
  "packageManager": {
    "name": "pnpm",
    "version": "10.5.2"
  },
  "frameworks": null,
  "databases": null,
  "betterAuth": {
    "version": "Unknown",
    "config": null
  }
}

Which area(s) are affected? (Select all that apply)

Client

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
	trustedOrigins: [env.NEXT_PUBLIC_BASE_URL],
	database: mongodbAdapter(db),
	appName: "Neptune 3",
	rateLimit: {
		enabled: true,
	},
	telemetry: {
		enabled: false,
	},
	emailAndPassword: {
		enabled: true,
		requireEmailVerification: false, 
		minPasswordLength: 8,
		maxPasswordLength: 128,
		autoSignIn: true, 
		resetPasswordTokenExpiresIn: 3600, 
	},
	user: {
		additionalFields: {
			premiumUser: {
				type: "boolean",
				input: true,
				defaultValue: false,
				fieldName: "premiumUser",
			},
		},
	},
	account: {
		updateAccountOnSignIn: true,
	},
	socialProviders: {
		github: {
			clientId: env.GITHUB_CLIENT_ID || "",
			clientSecret: env.GITHUB_CLIENT_SECRET || "",
		},
		google: {
			clientId: env.GOOGLE_CLIENT_ID || "",
			clientSecret: env.GOOGLE_CLIENT_SECRET || "",
			prompt: "select_account",
		},
	},
	session: {
		cookieCache: {
			enabled: true,
			maxAge: 10 * 60, // 10 minutes
		},
	},
	plugins: [
		jwt({
			jwt: {
				expirationTime: "1h",
				definePayload: async ({ user, session }) => {
					return {
						id: user.id,
						email: user.email,
						sessionId: session.id,
					};
				},
			},
		}),
		username(),
	],
});

Additional context

No response

Originally created by @mahabubsaki on GitHub (Sep 29, 2025). ### Is this suited for github? - [ ] Yes, this is suited for github ### To Reproduce - Create a nextjs frontend - Connect with fastify backend - Try to implement google auth ### Current vs. Expected behavior Followed all the instructions from [docs](https://www.better-auth.com/docs/authentication/google). When I sign in with google it redirects to [Frontend URL]/api/auth/callback/google When I change the Authorized redirect URIs to [Backend URL]/api/auth/callback/google, I get Access blocked: test’s request is invalid ### What version of Better Auth are you using? 1.3.11 ### System info ```bash { "system": { "platform": "win32", "arch": "x64", "version": "Windows 10 Pro", "release": "10.0.19045", "cpuCount": 12, "cpuModel": "AMD Ryzen 5 5600G with Radeon Graphics ", "totalMemory": "19.90 GB", "freeMemory": "2.35 GB" }, "node": { "version": "v22.19.0", "env": "development" }, "packageManager": { "name": "pnpm", "version": "10.5.2" }, "frameworks": null, "databases": null, "betterAuth": { "version": "Unknown", "config": null } } ``` ### Which area(s) are affected? (Select all that apply) Client ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ trustedOrigins: [env.NEXT_PUBLIC_BASE_URL], database: mongodbAdapter(db), appName: "Neptune 3", rateLimit: { enabled: true, }, telemetry: { enabled: false, }, emailAndPassword: { enabled: true, requireEmailVerification: false, minPasswordLength: 8, maxPasswordLength: 128, autoSignIn: true, resetPasswordTokenExpiresIn: 3600, }, user: { additionalFields: { premiumUser: { type: "boolean", input: true, defaultValue: false, fieldName: "premiumUser", }, }, }, account: { updateAccountOnSignIn: true, }, socialProviders: { github: { clientId: env.GITHUB_CLIENT_ID || "", clientSecret: env.GITHUB_CLIENT_SECRET || "", }, google: { clientId: env.GOOGLE_CLIENT_ID || "", clientSecret: env.GOOGLE_CLIENT_SECRET || "", prompt: "select_account", }, }, session: { cookieCache: { enabled: true, maxAge: 10 * 60, // 10 minutes }, }, plugins: [ jwt({ jwt: { expirationTime: "1h", definePayload: async ({ user, session }) => { return { id: user.id, email: user.email, sessionId: session.id, }; }, }, }), username(), ], }); ``` ### Additional context _No response_
GiteaMirror added the nextjsfastify labels 2026-03-13 09:22:45 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Sep 29, 2025):

Hi @mahabubsaki! I'm Dosu and I’m helping the better-auth team.

The "Access blocked: test’s request is invalid" error with Google sign-in in a split Next.js frontend and Fastify backend setup is almost always caused by a mismatch between the redirect URI registered in Google Cloud Console and the actual backend endpoint handling the OAuth callback. The redirect URI must be exactly the backend's callback endpoint (e.g., https://your-backend-domain/api/auth/callback/google), not the frontend URL. Google will block the request if the redirect URI doesn't match exactly, including protocol, domain, port, and path—no trailing slashes or case differences allowed [source].

In this architecture, the backend (Fastify) must handle the /api/auth/callback/google route, and that's the URI you need to register in Google Cloud Console. The frontend should never be the OAuth callback endpoint; instead, after successful authentication, you can redirect users to a frontend route (like a dashboard) using the callbackURL parameter in your sign-in call [source].

If you're running into issues in development with different ports or domains (like localhost:3000 for frontend and localhost:4000 for backend), cookies and PKCE code_verifier handling can break the flow. For local development, consider using a tunneling service like ngrok to expose your backend on a public HTTPS URL, and register that full URL (including /api/auth/callback/google) in Google Cloud Console [source].

Make sure your trustedOrigins in Better Auth config includes your frontend's full origin (protocol + domain + port), and only one CORS handler is active for /api/auth/* routes—either Fastify or Better Auth, not both [source].

If you need more flexibility (e.g., frontend and backend on different domains in production), check out the OAuth proxy plugin, which helps manage callback redirects across origins.

If you still see errors, enable debug logging, clear cookies, and double-check that all URLs and environment variables are set correctly. Let me know if you need a step-by-step checklist for your exact setup.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

@dosubot[bot] commented on GitHub (Sep 29, 2025): <!-- Greeting --> Hi @mahabubsaki! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> The "Access blocked: test’s request is invalid" error with Google sign-in in a split Next.js frontend and Fastify backend setup is almost always caused by a mismatch between the redirect URI registered in Google Cloud Console and the actual backend endpoint handling the OAuth callback. The redirect URI must be exactly the backend's callback endpoint (e.g., `https://your-backend-domain/api/auth/callback/google`), not the frontend URL. Google will block the request if the redirect URI doesn't match exactly, including protocol, domain, port, and path—no trailing slashes or case differences allowed [[source](https://github.com/better-auth/better-auth/issues/3881)]. In this architecture, the backend (Fastify) must handle the `/api/auth/callback/google` route, and that's the URI you need to register in Google Cloud Console. The frontend should never be the OAuth callback endpoint; instead, after successful authentication, you can redirect users to a frontend route (like a dashboard) using the `callbackURL` parameter in your sign-in call [[source](https://github.com/better-auth/better-auth/issues/3881)]. If you're running into issues in development with different ports or domains (like `localhost:3000` for frontend and `localhost:4000` for backend), cookies and PKCE code_verifier handling can break the flow. For local development, consider using a tunneling service like ngrok to expose your backend on a public HTTPS URL, and register that full URL (including `/api/auth/callback/google`) in Google Cloud Console [[source](https://github.com/better-auth/better-auth/issues/4070)]. Make sure your `trustedOrigins` in Better Auth config includes your frontend's full origin (protocol + domain + port), and only one CORS handler is active for `/api/auth/*` routes—either Fastify or Better Auth, not both [[source](https://github.com/better-auth/better-auth/issues/4021)]. If you need more flexibility (e.g., frontend and backend on different domains in production), check out the [OAuth proxy plugin](https://github.com/better-auth/better-auth/pull/4825), which helps manage callback redirects across origins. If you still see errors, enable debug logging, clear cookies, and double-check that all URLs and environment variables are set correctly. Let me know if you need a step-by-step checklist for your exact setup. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4970)
Author
Owner

@mahabubsaki commented on GitHub (Sep 29, 2025):

Hi @mahabubsaki! I'm Dosu and I’m helping the better-auth team.

The "Access blocked: test’s request is invalid" error with Google sign-in in a split Next.js frontend and Fastify backend setup is almost always caused by a mismatch between the redirect URI registered in Google Cloud Console and the actual backend endpoint handling the OAuth callback. The redirect URI must be exactly the backend's callback endpoint (e.g., https://your-backend-domain/api/auth/callback/google), not the frontend URL. Google will block the request if the redirect URI doesn't match exactly, including protocol, domain, port, and path—no trailing slashes or case differences allowed [source].

In this architecture, the backend (Fastify) must handle the /api/auth/callback/google route, and that's the URI you need to register in Google Cloud Console. The frontend should never be the OAuth callback endpoint; instead, after successful authentication, you can redirect users to a frontend route (like a dashboard) using the callbackURL parameter in your sign-in call [source].

If you're running into issues in development with different ports or domains (like localhost:3000 for frontend and localhost:4000 for backend), cookies and PKCE code_verifier handling can break the flow. For local development, consider using a tunneling service like ngrok to expose your backend on a public HTTPS URL, and register that full URL (including /api/auth/callback/google) in Google Cloud Console [source].

Make sure your trustedOrigins in Better Auth config includes your frontend's full origin (protocol + domain + port), and only one CORS handler is active for /api/auth/* routes—either Fastify or Better Auth, not both [source].

If you need more flexibility (e.g., frontend and backend on different domains in production), check out the OAuth proxy plugin, which helps manage callback redirects across origins.

If you still see errors, enable debug logging, clear cookies, and double-check that all URLs and environment variables are set correctly. Let me know if you need a step-by-step checklist for your exact setup.

To reply, just mention @dosu.

How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other Chat with Dosu Join Discord Share on X

It solved when I updated the google config to this

google: {
			clientId: env.GOOGLE_CLIENT_ID || "",
			clientSecret: env.GOOGLE_CLIENT_SECRET || "",
			prompt: "select_account",
			redirectURI: `${env.BACKEND_URL}api/auth/callback/google`,
		},

Also In frontend I had to give the exact callback URL where I want to navigate after sign in, For Instance setting '/' as callback URL was working perfectly fine on Github

@dosu.

@mahabubsaki commented on GitHub (Sep 29, 2025): > Hi [@mahabubsaki](https://github.com/mahabubsaki)! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. > > The "Access blocked: test’s request is invalid" error with Google sign-in in a split Next.js frontend and Fastify backend setup is almost always caused by a mismatch between the redirect URI registered in Google Cloud Console and the actual backend endpoint handling the OAuth callback. The redirect URI must be exactly the backend's callback endpoint (e.g., `https://your-backend-domain/api/auth/callback/google`), not the frontend URL. Google will block the request if the redirect URI doesn't match exactly, including protocol, domain, port, and path—no trailing slashes or case differences allowed [[source](https://github.com/better-auth/better-auth/issues/3881)]. > > In this architecture, the backend (Fastify) must handle the `/api/auth/callback/google` route, and that's the URI you need to register in Google Cloud Console. The frontend should never be the OAuth callback endpoint; instead, after successful authentication, you can redirect users to a frontend route (like a dashboard) using the `callbackURL` parameter in your sign-in call [[source](https://github.com/better-auth/better-auth/issues/3881)]. > > If you're running into issues in development with different ports or domains (like `localhost:3000` for frontend and `localhost:4000` for backend), cookies and PKCE code_verifier handling can break the flow. For local development, consider using a tunneling service like ngrok to expose your backend on a public HTTPS URL, and register that full URL (including `/api/auth/callback/google`) in Google Cloud Console [[source](https://github.com/better-auth/better-auth/issues/4070)]. > > Make sure your `trustedOrigins` in Better Auth config includes your frontend's full origin (protocol + domain + port), and only one CORS handler is active for `/api/auth/*` routes—either Fastify or Better Auth, not both [[source](https://github.com/better-auth/better-auth/issues/4021)]. > > If you need more flexibility (e.g., frontend and backend on different domains in production), check out the [OAuth proxy plugin](https://github.com/better-auth/better-auth/pull/4825), which helps manage callback redirects across origins. > > If you still see errors, enable debug logging, clear cookies, and double-check that all URLs and environment variables are set correctly. Let me know if you need a step-by-step checklist for your exact setup. > > _To reply, just mention [@dosu](https://go.dosu.dev/dosubot)._ > > How did I do? [Good](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/d530f3d1-dd7e-472b-9c93-a801ec5f6e7c?feedback_type=other) [![Chat with Dosu](https://camo.githubusercontent.com/d9ffebb979729c9ef0fc4e3090dbae5b17cabbfec8afe378ada6b81913d6ad8a/68747470733a2f2f646f73752e6465762f646f73752d636861742d62616467652e737667)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github) [![Join Discord](https://camo.githubusercontent.com/d562c2df5e4567ea41d37f1d91a4da0839d8341037045b103b2da268998de17f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6a6f696e2d3538363546323f6c6f676f3d646973636f7264266c6f676f436f6c6f723d7768697465266c6162656c3d)](https://go.dosu.dev/discord-bot) [![Share on X](https://camo.githubusercontent.com/4649f705e2396d6f328dbc8e800a0509c9c17b3b20253b36706c393df124b93d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f582d73686172652d626c61636b)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4970) It solved when I updated the google config to this ``` google: { clientId: env.GOOGLE_CLIENT_ID || "", clientSecret: env.GOOGLE_CLIENT_SECRET || "", prompt: "select_account", redirectURI: `${env.BACKEND_URL}api/auth/callback/google`, }, ``` Also In frontend I had to give the exact callback URL where I want to navigate after sign in, For Instance setting '/' as callback URL was working perfectly fine on Github [@dosu](https://go.dosu.dev/dosubot).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2041