Google OAuth login fails with redirect_uri_mismatch on self-hosted instances
Description
Google OAuth login is broken on self-hosted instances. The login flow fails with a redirect_uri_mismatch error from Google because two different OAuth providers are used for the two halves of the same login flow, each with a different redirect_uri. This means the redirect_uri used to obtain the authorization code does not match the one used to exchange it for a token, which Google rejects. Specifically:
- Link generation is handled by OauthProvider (GENERIC) via oauth.provider.js, which constructs the Google auth URL with redirect_uri=${FRONTEND_URL}/settings
- Token exchange (the oauthExists call) is handled by GoogleProvider (GOOGLE) via google.provider.js, which uses redirect_uri=${FRONTEND_URL}/integrations/social/youtube
These two redirect URIs do not match, causing Google to return redirect_uri_mismatch and the backend to return a 500.
Reproduction steps
Deploy Postiz self-hosted via Docker Compose
Configure Google OAuth credentials:
- Set POSTIZ_OAUTH_CLIENT_ID, POSTIZ_OAUTH_CLIENT_SECRET, POSTIZ_OAUTH_AUTH_URL, POSTIZ_OAUTH_TOKEN_URL, POSTIZ_OAUTH_USERINFO_URL
- Set YOUTUBE_CLIENT_ID, YOUTUBE_CLIENT_SECRET
- Register both https:///settings and https:///integrations/social/youtube as authorized redirect URIs in Google Cloud Console
- Navigate to the Postiz login page
- Click Login with Google
- Authenticate with a Google account
- Observe the 500 error
Expected behavior
Google OAuth login completes successfully and the user is authenticated.
Actual Behavior with Screenshots
The backend returns a 500 Internal Server Error. The browser console shows:
POST /api/auth/oauth/GOOGLE/exists 500 (Internal Server Error)
The backend logs show:
ERROR [ExceptionsHandler] redirect_uri_mismatch Error: redirect_uri_mismatch at Gaxios._request (.../gaxios/build/src/gaxios.js:142:23) at async OAuth2Client.getTokenAsync (.../google-auth-library/build/src/auth/oauth2client.js:158:21) at async GoogleProvider.getToken (.../src/services/auth/providers/google.provider.js:44:28) at async AuthService.checkExists (.../src/services/auth/auth.service.js:185:23) at async AuthController.oauthExists (.../src/api/routes/auth.controller.js:181:32)
Operating system
MacOS
Node Version
v22.20.0
Provide any additional context for the Bug.
Root Cause Analysis
google.provider.js (GoogleProvider) is decorated with @AuthProvider({ provider: 'GOOGLE' }) and handles the oauthExists endpoint. However, it is built around YouTube OAuth (clientAndYoutube()) and uses YOUTUBE_CLIENT_ID/YOUTUBE_CLIENT_SECRET with redirectUri=${FRONTEND_URL}/integrations/social/youtube. oauth.provider.js (OauthProvider) is decorated with @AuthProvider({ provider: 'GENERIC' }) and generates the initial Google login link using redirectUri=${FRONTEND_URL}/settings. The frontend calls the GENERIC provider for link generation and the GOOGLE provider for the token exchange — these are incompatible because they use different redirect URIs. Relevant source paths:
apps/backend/src/services/auth/providers/google.provider.js apps/backend/src/services/auth/providers/oauth.provider.js
Workaround
Add a Traefik replacepathregex middleware to rewrite /api/auth/oauth/GOOGLE/* → /api/auth/oauth/GENERIC/*, forcing both steps through OauthProvider with a consistent redirect_uri=/settings: yaml- "traefik.http.middlewares.google-to-generic.replacepathregex.regex=^/api/auth/oauth/GOOGLE/(.+)$$"
- "traefik.http.middlewares.google-to-generic.replacepathregex.replacement=/api/auth/oauth/GENERIC/$${1}"
- "traefik.http.routers.postiz.middlewares=google-to-generic"
Suggested Fix
Either:
- Have the frontend call /api/auth/oauth/GENERIC/exists (instead of GOOGLE) after completing the OIDC flow initiated by OauthProvider, or
- Refactor GoogleProvider to use a dedicated, consistent redirect URI for login rather than sharing the YouTube integration redirect URI
also add a note that the GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET environment variables don't appear to be used anywhere in the auth flow in v2.21.5, which adds to the confusion for self-hosters.
Have you spent some time to check if this bug has been raised before?
- I checked and didn't find similar issue
Are you willing to submit PR?
None
Source: gitroomhq/postiz-app