From 1b664206894435cbfbe2dbb7a2348f119458c4db Mon Sep 17 00:00:00 2001 From: TomDakan Date: Wed, 5 Apr 2023 11:58:49 -0700 Subject: [PATCH 01/12] Updated Discord Authentication Module to allow optionally filtering based on Server Roles. Updated Discord Authentication Module to allow optionally filtering based on Server Roles. Added custom authentication error message. Added Discord-Oauth2 to package. Discord-Oauth2 is used to fetch role data from the specified server. --- .gitignore | 1 + package.json | 1 + server/helpers/error.js | 4 ++++ .../authentication/discord/authentication.js | 21 ++++++++++++++++++- .../authentication/discord/definition.yml | 5 +++++ yarn.lock | 5 +++++ 6 files changed, 36 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9e37fa62..038520a5 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,4 @@ test-results/ # Localization Resources /server/locales/**/*.yml +yarn.lock diff --git a/package.json b/package.json index 6717e922..2c8c37bb 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "dependency-graph": "0.11.0", "diff": "4.0.2", "diff2html": "3.1.14", + "discord-oauth2": "2.11.0", "dompurify": "2.4.3", "dotize": "0.3.0", "elasticsearch6": "npm:@elastic/elasticsearch@6", diff --git a/server/helpers/error.js b/server/helpers/error.js index f9a81779..15fc8677 100644 --- a/server/helpers/error.js +++ b/server/helpers/error.js @@ -73,6 +73,10 @@ module.exports = { message: 'You are not authorized to register. Your domain is not whitelisted.', code: 1011 }), + AuthDiscordRoleUnauthorized: CustomError('AuthDiscordRoleUnauthorized', { + message: 'You are not authorized to register. You lack the necessary Server Roles.', + code: 1012 + }), AuthRequired: CustomError('AuthRequired', { message: 'You must be authenticated to access this resource.', code: 1019 diff --git a/server/modules/authentication/discord/authentication.js b/server/modules/authentication/discord/authentication.js index eab94fd5..ec0b56f6 100644 --- a/server/modules/authentication/discord/authentication.js +++ b/server/modules/authentication/discord/authentication.js @@ -6,6 +6,18 @@ const DiscordStrategy = require('passport-discord').Strategy const _ = require('lodash') +const DiscordOauth2 = require('discord-oauth2') + +// Checks for the existence of all of the configured role IDs in the member's guild IDs. +function hasRoles(memberRoles, authRoles) { + if (memberRoles.every(value => { + return authRoles.includes(value) + })) { + return true + } else { + return false + } +}; module.exports = { init (passport, conf) { @@ -19,9 +31,16 @@ module.exports = { passReqToCallback: true }, async (req, accessToken, refreshToken, profile, cb) => { try { - if (conf.guildId && !_.some(profile.guilds, { id: conf.guildId })) { + if (conf.roles) { + const discord = new DiscordOauth2() + const memberRoles = await discord.getGuildMember(accessToken, conf.guildId) + if (!hasRoles(memberRoles.roles, conf.roles)) { + throw new WIKI.Error.AuthLoginFailed() + } + } else if (conf.guildId && !_.some(profile.guilds, { id: conf.guildId })) { throw new WIKI.Error.AuthLoginFailed() } + const user = await WIKI.models.users.processProfile({ providerKey: req.params.strategy, profile: { diff --git a/server/modules/authentication/discord/definition.yml b/server/modules/authentication/discord/definition.yml index e30becba..2262965d 100644 --- a/server/modules/authentication/discord/definition.yml +++ b/server/modules/authentication/discord/definition.yml @@ -23,3 +23,8 @@ props: title: Server ID hint: Optional - Your unique server identifier, such that only members are authorized order: 3 + roles: + type: String + title: Required Roles + hint: Optional - Comma-separated list of server role IDs that are required for access (you must hae a Server ID configured to use this.) + order: 4 diff --git a/yarn.lock b/yarn.lock index 19181d2b..fd781d9a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8490,6 +8490,11 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +discord-oauth2@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/discord-oauth2/-/discord-oauth2-2.11.0.tgz#799acc6777a216f8fbbf72d5ea29086eb4303f85" + integrity sha512-pIbgXm498f7vqNd8/7JwoLd36YMFOFASSJdqyCGdwQpaG7ULHu9nLyifpVXI1b88xvNLqQwqugS8jxkn8Ypd1Q== + doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" From e76d518041ff7181edb0b4d099121cfad00dd21e Mon Sep 17 00:00:00 2001 From: TomDakan Date: Mon, 25 Sep 2023 11:24:50 -0700 Subject: [PATCH 02/12] Added package.json. Fixed bug in authentication.js --- .../authentication/discord/authentication.js | 10 ++++----- .../authentication/discord/package-lock.json | 22 +++++++++++++++++++ .../authentication/discord/package.json | 19 ++++++++++++++++ 3 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 server/modules/authentication/discord/package-lock.json create mode 100644 server/modules/authentication/discord/package.json diff --git a/server/modules/authentication/discord/authentication.js b/server/modules/authentication/discord/authentication.js index ec0b56f6..67c079ca 100644 --- a/server/modules/authentication/discord/authentication.js +++ b/server/modules/authentication/discord/authentication.js @@ -6,12 +6,12 @@ const DiscordStrategy = require('passport-discord').Strategy const _ = require('lodash') -const DiscordOauth2 = require('discord-oauth2') +const DiscordOauth2 = require('./node_modules/discord-oauth2/index.js') //I don't remember why I -// Checks for the existence of all of the configured role IDs in the member's guild IDs. +// Checks for the existence of all of the required role IDs in the member's guild role IDs. function hasRoles(memberRoles, authRoles) { - if (memberRoles.every(value => { - return authRoles.includes(value) + if (authRoles.every(value => { + return memberRoles.includes(value) })) { return true } else { @@ -34,7 +34,7 @@ module.exports = { if (conf.roles) { const discord = new DiscordOauth2() const memberRoles = await discord.getGuildMember(accessToken, conf.guildId) - if (!hasRoles(memberRoles.roles, conf.roles)) { + if (!hasRoles(memberRoles.roles, conf.roles.split())) { throw new WIKI.Error.AuthLoginFailed() } } else if (conf.guildId && !_.some(profile.guilds, { id: conf.guildId })) { diff --git a/server/modules/authentication/discord/package-lock.json b/server/modules/authentication/discord/package-lock.json new file mode 100644 index 00000000..17756ef6 --- /dev/null +++ b/server/modules/authentication/discord/package-lock.json @@ -0,0 +1,22 @@ +{ + "name": "wikijs-discord-oauth2", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "wikijs-discord-oauth2", + "version": "1.0.0", + "license": "AGPL-3.0-or-later", + "dependencies": { + "discord-oauth2": "^2.11.0" + }, + "devDependencies": {} + }, + "node_modules/discord-oauth2": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/discord-oauth2/-/discord-oauth2-2.11.0.tgz", + "integrity": "sha512-pIbgXm498f7vqNd8/7JwoLd36YMFOFASSJdqyCGdwQpaG7ULHu9nLyifpVXI1b88xvNLqQwqugS8jxkn8Ypd1Q==" + } + } +} diff --git a/server/modules/authentication/discord/package.json b/server/modules/authentication/discord/package.json new file mode 100644 index 00000000..8c391798 --- /dev/null +++ b/server/modules/authentication/discord/package.json @@ -0,0 +1,19 @@ +{ + "name": "wikijs-discord-oauth2", + "version": "1.0.0", + "description": "Supports using Discord as a SSO source, and allows the administrator to configure discord groups that are required for authentication.", + "main": "authentication.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "wikijs", + "discord", + "sso" + ], + "author": "Tom Dakan", + "license": "AGPL-3.0-or-later", + "dependencies": { + "discord-oauth2": "^2.11.0" + } +} From b7189fbf7380ff9c257fb97cef00f03a785e3680 Mon Sep 17 00:00:00 2001 From: TomDakan Date: Mon, 25 Sep 2023 14:56:54 -0700 Subject: [PATCH 03/12] Update server/modules/authentication/discord/authentication.js cleaner refactoring of authentication logic. Co-authored-by: Tymoteusz Boba --- server/modules/authentication/discord/authentication.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/modules/authentication/discord/authentication.js b/server/modules/authentication/discord/authentication.js index 67c079ca..3c0af63a 100644 --- a/server/modules/authentication/discord/authentication.js +++ b/server/modules/authentication/discord/authentication.js @@ -34,7 +34,9 @@ module.exports = { if (conf.roles) { const discord = new DiscordOauth2() const memberRoles = await discord.getGuildMember(accessToken, conf.guildId) - if (!hasRoles(memberRoles.roles, conf.roles.split())) { + const authRoles = conf.roles.split(); + const { roles } = await discord.getGuildMember(accessToken, conf.guildId); + if (authRoles.every(role => roles.includes(role)) throw new WIKI.Error.AuthLoginFailed() } } else if (conf.guildId && !_.some(profile.guilds, { id: conf.guildId })) { From f960edb1a1ab87d4754ddf812ea166c0af01e530 Mon Sep 17 00:00:00 2001 From: TomDakan Date: Mon, 25 Sep 2023 14:59:54 -0700 Subject: [PATCH 04/12] Update .gitignore. Remove yarn.lock --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 038520a5..9e37fa62 100644 --- a/.gitignore +++ b/.gitignore @@ -47,4 +47,3 @@ test-results/ # Localization Resources /server/locales/**/*.yml -yarn.lock From cbc6e5068172890ddf8c669f566385a80039d703 Mon Sep 17 00:00:00 2001 From: TomDakan Date: Mon, 25 Sep 2023 15:02:26 -0700 Subject: [PATCH 05/12] Move initialization of DiscordOauth2 outside of passport strategy initialization --- server/modules/authentication/discord/authentication.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/modules/authentication/discord/authentication.js b/server/modules/authentication/discord/authentication.js index 3c0af63a..1a090199 100644 --- a/server/modules/authentication/discord/authentication.js +++ b/server/modules/authentication/discord/authentication.js @@ -21,6 +21,7 @@ function hasRoles(memberRoles, authRoles) { module.exports = { init (passport, conf) { + const discord = new DiscordOauth2() passport.use(conf.key, new DiscordStrategy({ clientID: conf.clientId, @@ -32,7 +33,6 @@ module.exports = { }, async (req, accessToken, refreshToken, profile, cb) => { try { if (conf.roles) { - const discord = new DiscordOauth2() const memberRoles = await discord.getGuildMember(accessToken, conf.guildId) const authRoles = conf.roles.split(); const { roles } = await discord.getGuildMember(accessToken, conf.guildId); From 7e0dfdce31520ffa26fe3723a8887a0a812b45ab Mon Sep 17 00:00:00 2001 From: TomDakan Date: Mon, 25 Sep 2023 15:02:48 -0700 Subject: [PATCH 06/12] Fixed spelling in user-facing hint. Co-authored-by: Tymoteusz Boba --- server/modules/authentication/discord/definition.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/modules/authentication/discord/definition.yml b/server/modules/authentication/discord/definition.yml index 2262965d..cd207f54 100644 --- a/server/modules/authentication/discord/definition.yml +++ b/server/modules/authentication/discord/definition.yml @@ -26,5 +26,5 @@ props: roles: type: String title: Required Roles - hint: Optional - Comma-separated list of server role IDs that are required for access (you must hae a Server ID configured to use this.) + hint: Optional - Comma-separated list of server role IDs that are required for access (you must have a Server ID property configured to use this.) order: 4 From c4f6976c7afa123bcf2bbb12114179c5bdb5cac8 Mon Sep 17 00:00:00 2001 From: TomDakan Date: Tue, 26 Sep 2023 08:43:15 -0700 Subject: [PATCH 07/12] clean up of module inclusion. Co-authored-by: Tymoteusz Boba --- server/modules/authentication/discord/authentication.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/modules/authentication/discord/authentication.js b/server/modules/authentication/discord/authentication.js index 1a090199..65cb421f 100644 --- a/server/modules/authentication/discord/authentication.js +++ b/server/modules/authentication/discord/authentication.js @@ -5,8 +5,8 @@ // ------------------------------------ const DiscordStrategy = require('passport-discord').Strategy +const DiscordOauth2 = require('./node_modules/discord-oauth2/index.js') const _ = require('lodash') -const DiscordOauth2 = require('./node_modules/discord-oauth2/index.js') //I don't remember why I // Checks for the existence of all of the required role IDs in the member's guild role IDs. function hasRoles(memberRoles, authRoles) { From 7c4f4faf38c54afb7a774b74024974693a530927 Mon Sep 17 00:00:00 2001 From: TomDakan Date: Tue, 26 Sep 2023 08:45:13 -0700 Subject: [PATCH 08/12] Update server/modules/authentication/discord/authentication.js Co-authored-by: Tymoteusz Boba --- .../modules/authentication/discord/authentication.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/server/modules/authentication/discord/authentication.js b/server/modules/authentication/discord/authentication.js index 65cb421f..26f4a42e 100644 --- a/server/modules/authentication/discord/authentication.js +++ b/server/modules/authentication/discord/authentication.js @@ -8,16 +8,6 @@ const DiscordStrategy = require('passport-discord').Strategy const DiscordOauth2 = require('./node_modules/discord-oauth2/index.js') const _ = require('lodash') -// Checks for the existence of all of the required role IDs in the member's guild role IDs. -function hasRoles(memberRoles, authRoles) { - if (authRoles.every(value => { - return memberRoles.includes(value) - })) { - return true - } else { - return false - } -}; module.exports = { init (passport, conf) { From f1839953251e7c27e79e5eaa5ca6fa84f1ac9c09 Mon Sep 17 00:00:00 2001 From: TomDakan Date: Tue, 26 Sep 2023 08:46:55 -0700 Subject: [PATCH 09/12] Removed duplicate call to discord.getGuildMember() Co-authored-by: Tymoteusz Boba --- server/modules/authentication/discord/authentication.js | 1 - 1 file changed, 1 deletion(-) diff --git a/server/modules/authentication/discord/authentication.js b/server/modules/authentication/discord/authentication.js index 26f4a42e..354768e9 100644 --- a/server/modules/authentication/discord/authentication.js +++ b/server/modules/authentication/discord/authentication.js @@ -23,7 +23,6 @@ module.exports = { }, async (req, accessToken, refreshToken, profile, cb) => { try { if (conf.roles) { - const memberRoles = await discord.getGuildMember(accessToken, conf.guildId) const authRoles = conf.roles.split(); const { roles } = await discord.getGuildMember(accessToken, conf.guildId); if (authRoles.every(role => roles.includes(role)) From a49898a5c9e7498bce89ad0615ea28d911a03de1 Mon Sep 17 00:00:00 2001 From: TomDakan Date: Tue, 26 Sep 2023 14:52:20 -0700 Subject: [PATCH 10/12] removed extra curly brace Co-authored-by: Tymoteusz Boba --- server/modules/authentication/discord/authentication.js | 1 - 1 file changed, 1 deletion(-) diff --git a/server/modules/authentication/discord/authentication.js b/server/modules/authentication/discord/authentication.js index 354768e9..aea2a2a1 100644 --- a/server/modules/authentication/discord/authentication.js +++ b/server/modules/authentication/discord/authentication.js @@ -27,7 +27,6 @@ module.exports = { const { roles } = await discord.getGuildMember(accessToken, conf.guildId); if (authRoles.every(role => roles.includes(role)) throw new WIKI.Error.AuthLoginFailed() - } } else if (conf.guildId && !_.some(profile.guilds, { id: conf.guildId })) { throw new WIKI.Error.AuthLoginFailed() } From 83e961262b8b0cb0cbb189d2410d75042559a4d9 Mon Sep 17 00:00:00 2001 From: TomDakan Date: Tue, 26 Sep 2023 16:12:50 -0700 Subject: [PATCH 11/12] Deleted server/modules/authentication/discord/package.json --- .../authentication/discord/package.json | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 server/modules/authentication/discord/package.json diff --git a/server/modules/authentication/discord/package.json b/server/modules/authentication/discord/package.json deleted file mode 100644 index 8c391798..00000000 --- a/server/modules/authentication/discord/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "wikijs-discord-oauth2", - "version": "1.0.0", - "description": "Supports using Discord as a SSO source, and allows the administrator to configure discord groups that are required for authentication.", - "main": "authentication.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "wikijs", - "discord", - "sso" - ], - "author": "Tom Dakan", - "license": "AGPL-3.0-or-later", - "dependencies": { - "discord-oauth2": "^2.11.0" - } -} From 3f123f304f3b085a72e4f5d205ec06adc489ceeb Mon Sep 17 00:00:00 2001 From: TomDakan Date: Tue, 26 Sep 2023 16:13:00 -0700 Subject: [PATCH 12/12] Deleted server/modules/authentication/discord/package-lock.json --- .../authentication/discord/package-lock.json | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 server/modules/authentication/discord/package-lock.json diff --git a/server/modules/authentication/discord/package-lock.json b/server/modules/authentication/discord/package-lock.json deleted file mode 100644 index 17756ef6..00000000 --- a/server/modules/authentication/discord/package-lock.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "wikijs-discord-oauth2", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "wikijs-discord-oauth2", - "version": "1.0.0", - "license": "AGPL-3.0-or-later", - "dependencies": { - "discord-oauth2": "^2.11.0" - }, - "devDependencies": {} - }, - "node_modules/discord-oauth2": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/discord-oauth2/-/discord-oauth2-2.11.0.tgz", - "integrity": "sha512-pIbgXm498f7vqNd8/7JwoLd36YMFOFASSJdqyCGdwQpaG7ULHu9nLyifpVXI1b88xvNLqQwqugS8jxkn8Ypd1Q==" - } - } -}