Google OAuth redirect_uri_mismatch on staging instance — production works fine with same OAuth app

<n8n version: 2.20.7
Database: SQLite (default)
Running via: Docker (self-hosted, Ubuntu 24.04 on DigitalOcean)
Reverse proxy: nginx with SSL via Certbot/Let’s Encrypt
Problem:
I have two self-hosted n8n instances:
Production: n8n.revvittsystems.com — Gmail OAuth works perfectly, including creating brand new credentials
Staging: staging.revvittsystems.com — Gmail OAuth fails with Error 400: redirect_uri_mismatch every time
Both instances run n8n 2.20.7 on Docker with nginx reverse proxy. Both use the same Google Cloud OAuth app (same Client ID/Secret). I also tried creating a completely separate OAuth client with only the staging redirect URI — same error.
What I’ve confirmed:
The redirect URI shown in n8n staging UI is https://staging.revvittsystems.com/rest/oauth2-credential/callback
This exact URI is registered in Google Cloud Console under Authorized redirect URIs
I decoded the Google error URL and confirmed the redirect_uri n8n sends is https://staging.revvittsystems.com/rest/oauth2-credential/callback — it matches exactly
X-Forwarded-Proto $scheme is set in nginx so n8n correctly generates https:// prefix
App is published to Production in Google OAuth consent screen
Tested in incognito window — same error
Creating a new credential on production works immediately — the Google OAuth app itself is fine
Creating a separate brand-new OAuth client just for staging also fails with the same error
Staging .env:
N8N_HOST=staging.revvittsystems.com
N8N_PORT=5678
N8N_PROTOCOL=https
WEBHOOK_URL=https://staging.revvittsystems.com/
N8N_EDITOR_BASE_URL=https://staging.revvittsystems.com
GENERIC_TIMEZONE=America/New_York
Staging nginx config:
server {
listen 443 ssl;
server_name staging.revvittsystems.com;
ssl_certificate /etc/letsencrypt/live/staging.revvittsystems.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/staging.revvittsystems.com/privkey.pem;
large_client_header_buffers 4 16k;
location / {
proxy_pass http://localhost:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection ‘upgrade’;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_buffer_size 16k;
proxy_buffers 4 16k;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Additional note: When logged in as the owner/admin account on staging, clicking “Sign in with Google” gives a 414 URI Too Long error instead (known n8n bug where admin scopes are appended to the URL). Creating from a non-admin member account gets past the 414 but hits the redirect_uri_mismatch.
Question: What else could cause redirect_uri_mismatch when the URI is confirmed correct and matches exactly? Is there something specific about n8n 2.20.7’s OAuth flow that could cause this on a fresh instance?!-- Hey! The fastest way to find solutions is by using the :magnifying_glass_tilted_right: search function at the upper right.
If your question hasn’t been asked before, please follow the template below. Skip the questions that are not relevant to you.
:brazil: :france: :south_korea: :germany: You can post in any language - we’ll translate your post for you!

Describe the problem/error/question

What is the error message (if any)?

Please share your workflow

(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow.)

Share the output returned by the last node

Information on your n8n setup

  • n8n version:
  • Database (default: SQLite):
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app):
  • Operating system:

Hi @Sam_Rao, welcome!
I think your n8n_proxy_hops is either unset or not set correctly according to your setup, that env variable should look like this:

N8N_HOST=staging.revvittsystems.com
N8N_PORT=5678
N8N_PROTOCOL=https
N8N_PROXY_HOPS=1
WEBHOOK_URL=https://staging.revvittsystems.com/
N8N_EDITOR_BASE_URL=https://staging.revvittsystems.com/
GENERIC_TIMEZONE=America/New_York

and make sure your Nginx config also has these things enabled:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;

Let me know how this goes after giving a restart.

Hi @Sam_Rao

The redirect URI mismatch you are experiencing on your staging instance is a common but frustrating hurdle in n8n deployments. Even when the URL appears identical, Google’s authentication servers are extremely strict. The process requires an exact, character-for-character match between the value defined in your Google Cloud Console and the value n8n sends in its request. If there is even a single character difference, such as a missing trailing slash, the authentication will be rejected immediately.

One of the most frequent causes for this error, especially after configuration changes, is Google’s global propagation delay. Even if you have updated the Authorized Redirect URIs in the Google Cloud Console, those changes can take several hours to propagate across Google’s infrastructure. If you recently modified these settings, the most likely solution is to simply wait a few hours and try again, as the system may still be using the old configuration.

It is also vital to verify that the environment variables inside your Docker container match your expectations. While your .env file looks correct, it is possible for the running n8n process to have a different configuration due to caching or how the container was initialized. Executing a command to print the environment variables from inside the container will help you confirm that the WEBHOOK_URL and N8N_PROTOCOL settings are correctly applied and not defaulting to internal, incorrect values.

docker exec <container_id> env

You should also examine your Nginx configuration for any potential conflicts. While your current settings are standard, ensure that headers such as X-Forwarded-Proto and X-Forwarded-Host are being passed correctly without being overwritten by other services. If you are using additional layers like Cloudflare, verify that they are not modifying or stripping these headers before they reach your Nginx reverse proxy, as this would prevent n8n from generating the proper secure redirect URL.

proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;

Regarding the Google Cloud Console setup, ensure your project’s OAuth consent screen is properly configured for the staging environment. If your app is currently in the testing phase, you must explicitly add any account you are using for testing to the “Test Users” list within the console. Furthermore, ensure that the project settings do not have domain restrictions that might be causing the staging domain to be treated differently than your production environment.

Finally, the 414 error encountered by your admin account indicates that the generated OAuth URL is exceeding typical character limits. This is a known issue caused by the accumulation of scopes and state data. Successfully completing the authentication with a non-admin account is the best way to bypass this, as it allows the initial handshake to occur and establishes the necessary session cookies for future interactions. Comparing the generated URL parameters side-by-side with your console configuration remains the most definitive way to identify any hidden discrepancies.

hi Anshul!

Thanks for your help!


I applied the suggested fixes — still getting redirect_uri_mismatch.

Changes made:

  • Added N8N_PROXY_HOPS=1 to .env (confirmed inside container via docker exec)

  • Added X-Forwarded-For, X-Forwarded-Host, and X-Forwarded-Proto to nginx

  • Restarted both nginx and n8n container

Container env confirms all variables are correct:

WEBHOOK_URL=https://staging.revvittsystems.com/
N8N_PROTOCOL=https
N8N_EDITOR_BASE_URL=https://staging.revvittsystems.com
N8N_PROXY_HOPS=1
N8N_HOST=staging.revvittsystems.com

Google’s error details show:

redirect_uri=https://staging.revvittsystems.com/rest/oauth2-credential/callback

This matches exactly what’s registered in Google Cloud Console. I also tried creating a completely separate OAuth client with only the staging redirect URI — same error.

Creating a new credential on production (n8n.revvittsystems.com) works immediately with the same Google OAuth app. The issue is specific to the staging instance.

The credential is being created from a non-admin/member account to avoid the 414 URI Too Long bug with admin accounts.


hi There! Thanks for your help! Please see my reply to @Anshul_Namdev . I am also including it here.

hi Anshul!

Thanks for your help!


I applied the suggested fixes — still getting redirect_uri_mismatch.

Changes made:

  • Added N8N_PROXY_HOPS=1 to .env (confirmed inside container via docker exec)

  • Added X-Forwarded-For, X-Forwarded-Host, and X-Forwarded-Proto to nginx

  • Restarted both nginx and n8n container

Container env confirms all variables are correct:

WEBHOOK_URL=https://staging.revvittsystems.com/
N8N_PROTOCOL=https
N8N_EDITOR_BASE_URL=https://staging.revvittsystems.com
N8N_PROXY_HOPS=1
N8N_HOST=staging.revvittsystems.com

Google’s error details show:

redirect_uri=https://staging.revvittsystems.com/rest/oauth2-credential/callback

This matches exactly what’s registered in Google Cloud Console. I also tried creating a completely separate OAuth client with only the staging redirect URI — same error.

Creating a new credential on production (n8n.revvittsystems.com) works immediately with the same Google OAuth app. The issue is specific to the staging instance.

The credential is being created from a non-admin/member account to avoid the 414 URI Too Long bug with admin accounts.