mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-28 15:00:59 -05:00
fix(auth/oidc): string "undefined" for missing userinfo response fields
The userinfo response endpoint from the OIDC provider should not be trusted to return what we expect. Fields could be undefined. In that case HedgeDoc would have written "undefined" into the fields for profile picture or email address. This fix checks for fields being undefined and returns a default value in that case. Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
parent
e8793271a0
commit
c4c5cbd5d0
1 changed files with 40 additions and 9 deletions
|
@ -9,7 +9,7 @@ import {
|
||||||
InternalServerErrorException,
|
InternalServerErrorException,
|
||||||
NotFoundException,
|
NotFoundException,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { Client, generators, Issuer } from 'openid-client';
|
import { Client, generators, Issuer, UserinfoResponse } from 'openid-client';
|
||||||
|
|
||||||
import appConfiguration, { AppConfig } from '../../config/app.config';
|
import appConfiguration, { AppConfig } from '../../config/app.config';
|
||||||
import authConfiguration, {
|
import authConfiguration, {
|
||||||
|
@ -178,16 +178,31 @@ export class OidcService {
|
||||||
|
|
||||||
request.session.oidcIdToken = tokenSet.id_token;
|
request.session.oidcIdToken = tokenSet.id_token;
|
||||||
const userInfoResponse = await client.userinfo(tokenSet);
|
const userInfoResponse = await client.userinfo(tokenSet);
|
||||||
const userId = String(
|
const userId = OidcService.getResponseFieldValue(
|
||||||
userInfoResponse[oidcConfig.userIdField] || userInfoResponse.sub,
|
userInfoResponse,
|
||||||
|
oidcConfig.userIdField,
|
||||||
|
userInfoResponse.sub,
|
||||||
);
|
);
|
||||||
const username = String(
|
const username = OidcService.getResponseFieldValue(
|
||||||
userInfoResponse[oidcConfig.userNameField] ||
|
userInfoResponse,
|
||||||
userInfoResponse[oidcConfig.userIdField],
|
oidcConfig.userNameField,
|
||||||
|
userId,
|
||||||
).toLowerCase() as Lowercase<string>;
|
).toLowerCase() as Lowercase<string>;
|
||||||
const displayName = String(userInfoResponse[oidcConfig.displayNameField]);
|
const displayName = OidcService.getResponseFieldValue(
|
||||||
const email = String(userInfoResponse[oidcConfig.emailField]);
|
userInfoResponse,
|
||||||
const photoUrl = String(userInfoResponse[oidcConfig.profilePictureField]);
|
oidcConfig.displayNameField,
|
||||||
|
username,
|
||||||
|
);
|
||||||
|
const email = OidcService.getResponseFieldValue(
|
||||||
|
userInfoResponse,
|
||||||
|
oidcConfig.emailField,
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
const photoUrl = OidcService.getResponseFieldValue(
|
||||||
|
userInfoResponse,
|
||||||
|
oidcConfig.profilePictureField,
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
const newUserData = {
|
const newUserData = {
|
||||||
username,
|
username,
|
||||||
displayName,
|
displayName,
|
||||||
|
@ -261,4 +276,20 @@ export class OidcService {
|
||||||
}
|
}
|
||||||
return `${endSessionEndpoint}?post_logout_redirect_uri=${this.appConfig.baseUrl}${idToken ? `&id_token_hint=${idToken}` : ''}`;
|
return `${endSessionEndpoint}?post_logout_redirect_uri=${this.appConfig.baseUrl}${idToken ? `&id_token_hint=${idToken}` : ''}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a specific field from the userinfo object or a default value.
|
||||||
|
*
|
||||||
|
* @param {UserinfoResponse} response The response from the OIDC userinfo endpoint
|
||||||
|
* @param {string} field The field to get from the response
|
||||||
|
* @param {string|undefined} defaultValue The default value to return if the value is empty
|
||||||
|
* @returns {string|undefined} The value of the field from the response or the default value
|
||||||
|
*/
|
||||||
|
private static getResponseFieldValue<T extends string | undefined>(
|
||||||
|
response: UserinfoResponse,
|
||||||
|
field: string,
|
||||||
|
defaultValue: T,
|
||||||
|
): string | T {
|
||||||
|
return response[field] ? String(response[field]) : defaultValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue