danny-avila / LibreChat

Enhanced ChatGPT Clone: Features Anthropic, OpenAI, Assistants API, Azure, Groq, GPT-4o, Mistral, OpenRouter, Vertex AI, Gemini, Artifacts, AI model switching, message search, langchain, DALL-E-3, ChatGPT Plugins, OpenAI Functions, Secure Multi-User System, Presets, completely open-source for self-hosting. Actively in public development.
https://librechat.ai/
MIT License
17.2k stars 2.87k forks source link

[Bug]: SSO Login with User names with special characters lead to errors #967

Closed nikhase closed 11 months ago

nikhase commented 11 months ago

Contact Details

No response

What happened?

We are deploying this amazing piece of software in our german company. We have many people with special german or french characters in their names - for example é or ö.

We use SSO Login. Unfortunately, they cannot create a user for LibreChat, it fails. The special character does not necessarily need to be in the email, because we have clean aliases - it can be in the profile stored in our Keycloak.

I am not experienced in TS / JS. If you point me to where to look, I might be able to create a PR and some tests for it. Thanks in advance ! :-)

Steps to Reproduce

Our setup (we put it into helm charts):

    allow_registration: "false"
    allow_social_login: "true"
      issuer: "<<our company-keycloak>>"
      scope: "openid profile email" 

What browsers are you seeing the problem on?

Chrome

Relevant log output

