From 320f98a8a753e5b583216d26401f4808f18b0c2c Mon Sep 17 00:00:00 2001 From: MathieuSevignyLavallee <89943988+MathieuSevignyLavallee@users.noreply.github.com> Date: Thu, 19 Sep 2024 17:10:41 -0400 Subject: [PATCH 01/11] Auth config .env.auth for docker-compose and Load environment variables in the backend --- .env.auth | 22 ++++++++++++++++++++++ docker-compose.yaml | 2 ++ server/config/auth.js | 30 ++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 .env.auth create mode 100644 server/config/auth.js diff --git a/.env.auth b/.env.auth new file mode 100644 index 0000000..f86d774 --- /dev/null +++ b/.env.auth @@ -0,0 +1,22 @@ +# Type of Autorizarions +SIMPLE_LOGIN_ACTIVE=false +OAUTH_ACTIVE=false +OIDC_ACTIVE=false + +# Configuration Simple Login +SESSION_SECRET=your_session_secret + +# Configuration OAuth +OAUTH_AUTHORIZATION_URL=https://www.testurl.com/oauth2/authorize +OAUTH_TOKEN_URL=https://www.testurl.com/oauth2/token +OAUTH_CLIENT_ID=your_oauth_client_id +OAUTH_CLIENT_SECRET=your_oauth_client_secret +OAUTH_CALLBACK_URL=https://localhost:3000/auth/provider/callback +OAUTH_ADD_SCOPE=scopes +OAUTH_ROLE_TEACHER_VALUE=teacher-claim-value + +# Configuration OIDC +OIDC_CLIENT_ID=your_oidc_client_id +OIDC_CLIENT_SECRET=your_oidc_client_secret +OIDC_ISSUER_URL=https://your-issuer.com +OIDC_CALLBACK_URL=http://localhost:3000/auth/oidc/callback diff --git a/docker-compose.yaml b/docker-compose.yaml index 284a46e..93e29f2 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -14,6 +14,8 @@ services: container_name: backend ports: - "3000:3000" + env_file: + - .env.auth environment: PORT: 3000 MONGO_URI: "mongodb://mongo:27017/evaluetonsavoir" diff --git a/server/config/auth.js b/server/config/auth.js new file mode 100644 index 0000000..167512e --- /dev/null +++ b/server/config/auth.js @@ -0,0 +1,30 @@ +require('dotenv').config({ path: './.env.auth' }); + +module.exports = { + // Activer ou désactiver les types d'authentifications + simpleLoginActive: process.env.SIMPLE_LOGIN_ACTIVE === 'true', + oauthActive: process.env.OAUTH_ACTIVE === 'true', + oidcActive: process.env.OIDC_ACTIVE === 'true', + + // Configuration Simple Login + sessionSecret: process.env.SESSION_SECRET || 'default_session_secret', + + // Configuration OAuth + oauth: { + authorizationURL: process.env.OAUTH_AUTHORIZATION_URL || '', + tokenURL: process.env.OAUTH_TOKEN_URL || '', + clientID: process.env.OAUTH_CLIENT_ID || '', + clientSecret: process.env.OAUTH_CLIENT_SECRET || '', + callbackURL: process.env.OAUTH_CALLBACK_URL || '', + scope: process.env.OAUTH_ADD_SCOPE || '', + teacherRoleClaim: process.env.OAUTH_ROLE_TEACHER_VALUE || '', + }, + + // Configuration OIDC + oidc: { + clientID: process.env.OIDC_CLIENT_ID || '', + clientSecret: process.env.OIDC_CLIENT_SECRET || '', + issuerURL: process.env.OIDC_ISSUER_URL || '', + callbackURL: process.env.OIDC_CALLBACK_URL || '', + } +}; From e3de6853c74af76b2027549ae3921b5068b35bc4 Mon Sep 17 00:00:00 2001 From: MathieuSevignyLavallee <89943988+MathieuSevignyLavallee@users.noreply.github.com> Date: Sun, 22 Sep 2024 10:41:02 -0400 Subject: [PATCH 02/11] studentRoleClaim --- .env.auth | 1 + server/config/auth.js | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.env.auth b/.env.auth index f86d774..18c9a63 100644 --- a/.env.auth +++ b/.env.auth @@ -14,6 +14,7 @@ OAUTH_CLIENT_SECRET=your_oauth_client_secret OAUTH_CALLBACK_URL=https://localhost:3000/auth/provider/callback OAUTH_ADD_SCOPE=scopes OAUTH_ROLE_TEACHER_VALUE=teacher-claim-value +OAUTH_ROLE_STUDENT_VALUE=student-claim-value # Configuration OIDC OIDC_CLIENT_ID=your_oidc_client_id diff --git a/server/config/auth.js b/server/config/auth.js index 167512e..c1effd2 100644 --- a/server/config/auth.js +++ b/server/config/auth.js @@ -1,15 +1,15 @@ require('dotenv').config({ path: './.env.auth' }); module.exports = { - // Activer ou désactiver les types d'authentifications + // Enable or disable the types of authentications simpleLoginActive: process.env.SIMPLE_LOGIN_ACTIVE === 'true', - oauthActive: process.env.OAUTH_ACTIVE === 'true', - oidcActive: process.env.OIDC_ACTIVE === 'true', + oauthActive: process.env.OAUTH_ACTIVE === 'false', + oidcActive: process.env.OIDC_ACTIVE === 'false', - // Configuration Simple Login + // Simple Login Configuration sessionSecret: process.env.SESSION_SECRET || 'default_session_secret', - // Configuration OAuth + // OAuth Configuration oauth: { authorizationURL: process.env.OAUTH_AUTHORIZATION_URL || '', tokenURL: process.env.OAUTH_TOKEN_URL || '', @@ -18,9 +18,10 @@ module.exports = { callbackURL: process.env.OAUTH_CALLBACK_URL || '', scope: process.env.OAUTH_ADD_SCOPE || '', teacherRoleClaim: process.env.OAUTH_ROLE_TEACHER_VALUE || '', + studentRoleClaim: process.env.OAUTH_ROLE_STUDENT_VALUE || '', // Added based on env file }, - // Configuration OIDC + // OIDC Configuration oidc: { clientID: process.env.OIDC_CLIENT_ID || '', clientSecret: process.env.OIDC_CLIENT_SECRET || '', From 6dde0cca386e307f1abd5d1e2b38e056c1164774 Mon Sep 17 00:00:00 2001 From: MathieuSevignyLavallee <89943988+MathieuSevignyLavallee@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:52:41 -0400 Subject: [PATCH 03/11] Routes for Auth Backend routes simple pour envoyer au frontend quel type de auth est disponible --- .env.auth | 2 +- server/app.js | 2 ++ server/config/auth.js | 4 +--- server/controllers/auth.js | 23 +++++++++++++++++++++++ server/routers/auth.js | 9 +++++++++ 5 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 server/controllers/auth.js create mode 100644 server/routers/auth.js diff --git a/.env.auth b/.env.auth index 18c9a63..65fb680 100644 --- a/.env.auth +++ b/.env.auth @@ -1,5 +1,5 @@ # Type of Autorizarions -SIMPLE_LOGIN_ACTIVE=false +SIMPLE_LOGIN_ACTIVE=true OAUTH_ACTIVE=false OIDC_ACTIVE=false diff --git a/server/app.js b/server/app.js index 76053ba..88e8da4 100644 --- a/server/app.js +++ b/server/app.js @@ -12,6 +12,7 @@ const userRouter = require('./routers/users.js'); const folderRouter = require('./routers/folders.js'); const quizRouter = require('./routers/quiz.js'); const imagesRouter = require('./routers/images.js') +const authRouter = require('./routers/auth.js') // Setup environement dotenv.config(); @@ -48,6 +49,7 @@ app.use('/api/user', userRouter); app.use('/api/folder', folderRouter); app.use('/api/quiz', quizRouter); app.use('/api/image', imagesRouter); +app.use('/api/auth', authRouter); app.use(errorHandler) diff --git a/server/config/auth.js b/server/config/auth.js index c1effd2..b675ce1 100644 --- a/server/config/auth.js +++ b/server/config/auth.js @@ -1,5 +1,3 @@ -require('dotenv').config({ path: './.env.auth' }); - module.exports = { // Enable or disable the types of authentications simpleLoginActive: process.env.SIMPLE_LOGIN_ACTIVE === 'true', @@ -18,7 +16,7 @@ module.exports = { callbackURL: process.env.OAUTH_CALLBACK_URL || '', scope: process.env.OAUTH_ADD_SCOPE || '', teacherRoleClaim: process.env.OAUTH_ROLE_TEACHER_VALUE || '', - studentRoleClaim: process.env.OAUTH_ROLE_STUDENT_VALUE || '', // Added based on env file + studentRoleClaim: process.env.OAUTH_ROLE_STUDENT_VALUE || '', }, // OIDC Configuration diff --git a/server/controllers/auth.js b/server/controllers/auth.js new file mode 100644 index 0000000..f468216 --- /dev/null +++ b/server/controllers/auth.js @@ -0,0 +1,23 @@ +const authConfig = require('../config/auth.js'); + +class authController { + + async getActive(req, res, next) { + try { + console.log(authConfig); + const authServices = { + simpleLoginActive: authConfig.simpleLoginActive, + oauthActive: authConfig.oauthActive, + oidcActive: authConfig.oidcActive + }; + + res.json(authServices); + } + catch (error) { + return next(error); + } + } + +} + +module.exports = new authController; \ No newline at end of file diff --git a/server/routers/auth.js b/server/routers/auth.js new file mode 100644 index 0000000..7fce26c --- /dev/null +++ b/server/routers/auth.js @@ -0,0 +1,9 @@ +const express = require('express'); +const router = express.Router(); +const jwt = require('../middleware/jwtToken.js'); + +const authController = require('../controllers/auth.js') + +router.get("/getActiveAuth", authController.getActive); + +module.exports = router; \ No newline at end of file From 97e7a4888fa789692a0e7a46bb04a112e3630231 Mon Sep 17 00:00:00 2001 From: MathieuSevignyLavallee <89943988+MathieuSevignyLavallee@users.noreply.github.com> Date: Sun, 22 Sep 2024 15:01:29 -0400 Subject: [PATCH 04/11] ajustement auth env --- server/config/auth.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/config/auth.js b/server/config/auth.js index b675ce1..dbcdca8 100644 --- a/server/config/auth.js +++ b/server/config/auth.js @@ -1,8 +1,8 @@ module.exports = { // Enable or disable the types of authentications - simpleLoginActive: process.env.SIMPLE_LOGIN_ACTIVE === 'true', - oauthActive: process.env.OAUTH_ACTIVE === 'false', - oidcActive: process.env.OIDC_ACTIVE === 'false', + simpleLoginActive: process.env.SIMPLE_LOGIN_ACTIVE || 'true', + oauthActive: process.env.OAUTH_ACTIVE || 'false', + oidcActive: process.env.OIDC_ACTIVE || 'false', // Simple Login Configuration sessionSecret: process.env.SESSION_SECRET || 'default_session_secret', From 4849380b731cd6c5410583f48d4f46e9143b7b33 Mon Sep 17 00:00:00 2001 From: MathieuSevignyLavallee <89943988+MathieuSevignyLavallee@users.noreply.github.com> Date: Sun, 22 Sep 2024 21:00:15 -0400 Subject: [PATCH 05/11] Dynamic auth config --- .env.auth | 23 ------------ auth_config.json | 32 ++++++++++++++++ docker-compose.yaml | 2 + server/config/auth.js | 75 +++++++++++++++++++++++++------------- server/controllers/auth.js | 17 +++++---- 5 files changed, 93 insertions(+), 56 deletions(-) delete mode 100644 .env.auth create mode 100644 auth_config.json diff --git a/.env.auth b/.env.auth deleted file mode 100644 index 65fb680..0000000 --- a/.env.auth +++ /dev/null @@ -1,23 +0,0 @@ -# Type of Autorizarions -SIMPLE_LOGIN_ACTIVE=true -OAUTH_ACTIVE=false -OIDC_ACTIVE=false - -# Configuration Simple Login -SESSION_SECRET=your_session_secret - -# Configuration OAuth -OAUTH_AUTHORIZATION_URL=https://www.testurl.com/oauth2/authorize -OAUTH_TOKEN_URL=https://www.testurl.com/oauth2/token -OAUTH_CLIENT_ID=your_oauth_client_id -OAUTH_CLIENT_SECRET=your_oauth_client_secret -OAUTH_CALLBACK_URL=https://localhost:3000/auth/provider/callback -OAUTH_ADD_SCOPE=scopes -OAUTH_ROLE_TEACHER_VALUE=teacher-claim-value -OAUTH_ROLE_STUDENT_VALUE=student-claim-value - -# Configuration OIDC -OIDC_CLIENT_ID=your_oidc_client_id -OIDC_CLIENT_SECRET=your_oidc_client_secret -OIDC_ISSUER_URL=https://your-issuer.com -OIDC_CALLBACK_URL=http://localhost:3000/auth/oidc/callback diff --git a/auth_config.json b/auth_config.json new file mode 100644 index 0000000..d5569e5 --- /dev/null +++ b/auth_config.json @@ -0,0 +1,32 @@ +{ + "auth": { + "passportjs": [ + { + "provider1": { + "OAUTH_AUTHORIZATION_URL": "https://www.testurl.com/oauth2/authorize", + "OAUTH_TOKEN_URL": "https://www.testurl.com/oauth2/token", + "OAUTH_CLIENT_ID": "your_oauth_client_id", + "OAUTH_CLIENT_SECRET": "your_oauth_client_secret", + "OAUTH_CALLBACK_URL": "https://localhost:3000/auth/provider/callback", + "OAUTH_ADD_SCOPE": "scopes", + "OAUTH_ROLE_TEACHER_VALUE": "teacher-claim-value", + "OAUTH_ROLE_STUDENT_VALUE": "student-claim-value" + } + }, + { + "provider2": { + "type": "oidc", + "OIDC_CLIENT_ID": "your_oidc_client_id", + "OIDC_CLIENT_SECRET": "your_oidc_client_secret", + "OIDC_ISSUER_URL": "https://your-issuer.com", + "OIDC_CALLBACK_URL": "http://localhost:3000/auth/oidc/callback" + } + } + ], + "simple-login": { + "enabled": true, + "name": "provider3", + "SESSION_SECRET": "your_session_secret" + } + } +} \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 93e29f2..9f91bd6 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -25,6 +25,8 @@ services: EMAIL_PSW: 'vvml wmfr dkzb vjzb' JWT_SECRET: haQdgd2jp09qb897GeBZyJetC8ECSpbFJe FRONTEND_URL: "http://localhost:5173" + volumes: + - ./auth_config.json:/usr/src/app/serveur/config/auth_config.json depends_on: - mongo restart: always diff --git a/server/config/auth.js b/server/config/auth.js index dbcdca8..493dd0c 100644 --- a/server/config/auth.js +++ b/server/config/auth.js @@ -1,29 +1,52 @@ -module.exports = { - // Enable or disable the types of authentications - simpleLoginActive: process.env.SIMPLE_LOGIN_ACTIVE || 'true', - oauthActive: process.env.OAUTH_ACTIVE || 'false', - oidcActive: process.env.OIDC_ACTIVE || 'false', +const fs = require('fs'); +const path = require('path'); - // Simple Login Configuration - sessionSecret: process.env.SESSION_SECRET || 'default_session_secret', +class AuthConfig { - // OAuth Configuration - oauth: { - authorizationURL: process.env.OAUTH_AUTHORIZATION_URL || '', - tokenURL: process.env.OAUTH_TOKEN_URL || '', - clientID: process.env.OAUTH_CLIENT_ID || '', - clientSecret: process.env.OAUTH_CLIENT_SECRET || '', - callbackURL: process.env.OAUTH_CALLBACK_URL || '', - scope: process.env.OAUTH_ADD_SCOPE || '', - teacherRoleClaim: process.env.OAUTH_ROLE_TEACHER_VALUE || '', - studentRoleClaim: process.env.OAUTH_ROLE_STUDENT_VALUE || '', - }, - - // OIDC Configuration - oidc: { - clientID: process.env.OIDC_CLIENT_ID || '', - clientSecret: process.env.OIDC_CLIENT_SECRET || '', - issuerURL: process.env.OIDC_ISSUER_URL || '', - callbackURL: process.env.OIDC_CALLBACK_URL || '', + constructor(configPath) { + this.configPath = configPath; + this.config = this.loadConfig(); } -}; + + // Méthode pour lire le fichier de configuration JSON + loadConfig() { + try { + const configData = fs.readFileSync(this.configPath, 'utf-8'); + return JSON.parse(configData); + } catch (error) { + console.error("Erreur lors de la lecture du fichier de configuration :", error); + return null; + } + } + + // Méthode pour retourner la configuration des fournisseurs PassportJS + getPassportJSConfig() { + if (this.config && this.config.auth && this.config.auth.passportjs) { + const passportConfig = {}; + + this.config.auth.passportjs.forEach(provider => { + const providerName = Object.keys(provider)[0]; + passportConfig[providerName] = provider[providerName]; + }); + + return passportConfig; + } else { + return { error: "Aucune configuration PassportJS disponible." }; + } + } + + // Méthode pour retourner la configuration de Simple Login + getSimpleLoginConfig() { + if (this.config && this.config.auth && this.config.auth["simple-login"]) { + return this.config.auth["simple-login"]; + } else { + return { error: "Aucune configuration Simple Login disponible." }; + } + } +} + +// Utilisation de la classe ConfigManager +const configPath = path.join(__dirname, './auth_config.json'); +const instance = new AuthConfig(configPath); +module.exports = instance; + diff --git a/server/controllers/auth.js b/server/controllers/auth.js index f468216..8d7fa53 100644 --- a/server/controllers/auth.js +++ b/server/controllers/auth.js @@ -3,18 +3,21 @@ const authConfig = require('../config/auth.js'); class authController { async getActive(req, res, next) { + try { - console.log(authConfig); - const authServices = { - simpleLoginActive: authConfig.simpleLoginActive, - oauthActive: authConfig.oauthActive, - oidcActive: authConfig.oidcActive + + const passportConfig = authConfig.getPassportJSConfig(); + const simpleLoginConfig = authConfig.getSimpleLoginConfig(); + + const response = { + passportConfig, + simpleLoginConfig }; - res.json(authServices); + return res.json(response); } catch (error) { - return next(error); + return next(error); // Gérer l'erreur } } From 5040c2189ddd72b09ea4764973b7ac8128489360 Mon Sep 17 00:00:00 2001 From: MathieuSevignyLavallee <89943988+MathieuSevignyLavallee@users.noreply.github.com> Date: Sun, 22 Sep 2024 21:04:07 -0400 Subject: [PATCH 06/11] jwt auth for route auth --- server/routers/auth.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/routers/auth.js b/server/routers/auth.js index 7fce26c..8e8fb4a 100644 --- a/server/routers/auth.js +++ b/server/routers/auth.js @@ -4,6 +4,6 @@ const jwt = require('../middleware/jwtToken.js'); const authController = require('../controllers/auth.js') -router.get("/getActiveAuth", authController.getActive); +router.get("/getActiveAuth",jwt.authenticate, authController.getActive); module.exports = router; \ No newline at end of file From 052de4dd9d86e6ecb8c67a43c06fb74eca72dec4 Mon Sep 17 00:00:00 2001 From: MathieuSevignyLavallee <89943988+MathieuSevignyLavallee@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:24:07 -0400 Subject: [PATCH 07/11] cleanup --- docker-compose.yaml | 2 -- server/config/auth.js | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 9f91bd6..077e2ae 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -14,8 +14,6 @@ services: container_name: backend ports: - "3000:3000" - env_file: - - .env.auth environment: PORT: 3000 MONGO_URI: "mongodb://mongo:27017/evaluetonsavoir" diff --git a/server/config/auth.js b/server/config/auth.js index 493dd0c..fffb426 100644 --- a/server/config/auth.js +++ b/server/config/auth.js @@ -1,5 +1,6 @@ const fs = require('fs'); const path = require('path'); +const pathAuthConfig = './auth_config.json'; class AuthConfig { @@ -46,7 +47,7 @@ class AuthConfig { } // Utilisation de la classe ConfigManager -const configPath = path.join(__dirname, './auth_config.json'); +const configPath = path.join(__dirname, pathAuthConfig); const instance = new AuthConfig(configPath); module.exports = instance; From dd6a38854dc093f2b288833485f7866c6cc3129d Mon Sep 17 00:00:00 2001 From: MathieuSevignyLavallee <89943988+MathieuSevignyLavallee@users.noreply.github.com> Date: Tue, 24 Sep 2024 22:00:28 -0400 Subject: [PATCH 08/11] =?UTF-8?q?Ajout=20de=20fonction=20et=20de=20v=C3=A9?= =?UTF-8?q?rification?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- auth_config.json | 23 +++++++ docker-compose.yaml | 4 +- server/config/auth.js | 121 ++++++++++++++++++++++++++++++++++++- server/controllers/auth.js | 6 +- 4 files changed, 148 insertions(+), 6 deletions(-) diff --git a/auth_config.json b/auth_config.json index d5569e5..3acc914 100644 --- a/auth_config.json +++ b/auth_config.json @@ -3,6 +3,7 @@ "passportjs": [ { "provider1": { + "type": "oauth", "OAUTH_AUTHORIZATION_URL": "https://www.testurl.com/oauth2/authorize", "OAUTH_TOKEN_URL": "https://www.testurl.com/oauth2/token", "OAUTH_CLIENT_ID": "your_oauth_client_id", @@ -21,6 +22,28 @@ "OIDC_ISSUER_URL": "https://your-issuer.com", "OIDC_CALLBACK_URL": "http://localhost:3000/auth/oidc/callback" } + }, + { + "provider3": { + "type": "oauth", + "OAUTH_AUTHORIZATION_URL": "https://www.testurl.com/oauth2/authorize", + "OAUTH_TOKEN_URL": "https://www.testurl.com/oauth2/token", + "OAUTH_CLIENT_ID": "your_oauth_client_id", + "OAUTH_CLIENT_SECRET": "your_oauth_client_secret", + "OAUTH_CALLBACK_URL": "https://localhost:3000/auth/provider/callback", + "OAUTH_ADD_SCOPE": "scopes", + "OAUTH_ROLE_TEACHER_VALUE": "teacher-claim-value", + "OAUTH_ROLE_STUDENT_VALUE": "student-claim-value" + } + }, + { + "provider4": { + "type": "oidc", + "OIDC_CLIENT_ID": "your_oidc_client_id", + "OIDC_CLIENT_SECRET": "your_oidc_client_secret", + "OIDC_ISSUER_URL": "https://your-issuer.com", + "OIDC_CALLBACK_URL": "http://localhost:3000/auth/oidc/callback" + } } ], "simple-login": { diff --git a/docker-compose.yaml b/docker-compose.yaml index 077e2ae..568258a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -10,7 +10,9 @@ services: restart: always backend: - image: fuhrmanator/evaluetonsavoir-backend:latest + build: + context: ./server + dockerfile: Dockerfile container_name: backend ports: - "3000:3000" diff --git a/server/config/auth.js b/server/config/auth.js index fffb426..7487cc1 100644 --- a/server/config/auth.js +++ b/server/config/auth.js @@ -7,6 +7,7 @@ class AuthConfig { constructor(configPath) { this.configPath = configPath; this.config = this.loadConfig(); + this.validateProvidersConfig(); } // Méthode pour lire le fichier de configuration JSON @@ -44,10 +45,128 @@ class AuthConfig { return { error: "Aucune configuration Simple Login disponible." }; } } + + // Méthode pour retourner tous les providers de type OAuth + getOAuthProviders() { + if (this.config && this.config.auth && this.config.auth.passportjs) { + const oauthProviders = this.config.auth.passportjs.filter(provider => { + const providerName = Object.keys(provider)[0]; + return provider[providerName].type === 'oauth'; + }); + + if (oauthProviders.length > 0) { + return oauthProviders; + } else { + return { error: "Aucun fournisseur OAuth disponible." }; + } + } else { + return { error: "Aucune configuration PassportJS disponible." }; + } + } + + // Méthode pour retourner tous les providers de type OIDC + getOIDCProviders() { + if (this.config && this.config.auth && this.config.auth.passportjs) { + const oidcProviders = this.config.auth.passportjs.filter(provider => { + const providerName = Object.keys(provider)[0]; + return provider[providerName].type === 'oidc'; + }); + + if (oidcProviders.length > 0) { + return oidcProviders; + } else { + return { error: "Aucun fournisseur OIDC disponible." }; + } + } else { + return { error: "Aucune configuration PassportJS disponible." }; + } + } + + // Méthode pour vérifier si tous les providers ont les variables nécessaires + validateProvidersConfig() { + const requiredOAuthFields = [ + 'OAUTH_AUTHORIZATION_URL', 'OAUTH_TOKEN_URL', 'OAUTH_CLIENT_ID', 'OAUTH_CLIENT_SECRET', 'OAUTH_CALLBACK_URL' + ]; + + const requiredOIDCFields = [ + 'OIDC_CLIENT_ID', 'OIDC_CLIENT_SECRET', 'OIDC_ISSUER_URL', 'OIDC_CALLBACK_URL' + ]; + + const missingFieldsReport = []; + + if (this.config && this.config.auth && this.config.auth.passportjs) { + this.config.auth.passportjs.forEach(provider => { + const providerName = Object.keys(provider)[0]; + const providerConfig = provider[providerName]; + + let missingFields = []; + + // Vérification des providers de type OAuth + if (providerConfig.type === 'oauth') { + missingFields = requiredOAuthFields.filter(field => !(field in providerConfig)); + } + // Vérification des providers de type OIDC + else if (providerConfig.type === 'oidc') { + missingFields = requiredOIDCFields.filter(field => !(field in providerConfig)); + } + + // Si des champs manquent, on les ajoute au rapport + if (missingFields.length > 0) { + missingFieldsReport.push({ + provider: providerName, + missingFields: missingFields + }); + } + }); + + // Si des champs manquent, lever une exception + if (missingFieldsReport.length > 0) { + throw new Error(`Configuration invalide pour les providers suivants : ${JSON.stringify(missingFieldsReport, null, 2)}`); + } else { + console.log("Configuration auth_config.json: Tous les providers ont les variables nécessaires.") + return { success: "Tous les providers ont les variables nécessaires." }; + } + } else { + throw new Error("Aucune configuration PassportJS disponible."); + } + } + + // Méthode pour retourner la configuration des fournisseurs PassportJS pour le frontend + getActiveAuth() { + if (this.config && this.config.auth && this.config.auth.passportjs) { + const passportConfig = {}; + + this.config.auth.passportjs.forEach(provider => { + const providerName = Object.keys(provider)[0]; + const providerConfig = provider[providerName]; + + // On inclut uniquement les champs nécessaires pour le frontend + passportConfig[providerName] = {}; + + if (providerConfig.type === 'oauth') { + passportConfig[providerName] = { + type: providerConfig.type, + authorizationUrl: providerConfig.OAUTH_AUTHORIZATION_URL, + callbackUrl: providerConfig.OAUTH_CALLBACK_URL, + }; + } else if (providerConfig.type === 'oidc') { + passportConfig[providerName] = { + type: providerConfig.type, + issuerUrl: providerConfig.OIDC_ISSUER_URL, + callbackUrl: providerConfig.OIDC_CALLBACK_URL + }; + } + }); + + return passportConfig; + } else { + return { error: "Aucune configuration PassportJS disponible." }; + } + } + } // Utilisation de la classe ConfigManager const configPath = path.join(__dirname, pathAuthConfig); const instance = new AuthConfig(configPath); module.exports = instance; - diff --git a/server/controllers/auth.js b/server/controllers/auth.js index 8d7fa53..845e062 100644 --- a/server/controllers/auth.js +++ b/server/controllers/auth.js @@ -6,12 +6,10 @@ class authController { try { - const passportConfig = authConfig.getPassportJSConfig(); - const simpleLoginConfig = authConfig.getSimpleLoginConfig(); + const authActive = authConfig.getActiveAuth(); const response = { - passportConfig, - simpleLoginConfig + authActive }; return res.json(response); From 9c10fbec69b48dee1b0ddd3ed4e1a216f43deecb Mon Sep 17 00:00:00 2001 From: MathieuSevignyLavallee <89943988+MathieuSevignyLavallee@users.noreply.github.com> Date: Tue, 24 Sep 2024 22:01:16 -0400 Subject: [PATCH 09/11] docker-compose typo --- docker-compose.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 568258a..077e2ae 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -10,9 +10,7 @@ services: restart: always backend: - build: - context: ./server - dockerfile: Dockerfile + image: fuhrmanator/evaluetonsavoir-backend:latest container_name: backend ports: - "3000:3000" From 63769e9bafd402de0ee674e846f24f6a189777c1 Mon Sep 17 00:00:00 2001 From: MathieuSevignyLavallee <89943988+MathieuSevignyLavallee@users.noreply.github.com> Date: Tue, 24 Sep 2024 22:08:48 -0400 Subject: [PATCH 10/11] active auth simple login added --- server/config/auth.js | 53 ++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/server/config/auth.js b/server/config/auth.js index 7487cc1..fc54497 100644 --- a/server/config/auth.js +++ b/server/config/auth.js @@ -133,37 +133,48 @@ class AuthConfig { // Méthode pour retourner la configuration des fournisseurs PassportJS pour le frontend getActiveAuth() { - if (this.config && this.config.auth && this.config.auth.passportjs) { + if (this.config && this.config.auth) { const passportConfig = {}; - this.config.auth.passportjs.forEach(provider => { - const providerName = Object.keys(provider)[0]; - const providerConfig = provider[providerName]; + // Gestion des providers PassportJS + if (this.config.auth.passportjs) { + this.config.auth.passportjs.forEach(provider => { + const providerName = Object.keys(provider)[0]; + const providerConfig = provider[providerName]; - // On inclut uniquement les champs nécessaires pour le frontend - passportConfig[providerName] = {}; + passportConfig[providerName] = {}; - if (providerConfig.type === 'oauth') { - passportConfig[providerName] = { - type: providerConfig.type, - authorizationUrl: providerConfig.OAUTH_AUTHORIZATION_URL, - callbackUrl: providerConfig.OAUTH_CALLBACK_URL, - }; - } else if (providerConfig.type === 'oidc') { - passportConfig[providerName] = { - type: providerConfig.type, - issuerUrl: providerConfig.OIDC_ISSUER_URL, - callbackUrl: providerConfig.OIDC_CALLBACK_URL - }; - } - }); + if (providerConfig.type === 'oauth') { + passportConfig[providerName] = { + type: providerConfig.type, + authorizationUrl: providerConfig.OAUTH_AUTHORIZATION_URL, + callbackUrl: providerConfig.OAUTH_CALLBACK_URL, + }; + } else if (providerConfig.type === 'oidc') { + passportConfig[providerName] = { + type: providerConfig.type, + issuerUrl: providerConfig.OIDC_ISSUER_URL, + callbackUrl: providerConfig.OIDC_CALLBACK_URL + }; + } + }); + } + + // Gestion du Simple Login + if (this.config.auth["simple-login"] && this.config.auth["simple-login"].enabled) { + passportConfig['simple-login'] = { + type: "simple-login", + name: this.config.auth["simple-login"].name + }; + } return passportConfig; } else { - return { error: "Aucune configuration PassportJS disponible." }; + return { error: "Aucune configuration d'authentification disponible." }; } } + } // Utilisation de la classe ConfigManager From 3087e16e3e5fc1081a0c39a8b18df0299feeeab7 Mon Sep 17 00:00:00 2001 From: MathieuSevignyLavallee <89943988+MathieuSevignyLavallee@users.noreply.github.com> Date: Fri, 27 Sep 2024 14:16:11 -0400 Subject: [PATCH 11/11] added tests --- server/__tests__/auth.test.js | 103 ++++++++++++++++++++++++++++++++++ server/config/auth.js | 23 ++++---- server/controllers/auth.js | 9 +-- 3 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 server/__tests__/auth.test.js diff --git a/server/__tests__/auth.test.js b/server/__tests__/auth.test.js new file mode 100644 index 0000000..f4c8ea4 --- /dev/null +++ b/server/__tests__/auth.test.js @@ -0,0 +1,103 @@ +const request = require('supertest'); +const AuthConfig = require('../config/auth.js'); + +const mockConfig = { + "auth": { + "passportjs": [ + { + "provider1": { + "type": "oauth", + "OAUTH_AUTHORIZATION_URL": "https://www.testurl.com/oauth2/authorize", + "OAUTH_TOKEN_URL": "https://www.testurl.com/oauth2/token", + "OAUTH_CLIENT_ID": "your_oauth_client_id", + "OAUTH_CLIENT_SECRET": "your_oauth_client_secret", + "OAUTH_CALLBACK_URL": "https://localhost:3000/auth/provider/callback", + "OAUTH_ADD_SCOPE": "scopes", + "OAUTH_ROLE_TEACHER_VALUE": "teacher-claim-value", + "OAUTH_ROLE_STUDENT_VALUE": "student-claim-value" + } + }, + { + "provider2": { + "type": "oidc", + "OIDC_CLIENT_ID": "your_oidc_client_id", + "OIDC_CLIENT_SECRET": "your_oidc_client_secret", + "OIDC_ISSUER_URL": "https://your-issuer.com", + "OIDC_CALLBACK_URL": "http://localhost:3000/auth/oidc/callback" + } + } + ], + "simple-login": { + "enabled": true, + "name": "provider3", + "SESSION_SECRET": "your_session_secret" + } + } +}; + +// Créez une instance de AuthConfig en utilisant la configuration mockée +describe('AuthConfig Class Tests', () => { + let authConfigInstance; + + // Initialisez l'instance avec la configuration mockée + beforeAll(() => { + authConfigInstance = new AuthConfig(); + authConfigInstance.loadConfigTest(mockConfig); // On injecte la configuration mockée + }); + + it('devrait retourner la configuration PassportJS', () => { + const config = authConfigInstance.getPassportJSConfig(); + expect(config).toHaveProperty('provider1'); + expect(config).toHaveProperty('provider2'); + }); + + it('devrait retourner la configuration Simple Login', () => { + const config = authConfigInstance.getSimpleLoginConfig(); + expect(config).toHaveProperty('name', 'provider3'); + expect(config).toHaveProperty('SESSION_SECRET', 'your_session_secret'); + }); + + it('devrait retourner les providers OAuth', () => { + const oauthProviders = authConfigInstance.getOAuthProviders(); + expect(Array.isArray(oauthProviders)).toBe(true); + expect(oauthProviders.length).toBe(1); // Il y a un seul provider OAuth + expect(oauthProviders[0]).toHaveProperty('provider1'); + }); + + it('devrait valider la configuration des providers', () => { + expect(() => authConfigInstance.validateProvidersConfig()).not.toThrow(); + }); + + it('devrait lever une erreur si une configuration manque', () => { + const invalidMockConfig = { + "auth": { + "passportjs": [ + { + "provider1": { + "type": "oauth", + "OAUTH_CLIENT_ID": "your_oauth_client_id" // Il manque des champs nécessaires + } + } + ] + } + }; + + const instanceWithInvalidConfig = new AuthConfig(); + instanceWithInvalidConfig.loadConfigTest(invalidMockConfig); + + // Vérifiez que l'erreur est lancée avec les champs manquants corrects + expect(() => instanceWithInvalidConfig.validateProvidersConfig()).toThrow( + new Error(`Configuration invalide pour les providers suivants : [ + { + "provider": "provider1", + "missingFields": [ + "OAUTH_AUTHORIZATION_URL", + "OAUTH_TOKEN_URL", + "OAUTH_CLIENT_SECRET", + "OAUTH_CALLBACK_URL" + ] + } +]`) + ); + }); +}); \ No newline at end of file diff --git a/server/config/auth.js b/server/config/auth.js index fc54497..b8b1f34 100644 --- a/server/config/auth.js +++ b/server/config/auth.js @@ -2,25 +2,29 @@ const fs = require('fs'); const path = require('path'); const pathAuthConfig = './auth_config.json'; +const configPath = path.join(__dirname, pathAuthConfig); + class AuthConfig { - constructor(configPath) { - this.configPath = configPath; - this.config = this.loadConfig(); - this.validateProvidersConfig(); - } + config = null; + // Méthode pour lire le fichier de configuration JSON loadConfig() { try { - const configData = fs.readFileSync(this.configPath, 'utf-8'); - return JSON.parse(configData); + const configData = fs.readFileSync(configPath, 'utf-8'); + this.config = JSON.parse(configData); } catch (error) { console.error("Erreur lors de la lecture du fichier de configuration :", error); return null; } } + // Méthode pour load le fichier de test + loadConfigTest(mockConfig) { + this.config = mockConfig; + } + // Méthode pour retourner la configuration des fournisseurs PassportJS getPassportJSConfig() { if (this.config && this.config.auth && this.config.auth.passportjs) { @@ -177,7 +181,4 @@ class AuthConfig { } -// Utilisation de la classe ConfigManager -const configPath = path.join(__dirname, pathAuthConfig); -const instance = new AuthConfig(configPath); -module.exports = instance; +module.exports = AuthConfig; diff --git a/server/controllers/auth.js b/server/controllers/auth.js index 845e062..21fa3b1 100644 --- a/server/controllers/auth.js +++ b/server/controllers/auth.js @@ -1,17 +1,18 @@ -const authConfig = require('../config/auth.js'); +const AuthConfig = require('../config/auth.js'); class authController { async getActive(req, res, next) { - try { - const authActive = authConfig.getActiveAuth(); + const authC = new AuthConfig(); + authC.loadConfig(); + + const authActive = authC.getActiveAuth(); const response = { authActive }; - return res.json(response); } catch (error) {