LibreChat/api/server/middleware/index.js
Marco Beretta 146664e0d1
🔐 fix: Redirect OAuth Browser Navigations Instead of Rendering JSON (#15440)
* 🔐 fix: Redirect OAuth Browser Navigations Instead of Rendering JSON

The /oauth/* routes are reached by top-level browser navigation, so a
middleware that rejects one with a JSON body makes the browser render
that body as the page. Hitting the login rate limit during a social
sign-in dropped the user on a blank page showing:

  {"message": "Too many login attempts, please try again after 5 minutes."}

Mark those requests with markOAuthNavigation and have the two middlewares
that can reject them answer with a redirect to the login page carrying an
error code the client localizes. The login limiter stays a single instance
so the attempt budget is still shared with POST /api/auth/login, and that
route keeps its JSON 429 for the SPA.

* 🧪 fix: Address PR Review Bot Findings

chatgpt-codex-connector:
- Split the inline `type TranslationKeys` specifier out of the value
  import, per the standalone `import type` convention in CLAUDE.md. This
  also clears the Static checks import-sort failure.
- Cover the new OAuth error branches in Login.spec.tsx: each mapped
  `?error=` code raises its localized toast and the query is cleaned,
  and unmapped codes including prototype members raise nothing.
2026-08-31 21:13:47 -04:00

65 lines
2.1 KiB
JavaScript

const validatePasswordReset = require('./validatePasswordReset');
const setTwoFactorTempUser = require('./setTwoFactorTempUser');
const validateRegistration = require('./validateRegistration');
const buildEndpointOption = require('./buildEndpointOption');
const validateEmailLogin = require('./validateEmailLogin');
const validateMessageReq = require('./validateMessageReq');
const {
canReadActiveJobConversation,
prepareMessageRequestValidation,
sendValidationResponse,
} = require('./messageValidation');
const checkDomainAllowed = require('./checkDomainAllowed');
const { markOAuthNavigation } = require('./oauthNavigation');
const requireLocalAuth = require('./requireLocalAuth');
const canDeleteAccount = require('./canDeleteAccount');
const accessResources = require('./accessResources');
const requireLdapAuth = require('./requireLdapAuth');
const abortMiddleware = require('./abortMiddleware');
const checkInviteUser = require('./checkInviteUser');
const requireJwtAuth = require('./requireJwtAuth');
const { requireRumProxyAuth } = require('./requireJwtAuth');
const configMiddleware = require('./config/app');
const validateModel = require('./validateModel');
const moderateText = require('./moderateText');
const logHeaders = require('./logHeaders');
const setHeaders = require('./setHeaders');
const validate = require('./validate');
const limiters = require('./limiters');
const uaParser = require('./uaParser');
const checkBan = require('./checkBan');
const noIndex = require('./noIndex');
const roles = require('./roles');
module.exports = {
...abortMiddleware,
...validate,
...limiters,
...roles,
...accessResources,
noIndex,
checkBan,
uaParser,
setHeaders,
logHeaders,
markOAuthNavigation,
moderateText,
validateModel,
requireJwtAuth,
requireRumProxyAuth,
setTwoFactorTempUser,
checkInviteUser,
requireLdapAuth,
requireLocalAuth,
canDeleteAccount,
configMiddleware,
checkDomainAllowed,
validateMessageReq,
canReadActiveJobConversation,
sendValidationResponse,
prepareMessageRequestValidation,
buildEndpointOption,
validateRegistration,
validatePasswordReset,
validateEmailLogin,
};