023-08-25T11:15:26.572501370Z ValidationError: User validation failed: username: is invalid
2023-08-25T11:15:26.572561671Z     at Document.invalidate (/app/node_modules/mongoose/lib/document.js:3153:32)
2023-08-25T11:15:26.572570972Z     at /app/node_modules/mongoose/lib/document.js:2946:17
2023-08-25T11:15:26.572576185Z     at /app/node_modules/mongoose/lib/schematype.js:1368:9
2023-08-25T11:15:26.572595870Z     at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
2023-08-25T11:15:28.201417339Z AxiosError: Request failed with status code 401
2023-08-25T11:15:28.201469048Z     at settle (/app/node_modules/axios/dist/node/axios.cjs:1909:12)
2023-08-25T11:15:28.201477672Z     at IncomingMessage.handleStreamEnd (/app/node_modules/axios/dist/node/axios.cjs:2989:11)
2023-08-25T11:15:28.201483036Z     at IncomingMessage.emit (node:events:525:35)
2023-08-25T11:15:28.201487855Z     at endReadableNT (node:internal/streams/readable:1359:12)
2023-08-25T11:15:28.201492706Z     at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
2023-08-25T11:15:28.201497448Z   code: 'ERR_BAD_REQUEST',
2023-08-25T11:15:28.201502006Z   config: {
2023-08-25T11:15:28.201506718Z     transitional: {
2023-08-25T11:15:28.201510574Z       silentJSONParsing: true,
2023-08-25T11:15:28.201514421Z       forcedJSONParsing: true,
2023-08-25T11:15:28.201518261Z       clarifyTimeoutError: false
2023-08-25T11:15:28.201522327Z     },
2023-08-25T11:15:28.201526909Z     adapter: [ 'xhr', 'http' ],
2023-08-25T11:15:28.201531660Z     transformRequest: [ [Function: transformRequest] ],
2023-08-25T11:15:28.201536130Z     transformResponse: [ [Function: transformResponse] ],
2023-08-25T11:15:28.201540422Z     timeout: 0,
2023-08-25T11:15:28.201554678Z     xsrfCookieName: 'XSRF-TOKEN',
2023-08-25T11:15:28.201558469Z     xsrfHeaderName: 'X-XSRF-TOKEN',
2023-08-25T11:15:28.201562435Z     maxContentLength: -1,
2023-08-25T11:15:28.201566797Z     maxBodyLength: -1,
2023-08-25T11:15:28.201571265Z     env: { FormData: [Function], Blob: [class Blob] },
2023-08-25T11:15:28.201575104Z     validateStatus: [Function: validateStatus],
2023-08-25T11:15:28.201579478Z     headers: AxiosHeaders {
2023-08-25T11:15:28.201583279Z       Accept: 'application/json, text/plain, */*',
2023-08-25T11:15:28.201587662Z       Authorization: 'Bearer ',
2023-08-25T11:15:28.201591495Z       'User-Agent': 'axios/1.4.0',
2023-08-25T11:15:28.201595506Z       'Accept-Encoding': 'gzip, compress, deflate, br'
2023-08-25T11:15:28.201599462Z     },
2023-08-25T11:15:28.201603168Z     method: 'get',
2023-08-25T11:15:28.201607589Z     url: 'https://api.openai.com/v1//models',
2023-08-25T11:15:28.201611394Z     data: undefined
2023-08-25T11:15:28.201615825Z   },
2023-08-25T11:15:28.201620232Z   request: <ref *1> ClientRequest {
2023-08-25T11:15:28.201624065Z     _events: [Object: null prototype] {
2023-08-25T11:15:28.201628297Z       abort: [Function (anonymous)],
2023-08-25T11:15:28.201632487Z       aborted: [Function (anonymous)],
2023-08-25T11:15:28.201637529Z       connect: [Function (anonymous)],
2023-08-25T11:15:28.201642282Z       error: [Function (anonymous)],
2023-08-25T11:15:28.201657759Z       socket: [Function (anonymous)],
2023-08-25T11:15:28.201663064Z       timeout: [Function (anonymous)],
2023-08-25T11:15:28.201667440Z       finish: [Function: requestOnFinish]
2023-08-25T11:15:28.201672066Z     },
2023-08-25T11:15:28.201676766Z     _eventsCount: 7,
2023-08-25T11:15:28.201681239Z     _maxListeners: undefined,
2023-08-25T11:15:28.201685910Z     outputData: [],
2023-08-25T11:15:28.201690484Z     outputSize: 0,
2023-08-25T11:15:28.201695424Z     writable: true,
2023-08-25T11:15:28.201700164Z     destroyed: true,
2023-08-25T11:15:28.201705077Z     _last: true,
2023-08-25T11:15:28.201709466Z     chunkedEncoding: false,
2023-08-25T11:15:28.201730255Z     shouldKeepAlive: true,
2023-08-25T11:15:28.201736080Z     maxRequestsOnConnectionReached: false,
2023-08-25T11:15:28.201755912Z     _defaultKeepAlive: true,
2023-08-25T11:15:28.201760952Z     useChunkedEncodingByDefault: false,
2023-08-25T11:15:28.201765867Z     sendDate: false,
2023-08-25T11:15:28.201770655Z     _removedConnection: false,
2023-08-25T11:15:28.201775016Z     _removedContLen: false,
2023-08-25T11:15:28.201779396Z     _removedTE: false,
2023-08-25T11:15:28.201784069Z     strictContentLength: false,
2023-08-25T11:15:28.201788367Z     _contentLength: 0,
2023-08-25T11:15:28.201792926Z     _hasBody: true,
2023-08-25T11:15:28.201808500Z     _trailer: '',
2023-08-25T11:15:28.201813298Z     finished: true,
2023-08-25T11:15:28.201817793Z     _headerSent: true,
2023-08-25T11:15:28.201822314Z     _closed: true,
2023-08-25T11:15:28.201826745Z     socket: TLSSocket {
2023-08-25T11:15:28.201831324Z       _tlsOptions: [Object],
2023-08-25T11:15:28.201836035Z       _secureEstablished: true,
2023-08-25T11:15:28.201840649Z       _securePending: false,
2023-08-25T11:15:28.201845423Z       _newSessionPending: false,
2023-08-25T11:15:28.201850029Z       _controlReleased: true,
2023-08-25T11:15:28.201854921Z       secureConnecting: false,
2023-08-25T11:15:28.201869741Z       _SNICallback: null,
2023-08-25T11:15:28.201874619Z       servername: 'api.openai.com',
2023-08-25T11:15:28.201879375Z       alpnProtocol: false,
2023-08-25T11:15:28.201883983Z       authorized: true,
2023-08-25T11:15:28.201888886Z       authorizationError: null,
2023-08-25T11:15:28.201893502Z       encrypted: true,
2023-08-25T11:15:28.201898155Z       _events: [Object: null prototype],
2023-08-25T11:15:28.201906768Z       _eventsCount: 9,
2023-08-25T11:15:28.201911688Z       connecting: false,
2023-08-25T11:15:28.201916267Z       _hadError: false,
2023-08-25T11:15:28.201921007Z       _parent: null,
2023-08-25T11:15:28.201925561Z       _host: 'api.openai.com',
2023-08-25T11:15:28.201940437Z       _closeAfterHandlingError: false,
2023-08-25T11:15:28.201946091Z       _readableState: [ReadableState],
2023-08-25T11:15:28.201950825Z       _maxListeners: undefined,
2023-08-25T11:15:28.201955425Z       _writableState: [WritableState],
2023-08-25T11:15:28.201960238Z       allowHalfOpen: false,
2023-08-25T11:15:28.201964805Z       _sockname: null,
2023-08-25T11:15:28.201970007Z       _pendingData: null,
2023-08-25T11:15:28.201974418Z       _pendingEncoding: '',
2023-08-25T11:15:28.201984108Z       server: undefined,
2023-08-25T11:15:28.201989102Z       _server: null,
2023-08-25T11:15:28.201993847Z       ssl: [TLSWrap],
2023-08-25T11:15:28.201998415Z       _requestCert: true,
2023-08-25T11:15:28.202003046Z       _rejectUnauthorized: true,
2023-08-25T11:15:28.202007652Z       timeout: 5000,
2023-08-25T11:15:28.202012360Z       parser: null,
2023-08-25T11:15:28.202025079Z       _httpMessage: null,
2023-08-25T11:15:28.202030245Z       [Symbol(res)]: [TLSWrap],
2023-08-25T11:15:28.202034825Z       [Symbol(verified)]: true,
2023-08-25T11:15:28.202039602Z       [Symbol(pendingSession)]: null,
2023-08-25T11:15:28.202044237Z       [Symbol(async_id_symbol)]: -1,
2023-08-25T11:15:28.202048957Z       [Symbol(kHandle)]: [TLSWrap],
2023-08-25T11:15:28.202053616Z       [Symbol(lastWriteQueueSize)]: 0,
2023-08-25T11:15:28.202058898Z       [Symbol(timeout)]: Timeout {
2023-08-25T11:15:28.202063530Z         _idleTimeout: 5000,
2023-08-25T11:15:28.202068716Z         _idlePrev: [TimersList],
2023-08-25T11:15:28.202073382Z         _idleNext: [Timeout],
2023-08-25T11:15:28.202078358Z         _idleStart: 596349549,
2023-08-25T11:15:28.202082704Z         _onTimeout: [Function: bound ],
2023-08-25T11:15:28.202093675Z         _timerArgs: undefined,
2023-08-25T11:15:28.202098774Z         _repeat: null,
2023-08-25T11:15:28.202103352Z         _destroyed: false,
2023-08-25T11:15:28.202108051Z         [Symbol(refed)]: false,
2023-08-25T11:15:28.202112103Z         [Symbol(kHasPrimitive)]: false,
2023-08-25T11:15:28.202163960Z         [Symbol(asyncId)]: 446246,
2023-08-25T11:15:28.202171208Z         [Symbol(triggerId)]: 446244
2023-08-25T11:15:28.202175709Z       },
2023-08-25T11:15:28.202180379Z       [Symbol(kBuffer)]: null,
2023-08-25T11:15:28.202184943Z       [Symbol(kBufferCb)]: null,
2023-08-25T11:15:28.202189691Z       [Symbol(kBufferGen)]: null,
2023-08-25T11:15:28.202194101Z       [Symbol(kCapture)]: false,
2023-08-25T11:15:28.202198900Z       [Symbol(kSetNoDelay)]: false,
2023-08-25T11:15:28.202203480Z       [Symbol(kSetKeepAlive)]: true,
2023-08-25T11:15:28.202208436Z       [Symbol(kSetKeepAliveInitialDelay)]: 1,
2023-08-25T11:15:28.202213196Z       [Symbol(kBytesRead)]: 0,
2023-08-25T11:15:28.202232499Z       [Symbol(kBytesWritten)]: 0,
2023-08-25T11:15:28.202237897Z       [Symbol(connect-options)]: [Object]
2023-08-25T11:15:28.202242045Z     },
2023-08-25T11:15:28.202246930Z     _header: 'GET /v1//models HTTP/1.1\r\n' +
2023-08-25T11:15:28.202251946Z       'Accept: application/json, text/plain, */*\r\n' +
2023-08-25T11:15:28.202256589Z       'Authorization: Bearer \r\n' +
2023-08-25T11:15:28.202261373Z       'User-Agent: axios/1.4.0\r\n' +
2023-08-25T11:15:28.202265898Z       'Accept-Encoding: gzip, compress, deflate, br\r\n' +
2023-08-25T11:15:28.202270522Z       'Host: api.openai.com\r\n' +
2023-08-25T11:15:28.202275117Z       'Connection: keep-alive\r\n' +
2023-08-25T11:15:28.202279707Z       '\r\n',
2023-08-25T11:15:28.202284712Z     _keepAliveTimeout: 0,
2023-08-25T11:15:28.202289323Z     _onPendingData: [Function: nop],
2023-08-25T11:15:28.202294127Z     agent: Agent {
2023-08-25T11:15:28.202299003Z       _events: [Object: null prototype],
2023-08-25T11:15:28.202303727Z       _eventsCount: 2,
2023-08-25T11:15:28.202363995Z       _maxListeners: undefined,
2023-08-25T11:15:28.202369103Z       defaultPort: 443,
2023-08-25T11:15:28.202373422Z       protocol: 'https:',
2023-08-25T11:15:28.202400631Z       options: [Object: null prototype],
2023-08-25T11:15:28.202405287Z       requests: [Object: null prototype] {},
2023-08-25T11:15:28.202409661Z       sockets: [Object: null prototype] {},
2023-08-25T11:15:28.202414185Z       freeSockets: [Object: null prototype],
2023-08-25T11:15:28.202418885Z       keepAliveMsecs: 1000,
2023-08-25T11:15:28.202423512Z       keepAlive: true,
2023-08-25T11:15:28.202428240Z       maxSockets: Infinity,
2023-08-25T11:15:28.202432952Z       maxFreeSockets: 256,
2023-08-25T11:15:28.202437707Z       scheduling: 'lifo',
2023-08-25T11:15:28.202442079Z       maxTotalSockets: Infinity,
2023-08-25T11:15:28.202464083Z       totalSocketCount: 2,
2023-08-25T11:15:28.202469539Z       maxCachedSessions: 100,
2023-08-25T11:15:28.202473990Z       _sessionCache: [Object],
2023-08-25T11:15:28.202478508Z       [Symbol(kCapture)]: false
2023-08-25T11:15:28.202482942Z     },
2023-08-25T11:15:28.202487766Z     socketPath: undefined,
2023-08-25T11:15:28.202492311Z     method: 'GET',
2023-08-25T11:15:28.202497066Z     maxHeaderSize: undefined,
2023-08-25T11:15:28.202501587Z     insecureHTTPParser: undefined,
2023-08-25T11:15:28.202518774Z     joinDuplicateHeaders: undefined,
2023-08-25T11:15:28.202524392Z     path: '/v1//models',
2023-08-25T11:15:28.202528792Z     _ended: true,
2023-08-25T11:15:28.202541050Z     res: IncomingMessage {
2023-08-25T11:15:28.202545954Z       _readableState: [ReadableState],
2023-08-25T11:15:28.202550564Z       _events: [Object: null prototype],
2023-08-25T11:15:28.202555426Z       _eventsCount: 4,
2023-08-25T11:15:28.202560113Z       _maxListeners: undefined,
2023-08-25T11:15:28.202564999Z       socket: null,
2023-08-25T11:15:28.202569613Z       httpVersionMajor: 1,
2023-08-25T11:15:28.202574548Z       httpVersionMinor: 1,
2023-08-25T11:15:28.202609293Z       httpVersion: '1.1',
2023-08-25T11:15:28.202614759Z       complete: true,
2023-08-25T11:15:28.202619623Z       rawHeaders: [Array],
2023-08-25T11:15:28.203084206Z       rawTrailers: [],
2023-08-25T11:15:28.203109320Z       joinDuplicateHeaders: undefined,
2023-08-25T11:15:28.203114575Z       aborted: false,
2023-08-25T11:15:28.203119055Z       upgrade: false,
2023-08-25T11:15:28.203123467Z       url: '',
2023-08-25T11:15:28.203128136Z       method: null,
2023-08-25T11:15:28.203132499Z       statusCode: 401,
2023-08-25T11:15:28.203137033Z       statusMessage: 'Unauthorized',
2023-08-25T11:15:28.203141893Z       client: [TLSSocket],
2023-08-25T11:15:28.203146243Z       _consuming: false,
2023-08-25T11:15:28.203165383Z       _dumped: false,
2023-08-25T11:15:28.203171113Z       req: [Circular *1],
2023-08-25T11:15:28.203176117Z       responseUrl: 'https://api.openai.com/v1//models',
2023-08-25T11:15:28.203180861Z       redirects: [],
2023-08-25T11:15:28.203185293Z       [Symbol(kCapture)]: false,
2023-08-25T11:15:28.203190101Z       [Symbol(kHeaders)]: [Object],
2023-08-25T11:15:28.203194583Z       [Symbol(kHeadersCount)]: 26,
2023-08-25T11:15:28.203199267Z       [Symbol(kTrailers)]: null,
2023-08-25T11:15:28.203203981Z       [Symbol(kTrailersCount)]: 0
2023-08-25T11:15:28.203208591Z     },
2023-08-25T11:15:28.203230047Z     aborted: false,
2023-08-25T11:15:28.203235995Z     timeoutCb: null,
2023-08-25T11:15:28.203240410Z     upgradeOrConnect: false,
2023-08-25T11:15:28.203244881Z     parser: null,
2023-08-25T11:15:28.203249577Z     maxHeadersCount: null,
2023-08-25T11:15:28.203254328Z     reusedSocket: false,
2023-08-25T11:15:28.203269751Z     host: 'api.openai.com',
2023-08-25T11:15:28.203275492Z     protocol: 'https:',
2023-08-25T11:15:28.203280033Z     _redirectable: Writable {
2023-08-25T11:15:28.203285017Z       _writableState: [WritableState],
2023-08-25T11:15:28.203289622Z       _events: [Object: null prototype],
2023-08-25T11:15:28.203294580Z       _eventsCount: 3,
2023-08-25T11:15:28.203299298Z       _maxListeners: undefined,
2023-08-25T11:15:28.203303940Z       _options: [Object],
2023-08-25T11:15:28.203695901Z       _ended: true,
2023-08-25T11:15:28.203712757Z       _ending: true,
2023-08-25T11:15:28.203717595Z       _redirectCount: 0,
2023-08-25T11:15:28.203721876Z       _redirects: [],
2023-08-25T11:15:28.203726601Z       _requestBodyLength: 0,
2023-08-25T11:15:28.203730986Z       _requestBodyBuffers: [],
2023-08-25T11:15:28.203735746Z       _onNativeResponse: [Function (anonymous)],
2023-08-25T11:15:28.203740563Z       _currentRequest: [Circular *1],
2023-08-25T11:15:28.203745562Z       _currentUrl: 'https://api.openai.com/v1//models',
2023-08-25T11:15:28.203750062Z       [Symbol(kCapture)]: false
2023-08-25T11:15:28.203784590Z     },
2023-08-25T11:15:28.203789684Z     [Symbol(kCapture)]: false,
2023-08-25T11:15:28.203794188Z     [Symbol(kBytesWritten)]: 0,
2023-08-25T11:15:28.203799276Z     [Symbol(kNeedDrain)]: false,
2023-08-25T11:15:28.203803845Z     [Symbol(corked)]: 0,
2023-08-25T11:15:28.203828478Z     [Symbol(kOutHeaders)]: [Object: null prototype] {
2023-08-25T11:15:28.203833740Z       accept: [Array],
2023-08-25T11:15:28.203838374Z       authorization: [Array],
2023-08-25T11:15:28.203843463Z       'user-agent': [Array],
2023-08-25T11:15:28.203848107Z       'accept-encoding': [Array],
2023-08-25T11:15:28.203853087Z       host: [Array]
2023-08-25T11:15:28.203857867Z     },
2023-08-25T11:15:28.203863023Z     [Symbol(errored)]: null,
2023-08-25T11:15:28.203867597Z     [Symbol(kHighWaterMark)]: 16384,
2023-08-25T11:15:28.203872349Z     [Symbol(kUniqueHeaders)]: null
2023-08-25T11:15:28.203892640Z   },
2023-08-25T11:15:28.203898333Z   response: {
2023-08-25T11:15:28.203902938Z     status: 401,
2023-08-25T11:15:28.203907592Z     statusText: 'Unauthorized',
...

Screenshots

No response

Code of Conduct

danny-avila commented 11 months ago

Hi @nikhase thanks for the report! This should be an easy fix as the validator schema would need to be made more lenient to this end, and there are already several tests for it but not for this case

validators: api/strategies/validators.js Tests: api/strategies/validators.spec.js

I can start work on this right now, and you can let me know if I've fully addressed this

nikhase commented 11 months ago

Hi @danny-avila , thanks for the prompt (pun intended! 😁 ) response! In general, we mostly have é, è, ä,ö,ü. Are there pre-defined validators that contain the whole german and french alphabet?

Do I see it correctly that it's done in this line? https://github.com/danny-avila/LibreChat/blob/b48c618f326015b5e4469be471dd9cf453f1ddfa/api/strategies/validators.js#L35C1-L36C1

danny-avila commented 11 months ago

Do I see it correctly that it's done in this line? https://github.com/danny-avila/LibreChat/blob/b48c618f326015b5e4469be471dd9cf453f1ddfa/api/strategies/validators.js#L35C1-L36C1

Yes I've already put in a PR #969 that should close this issue! Going to merge and let me know if it solves your use case