Google Marked My Login Page with NextAuth as Malicious

By Raddy in NextJs ·

If you are encountering a ‘Dangerous Site’ warning when using magic links for login, this post will help you resolve the issue. For context, I encountered this issue while running Next.js App Router v16.0.7 and NextAuth 5.0.0-beta.30.

TLDR: I was setting the callbackUrl without proper validation. 🥲

dangerous site

Even though the app passed tests on all major browsers, the login page was flagged – either by Google’s crawlers or the browser itself during runtime. Significantly, the user encountering the error had Chrome’s Enhanced Protection turned on, which suggests the stricter security settings played a role? – maybe.

I am pretty sure that I followed the official documentation to do the magic links, but I still managed to mess it up somehow as I was missing a key validation step.

Below, I will show you how to patch this vulnerability and ensure your authentication flow is fully secure.

1. Diagnosis: Google Search Console

The first step is to verify the issue. Log in to your Google Search Console and navigate to the Security & Manual Actions tab.

  • What to look for: You may see a flagged issue regarding your website’s login route. Google’s security systems detect patterns where users could be redirected to malicious sites after authentication.
  • Important: Once you apply the fix below, you must go back to this tab and click Request Review to clear the flag.
google search console

2. The Problem: Open Redirect Vulnerability

My original authentication flow contained a potential Open Redirect vulnerability.

In my auth.ts, I was setting the callbackUrl without proper validation. This meant an attacker could craft a deceptive URL such as: /auth/signin?callbackUrl=https://evil-site.com

If a user clicked this link and signed in, they would be immediately redirected to the attacker’s malicious site (evil-site.com). This is a common phishing tactic used to steal user credentials.

3. The Fix: Validating the redirect Callback

The fix was fairly simple to implement within NextAuth.js. I updated my auth.ts file to explicitly handle the redirect callback.

Here is the code I added to ensure only safe URLs are processed:

  callbacks: {
    async redirect({ url, baseUrl }) {
      // Validate redirect URLs to prevent open redirect vulnerabilities
      // Only allow relative URLs or URLs from the same origin
      if (url.startsWith("/")) return `${baseUrl}${url}`;
      else if (new URL(url).origin === baseUrl) return url;
      return baseUrl;
    },

    async jwt({ token, user, account, trigger }) {
      // Initial sign in
      if (account && user) { ...

4. How It Works

By implementing the code above, the system now enforces strict rules on where a user can land after logging in:

  • Validates callbackUrl: Every time a login occurs, this function runs.
  • Allows Relative URLs: It accepts paths like /app or /dashboard because they are internal to your site.
  • Allows Same-Origin: It checks if the domain matches your baseUrl. If your site is example.com, it allows example.com/settings but blocks evil.com.
  • Blocks External URLs: If an attacker tries to pass https://evil-site.com, the validation fails, and the user is safely redirected to your homepage (baseUrl) instead.

Example Scenario:

After: User clicks Login → redirects to /auth/signin?callbackUrl=https://evil.com → NextAuth validates the URL, sees it is external, and redirects the user to Your Homepage.

Before: User clicks Login → redirects to /auth/signin?callbackUrl=https://evil.com → User lands on Evil Site.

5. Here is what I generated with Claude for the Google Review form:

What was the issue:
An open redirect vulnerability was detected in our authentication flow where the callbackUrl parameter could potentially redirect users to external sites after login.

What was done to fix it:
We implemented server-side validation in our NextAuth configuration that restricts all authentication redirects to:

  1. Relative paths within our application only (e.g., /app)
  2. URLs that match our domain origin exclusively Any attempt to redirect to an external domain is now blocked and defaults to our homepage. Technical implementation:
    Added a redirect callback to our NextAuth configuration (src/auth.ts) that validates all callback URLs before redirecting users. External URLs are rejected, preventing open redirect attacks. Current status:
    The vulnerability has been patched and deployed. All authentication redirects are now validated server-side before execution.

I hope this article helped you solve your problem. You can shame me in the comments below.

Note: In the interest of getting this solution to you quickly, I utilized AI to assist with drafting sections of this post. – sorry 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *