Skip to content

Commit

Permalink
🛂 fix: OIDC Username Array Edge Case (danny-avila#2394)
Browse files Browse the repository at this point in the history
* Patch for OpenID username

`username` is generally based on email, rather than `given_name`. The challenge with `given_name` is that it can be a multi-value array (ex: "Nick, Fullname"), which completely breaks the system with: 

```
LibreChat      | ValidationError: User validation failed: username: Cast to string failed for value "[ 'Nickname', 'Firstname' ]" (type Array) at path "username"
LibreChat      |     at Document.invalidate (/app/node_modules/mongoose/lib/document.js:3200:32)
LibreChat      |     at model.$set (/app/node_modules/mongoose/lib/document.js:1459:12)
LibreChat      |     at model.set [as username] (/app/node_modules/mongoose/lib/helpers/document/compile.js:205:19)
LibreChat      |     at OpenIDConnectStrategy._verify (/app/api/strategies/openidStrategy.js:127:27)
LibreChat      |     at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
```

* Update openidStrategy.js

* refactor(openidStrategy): add helper function for stringy username

---------

Co-authored-by: Danny Avila <[email protected]>
  • Loading branch information
ventz and danny-avila authored Apr 12, 2024
1 parent 9d137ce commit f380f26
Showing 1 changed file with 24 additions and 2 deletions.
26 changes: 24 additions & 2 deletions api/strategies/openidStrategy.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,26 @@ const downloadImage = async (url, imagePath, accessToken) => {
}
};

/**
* Converts an input into a string suitable for a username.
* If the input is a string, it will be returned as is.
* If the input is an array, elements will be joined with underscores.
* In case of undefined or other falsy values, a default value will be returned.
*
* @param {string | string[] | undefined} input - The input value to be converted into a username.
* @param {string} [defaultValue=''] - The default value to return if the input is falsy.
* @returns {string} The processed input as a string suitable for a username.
*/
function convertToUsername(input, defaultValue = '') {
if (typeof input === 'string') {
return input;
} else if (Array.isArray(input)) {
return input.join('_');
}

return defaultValue;
}

async function setupOpenId() {
try {
const issuer = await Issuer.discover(process.env.OPENID_ISSUER);
Expand Down Expand Up @@ -104,19 +124,21 @@ async function setupOpenId() {
}
}

const username = convertToUsername(userinfo.username || userinfo.given_name || userinfo.email);

if (!user) {
user = new User({
provider: 'openid',
openidId: userinfo.sub,
username: userinfo.username || userinfo.given_name || '',
username,
email: userinfo.email || '',
emailVerified: userinfo.email_verified || false,
name: fullName,
});
} else {
user.provider = 'openid';
user.openidId = userinfo.sub;
user.username = userinfo.username || userinfo.given_name || '';
user.username = username;
user.name = fullName;
}

Expand Down

0 comments on commit f380f26

Please sign in to comment.