mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-12-22 17:01:38 +00:00
enhancement(auth/oidc): allow manual defining end_session_endpoint URL
For non-OIDC compliant OAuth2 providers it was only possible to define the authorize, token and userinfo URLs but not the end_session_endpoint. This commit adds that functionality. Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
parent
53409825d4
commit
603ad8088c
5 changed files with 53 additions and 2 deletions
|
@ -524,7 +524,7 @@ describe('authConfig', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('odic', () => {
|
||||
describe('oidc', () => {
|
||||
const oidcNames = ['gitlab'];
|
||||
const providerName = 'Gitlab oAuth2';
|
||||
const issuer = 'https://gitlab.example.org';
|
||||
|
@ -534,7 +534,8 @@ describe('authConfig', () => {
|
|||
const authorizeUrl = 'https://example.org/auth';
|
||||
const tokenUrl = 'https://example.org/token';
|
||||
const userinfoUrl = 'https://example.org/user';
|
||||
const scope = 'some scopr';
|
||||
const endSessionUrl = 'https://example.org/end';
|
||||
const scope = 'some scope';
|
||||
const defaultScope = 'openid profile email';
|
||||
const userIdField = 'login';
|
||||
const defaultUserIdField = 'sub';
|
||||
|
@ -556,6 +557,7 @@ describe('authConfig', () => {
|
|||
HD_AUTH_OIDC_GITLAB_AUTHORIZE_URL: authorizeUrl,
|
||||
HD_AUTH_OIDC_GITLAB_TOKEN_URL: tokenUrl,
|
||||
HD_AUTH_OIDC_GITLAB_USERINFO_URL: userinfoUrl,
|
||||
HD_AUTH_OIDC_GITLAB_END_SESSION_URL: endSessionUrl,
|
||||
HD_AUTH_OIDC_GITLAB_SCOPE: scope,
|
||||
HD_AUTH_OIDC_GITLAB_USER_ID_FIELD: userIdField,
|
||||
HD_AUTH_OIDC_GITLAB_USER_NAME_FIELD: userNameField,
|
||||
|
@ -587,6 +589,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.theme).toEqual(theme);
|
||||
expect(firstOidc.authorizeUrl).toEqual(authorizeUrl);
|
||||
expect(firstOidc.tokenUrl).toEqual(tokenUrl);
|
||||
expect(firstOidc.endSessionUrl).toEqual(endSessionUrl);
|
||||
expect(firstOidc.scope).toEqual(scope);
|
||||
expect(firstOidc.userinfoUrl).toEqual(userinfoUrl);
|
||||
expect(firstOidc.userIdField).toEqual(userIdField);
|
||||
|
@ -620,6 +623,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.authorizeUrl).toEqual(authorizeUrl);
|
||||
expect(firstOidc.tokenUrl).toEqual(tokenUrl);
|
||||
expect(firstOidc.userinfoUrl).toEqual(userinfoUrl);
|
||||
expect(firstOidc.endSessionUrl).toEqual(endSessionUrl);
|
||||
expect(firstOidc.scope).toEqual(scope);
|
||||
expect(firstOidc.userIdField).toEqual(userIdField);
|
||||
expect(firstOidc.userNameField).toEqual(userNameField);
|
||||
|
@ -652,6 +656,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.authorizeUrl).toBeUndefined();
|
||||
expect(firstOidc.tokenUrl).toEqual(tokenUrl);
|
||||
expect(firstOidc.userinfoUrl).toEqual(userinfoUrl);
|
||||
expect(firstOidc.endSessionUrl).toEqual(endSessionUrl);
|
||||
expect(firstOidc.scope).toEqual(scope);
|
||||
expect(firstOidc.userIdField).toEqual(userIdField);
|
||||
expect(firstOidc.userNameField).toEqual(userNameField);
|
||||
|
@ -684,6 +689,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.authorizeUrl).toEqual(authorizeUrl);
|
||||
expect(firstOidc.tokenUrl).toBeUndefined();
|
||||
expect(firstOidc.userinfoUrl).toEqual(userinfoUrl);
|
||||
expect(firstOidc.endSessionUrl).toEqual(endSessionUrl);
|
||||
expect(firstOidc.scope).toEqual(scope);
|
||||
expect(firstOidc.userIdField).toEqual(userIdField);
|
||||
expect(firstOidc.userNameField).toEqual(userNameField);
|
||||
|
@ -716,6 +722,40 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.authorizeUrl).toEqual(authorizeUrl);
|
||||
expect(firstOidc.tokenUrl).toEqual(tokenUrl);
|
||||
expect(firstOidc.userinfoUrl).toBeUndefined();
|
||||
expect(firstOidc.endSessionUrl).toEqual(endSessionUrl);
|
||||
expect(firstOidc.scope).toEqual(scope);
|
||||
expect(firstOidc.userIdField).toEqual(userIdField);
|
||||
expect(firstOidc.userNameField).toEqual(userNameField);
|
||||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||
expect(firstOidc.emailField).toEqual(emailField);
|
||||
restore();
|
||||
});
|
||||
it('when HD_AUTH_OIDC_GITLAB_END_SESSION_URL is not set', () => {
|
||||
const restore = mockedEnv(
|
||||
{
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
...neededAuthConfig,
|
||||
...completeOidcConfig,
|
||||
HD_AUTH_OIDC_GITLAB_END_SESSION_URL: undefined,
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
},
|
||||
{
|
||||
clear: true,
|
||||
},
|
||||
);
|
||||
const config = authConfig();
|
||||
expect(config.oidc).toHaveLength(1);
|
||||
const firstOidc = config.oidc[0];
|
||||
expect(firstOidc.identifier).toEqual(oidcNames[0]);
|
||||
expect(firstOidc.issuer).toEqual(issuer);
|
||||
expect(firstOidc.clientID).toEqual(clientId);
|
||||
expect(firstOidc.clientSecret).toEqual(clientSecret);
|
||||
expect(firstOidc.theme).toEqual(theme);
|
||||
expect(firstOidc.authorizeUrl).toEqual(authorizeUrl);
|
||||
expect(firstOidc.tokenUrl).toEqual(tokenUrl);
|
||||
expect(firstOidc.userinfoUrl).toEqual(userinfoUrl);
|
||||
expect(firstOidc.endSessionUrl).toBeUndefined();
|
||||
expect(firstOidc.scope).toEqual(scope);
|
||||
expect(firstOidc.userIdField).toEqual(userIdField);
|
||||
expect(firstOidc.userNameField).toEqual(userNameField);
|
||||
|
@ -748,6 +788,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.authorizeUrl).toEqual(authorizeUrl);
|
||||
expect(firstOidc.tokenUrl).toEqual(tokenUrl);
|
||||
expect(firstOidc.userinfoUrl).toEqual(userinfoUrl);
|
||||
expect(firstOidc.endSessionUrl).toEqual(endSessionUrl);
|
||||
expect(firstOidc.scope).toEqual(defaultScope);
|
||||
expect(firstOidc.userIdField).toEqual(userIdField);
|
||||
expect(firstOidc.userNameField).toEqual(userNameField);
|
||||
|
@ -781,6 +822,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.tokenUrl).toEqual(tokenUrl);
|
||||
expect(firstOidc.scope).toEqual(scope);
|
||||
expect(firstOidc.userinfoUrl).toEqual(userinfoUrl);
|
||||
expect(firstOidc.endSessionUrl).toEqual(endSessionUrl);
|
||||
expect(firstOidc.userIdField).toEqual(defaultUserIdField);
|
||||
expect(firstOidc.userNameField).toEqual(userNameField);
|
||||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||
|
@ -813,6 +855,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.tokenUrl).toEqual(tokenUrl);
|
||||
expect(firstOidc.scope).toEqual(scope);
|
||||
expect(firstOidc.userinfoUrl).toEqual(userinfoUrl);
|
||||
expect(firstOidc.endSessionUrl).toEqual(endSessionUrl);
|
||||
expect(firstOidc.userIdField).toEqual(userIdField);
|
||||
expect(firstOidc.userNameField).toEqual(userNameField);
|
||||
expect(firstOidc.displayNameField).toEqual(defaultDisplayNameField);
|
||||
|
@ -845,6 +888,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.tokenUrl).toEqual(tokenUrl);
|
||||
expect(firstOidc.scope).toEqual(scope);
|
||||
expect(firstOidc.userinfoUrl).toEqual(userinfoUrl);
|
||||
expect(firstOidc.endSessionUrl).toEqual(endSessionUrl);
|
||||
expect(firstOidc.userIdField).toEqual(userIdField);
|
||||
expect(firstOidc.userNameField).toEqual(userNameField);
|
||||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||
|
@ -879,6 +923,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.tokenUrl).toEqual(tokenUrl);
|
||||
expect(firstOidc.scope).toEqual(scope);
|
||||
expect(firstOidc.userinfoUrl).toEqual(userinfoUrl);
|
||||
expect(firstOidc.endSessionUrl).toEqual(endSessionUrl);
|
||||
expect(firstOidc.userIdField).toEqual(userIdField);
|
||||
expect(firstOidc.userNameField).toEqual(userNameField);
|
||||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||
|
|
|
@ -43,6 +43,7 @@ export interface OidcConfig extends InternalIdentifier {
|
|||
authorizeUrl?: string;
|
||||
tokenUrl?: string;
|
||||
userinfoUrl?: string;
|
||||
endSessionUrl?: string;
|
||||
scope: string;
|
||||
userNameField: string;
|
||||
userIdField: string;
|
||||
|
@ -139,6 +140,7 @@ const authSchema = Joi.object({
|
|||
authorizeUrl: Joi.string().optional(),
|
||||
tokenUrl: Joi.string().optional(),
|
||||
userinfoUrl: Joi.string().optional(),
|
||||
endSessionUrl: Joi.string().optional(),
|
||||
scope: Joi.string().default('openid profile email').optional(),
|
||||
userIdField: Joi.string().default('sub').optional(),
|
||||
userNameField: Joi.string().default('preferred_username').optional(),
|
||||
|
@ -206,6 +208,7 @@ export default registerAs('authConfig', () => {
|
|||
authorizeUrl: process.env[`HD_AUTH_OIDC_${oidcName}_AUTHORIZE_URL`],
|
||||
tokenUrl: process.env[`HD_AUTH_OIDC_${oidcName}_TOKEN_URL`],
|
||||
userinfoUrl: process.env[`HD_AUTH_OIDC_${oidcName}_USERINFO_URL`],
|
||||
endSessionUrl: process.env[`HD_AUTH_OIDC_${oidcName}_END_SESSION_URL`],
|
||||
scope: process.env[`HD_AUTH_OIDC_${oidcName}_SCOPE`],
|
||||
userIdField: process.env[`HD_AUTH_OIDC_${oidcName}_USER_ID_FIELD`],
|
||||
userNameField: process.env[`HD_AUTH_OIDC_${oidcName}_USER_NAME_FIELD`],
|
||||
|
|
|
@ -84,6 +84,7 @@ export function replaceAuthErrorsWithEnvironmentVariables(
|
|||
newMessage = newMessage.replace('.authorizeUrl', '_AUTHORIZE_URL');
|
||||
newMessage = newMessage.replace('.tokenUrl', '_TOKEN_URL');
|
||||
newMessage = newMessage.replace('.userinfoUrl', '_USERINFO_URL');
|
||||
newMessage = newMessage.replace('.endSessionUrl', '_END_SESSION_URL');
|
||||
newMessage = newMessage.replace('.scope', '_SCOPE');
|
||||
newMessage = newMessage.replace('.tlsCaCerts', '_TLS_CERT_PATHS');
|
||||
newMessage = newMessage.replace('.issuer', '_ISSUER');
|
||||
|
|
|
@ -89,6 +89,7 @@ export class OidcService {
|
|||
authorization_endpoint: oidcConfig.authorizeUrl,
|
||||
token_endpoint: oidcConfig.tokenUrl,
|
||||
userinfo_endpoint: oidcConfig.userinfoUrl,
|
||||
end_session_endpoint: oidcConfig.endSessionUrl,
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
});
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ no OIDC (e.g., GitHub or Discord). In this case, you need the following addition
|
|||
| `HD_AUTH_OIDC_$NAME_AUTHORIZE_URL` | - | `https://auth.example.com/oauth2/auth` | The URL to which the user should be redirected to start the OAuth2 flow. |
|
||||
| `HD_AUTH_OIDC_$NAME_TOKEN_URL` | - | `https://auth.example.com/oauth2/token` | The URL to which the user should be redirected to exchange the code for an access token. |
|
||||
| `HD_AUTH_OIDC_$NAME_USERINFO_URL` | - | `https://auth.example.com/oauth2/userinfo` | The URL to which the user should be redirected to get the user information. |
|
||||
| `HD_AUTH_OIDC_$NAME_END_SESSION_URL` | - | `https://auth.example.com/oauth2/logout` | The URL to which the user should be redirected to end the session. |
|
||||
| `HD_AUTH_OIDC_$NAME_SCOPE` | - | `profile` | The scope that should be requested to get the user information. |
|
||||
| `HD_AUTH_OIDC_$NAME_USER_ID_FIELD` | `sub` | `sub`, `id` | The unique identifier that is returned for the user from the OAuth2 provider. |
|
||||
| `HD_AUTH_OIDC_$NAME_USER_ID_FIELD` | `sub` | `sub`, `id` | The unique identifier that is returned for the user from the OAuth2 provider. |
|
||||
|
|
Loading…
Reference in a new issue