From 2454cb3a956a9ab2428d2bc5b1abbd46469ae0a9 Mon Sep 17 00:00:00 2001 From: Eddi3_As Date: Sat, 1 Mar 2025 19:24:24 -0500 Subject: [PATCH 01/10] ajout callback uri et debug consoles --- client/Dockerfile | 2 +- docker-compose-local.yaml | 109 ++++++++++++++++++ docker-compose.yaml | 17 +-- .../auth/modules/passport-providers/oidc.js | 18 ++- server/package-lock.json | 10 ++ server/package.json | 1 + 6 files changed, 143 insertions(+), 14 deletions(-) create mode 100644 docker-compose-local.yaml diff --git a/client/Dockerfile b/client/Dockerfile index f1021e6..9e8ec7a 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -1,6 +1,6 @@ # client -FROM node:18 AS build +FROM node:20 AS build WORKDIR /usr/src/app/client diff --git a/docker-compose-local.yaml b/docker-compose-local.yaml new file mode 100644 index 0000000..0d8d61a --- /dev/null +++ b/docker-compose-local.yaml @@ -0,0 +1,109 @@ +version: '3' + +services: + + frontend: + build: + context: ./client + dockerfile: Dockerfile + container_name: frontend + ports: + - "5173:5173" + restart: always + + backend: + build: + context: ./server + dockerfile: Dockerfile + container_name: backend + ports: + - "3000:3000" + environment: + PORT: 3000 + MONGO_URI: "mongodb://mongo:27017/evaluetonsavoir" + MONGO_DATABASE: evaluetonsavoir + EMAIL_SERVICE: gmail + SENDER_EMAIL: infoevaluetonsavoir@gmail.com + EMAIL_PSW: 'vvml wmfr dkzb vjzb' + JWT_SECRET: haQdgd2jp09qb897GeBZyJetC8ECSpbFJe + SESSION_Secret: 'lookMomImQuizzing' + SITE_URL: http://localhost + FRONTEND_PORT: 5173 + USE_PORTS: false + AUTHENTICATED_ROOMS: false + volumes: + - ./server/auth_config.json:/usr/src/app/serveur/config/auth_config.json + depends_on: + - mongo + - keycloak + restart: always + + # Ce conteneur sert de routeur pour assurer le bon fonctionnement de l'application + nginx: + image: fuhrmanator/evaluetonsavoir-routeur:latest + container_name: nginx + ports: + - "80:80" + depends_on: + - backend + - frontend + restart: always + + # Ce conteneur est la base de données principale pour l'application + mongo: + image: mongo + container_name: mongo + ports: + - "27017:27017" + tty: true + volumes: + - mongodb_data:/data/db + restart: always + + # Ce conteneur cherche des mises à jour à 5h du matin + watchtower: + image: containrrr/watchtower + container_name: watchtower + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + - TZ=America/Montreal + - WATCHTOWER_CLEANUP=true + - WATCHTOWER_DEBUG=true + - WATCHTOWER_INCLUDE_RESTARTING=true + - WATCHTOWER_SCHEDULE=0 0 5 * * * # At 5 am everyday + restart: always + + watchtower-once: + image: containrrr/watchtower + container_name: watchtower-once + volumes: + - /var/run/docker.sock:/var/run/docker.sock + command: --run-once + environment: + - TZ=America/Montreal + - WATCHTOWER_CLEANUP=true + - WATCHTOWER_DEBUG=true + - WATCHTOWER_INCLUDE_RESTARTING=true + restart: "no" + + keycloak: + container_name: keycloak + image: quay.io/keycloak/keycloak:latest + environment: + KEYCLOAK_ADMIN: admin + KEYCLOAK_ADMIN_PASSWORD: admin123 + KC_HEALTH_ENABLED: 'true' + KC_FEATURES: preview + ports: + - "8080:8080" + volumes: + - ./oauth-tester/config.json:/opt/keycloak/data/import/realm-config.json + command: + - start-dev + - --import-realm + - --hostname-strict=false + +volumes: + mongodb_data: + external: false diff --git a/docker-compose.yaml b/docker-compose.yaml index 0d8d61a..b0c1410 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -3,18 +3,19 @@ version: '3' services: frontend: - build: - context: ./client - dockerfile: Dockerfile + image: fuhrmanator/evaluetonsavoir-frontend:latest container_name: frontend + environment: + # Define empty VITE_BACKEND_URL because it's production + - VITE_BACKEND_URL= + # Define empty VITE_BACKEND_SOCKET_URL so it will default to window.location.host + - VITE_BACKEND_SOCKET_URL= ports: - "5173:5173" restart: always backend: - build: - context: ./server - dockerfile: Dockerfile + image: fuhrmanator/evaluetonsavoir-backend:latest container_name: backend ports: - "3000:3000" @@ -28,11 +29,13 @@ services: JWT_SECRET: haQdgd2jp09qb897GeBZyJetC8ECSpbFJe SESSION_Secret: 'lookMomImQuizzing' SITE_URL: http://localhost + OIDC_URL: https://evalsa.etsmtl.ca FRONTEND_PORT: 5173 USE_PORTS: false AUTHENTICATED_ROOMS: false volumes: - - ./server/auth_config.json:/usr/src/app/serveur/config/auth_config.json + - /opt/EvalueTonSavoir/auth_config.json:/usr/src/app/serveur/auth_config.json + - /opt/EvalueTonSavoir/oauth-tester/config.json:/usr/src/app/serveur/oauth-tester/config.json depends_on: - mongo - keycloak diff --git a/server/auth/modules/passport-providers/oidc.js b/server/auth/modules/passport-providers/oidc.js index 9ccebf1..4b6e990 100644 --- a/server/auth/modules/passport-providers/oidc.js +++ b/server/auth/modules/passport-providers/oidc.js @@ -4,6 +4,7 @@ var users = require('../../../models/users'); var { hasNestedValue } = require('../../../utils'); const { MISSING_OIDC_PARAMETER } = require('../../../constants/errorCodes.js'); const AppError = require('../../../middleware/AppError.js'); +const expressListEndpoints = require('express-list-endpoints'); class PassportOpenIDConnect { constructor(passportjs, auth_name) { @@ -23,11 +24,16 @@ class PassportOpenIDConnect { async register(app, passport, endpoint, name, provider) { - const config = await this.getConfigFromConfigURL(name, provider) - const cb_url = `${process.env['BACKEND_URL']}${endpoint}/${name}/callback` - const self = this - const scope = 'openid profile email ' + `${provider.OIDC_ADD_SCOPE}` + const config = await this.getConfigFromConfigURL(name, provider); + const cb_url = `${process.env['OIDC_URL']}${endpoint}/${name}/callback`; + const self = this; + const scope = 'openid profile email ' + `${provider.OIDC_ADD_SCOPE}`; + console.log(config); + console.log(''); + console.log(cb_url); + console.log(''); + console.log(scope); passport.use(name, new OpenIDConnectStrategy({ issuer: config.issuer, authorizationURL: config.authorization_endpoint, @@ -49,7 +55,6 @@ class PassportOpenIDConnect { roles: [] }; - if (hasNestedValue(profile, provider.OIDC_ROLE_TEACHER_VALUE)) received_user.roles.push('teacher') if (hasNestedValue(profile, provider.OIDC_ROLE_STUDENT_VALUE)) received_user.roles.push('student') @@ -99,7 +104,8 @@ class PassportOpenIDConnect { } } ); - console.info(`Ajout de la connexion : ${name}(OIDC)`) + console.info(`Ajout de la connexion : ${name}(OIDC)`); + console.log(expressListEndpoints(app)); } } diff --git a/server/package-lock.json b/server/package-lock.json index 1de4aeb..e0fdb07 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -14,6 +14,7 @@ "cors": "^2.8.5", "dotenv": "^16.4.4", "express": "^4.18.2", + "express-list-endpoints": "^7.1.1", "express-session": "^1.18.0", "jsonwebtoken": "^9.0.2", "mongodb": "^6.3.0", @@ -3247,6 +3248,15 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express-list-endpoints": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/express-list-endpoints/-/express-list-endpoints-7.1.1.tgz", + "integrity": "sha512-SA6YHH1r6DrioJ4fFJNqiwu1FweGFqJZO9KBApMzwPosoSGPOX2AW0wiMepOXjojjEXDuP9whIvckomheErbJA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/express-session": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.1.tgz", diff --git a/server/package.json b/server/package.json index 4eb536d..cd0348b 100644 --- a/server/package.json +++ b/server/package.json @@ -18,6 +18,7 @@ "cors": "^2.8.5", "dotenv": "^16.4.4", "express": "^4.18.2", + "express-list-endpoints": "^7.1.1", "express-session": "^1.18.0", "jsonwebtoken": "^9.0.2", "mongodb": "^6.3.0", From 2499f78b6a165e91b9f641a02561e815b66ab808 Mon Sep 17 00:00:00 2001 From: Eddi3_As Date: Sat, 1 Mar 2025 19:30:37 -0500 Subject: [PATCH 02/10] oauth-tester path modified --- docker-compose.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index b0c1410..539c800 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -35,7 +35,6 @@ services: AUTHENTICATED_ROOMS: false volumes: - /opt/EvalueTonSavoir/auth_config.json:/usr/src/app/serveur/auth_config.json - - /opt/EvalueTonSavoir/oauth-tester/config.json:/usr/src/app/serveur/oauth-tester/config.json depends_on: - mongo - keycloak @@ -101,7 +100,7 @@ services: ports: - "8080:8080" volumes: - - ./oauth-tester/config.json:/opt/keycloak/data/import/realm-config.json + - /opt/EvalueTonSavoir/oauth-tester/config.json:/opt/keycloak/data/import/realm-config.json command: - start-dev - --import-realm From a049ba5da18a8236bb507dd8a39b3df472b7ea72 Mon Sep 17 00:00:00 2001 From: Eddi3_As Date: Sat, 1 Mar 2025 23:01:31 -0500 Subject: [PATCH 03/10] FIX simpleauth for local dev --- client/Dockerfile | 2 +- .../pages/AuthManager/callback/AuthCallback.tsx | 2 +- server/auth/auth-manager.js | 5 ++++- server/auth/modules/simpleauth.js | 9 +++------ server/auth_config.json.example | 2 +- server/models/users.js | 16 +--------------- 6 files changed, 11 insertions(+), 25 deletions(-) diff --git a/client/Dockerfile b/client/Dockerfile index 9e8ec7a..f1021e6 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -1,6 +1,6 @@ # client -FROM node:20 AS build +FROM node:18 AS build WORKDIR /usr/src/app/client diff --git a/client/src/pages/AuthManager/callback/AuthCallback.tsx b/client/src/pages/AuthManager/callback/AuthCallback.tsx index 6206294..f05083d 100644 --- a/client/src/pages/AuthManager/callback/AuthCallback.tsx +++ b/client/src/pages/AuthManager/callback/AuthCallback.tsx @@ -15,7 +15,7 @@ const OAuthCallback: React.FC = () => { if (user) { apiService.saveToken(user); apiService.saveUsername(username || ""); - navigate('/'); + navigate('/teacher/dashboard'); } else { navigate('/login'); } diff --git a/server/auth/auth-manager.js b/server/auth/auth-manager.js index c38c44d..e09b8c4 100644 --- a/server/auth/auth-manager.js +++ b/server/auth/auth-manager.js @@ -50,13 +50,16 @@ class AuthManager{ } // eslint-disable-next-line no-unused-vars - async login(userInfo,req,res,next){ //passport and simpleauth use next + async login(email,pswd,req,res,next){ //passport and simpleauth use next + + const userInfo = await this.simpleregister.login(email, pswd); const tokenToSave = jwt.create(userInfo.email, userInfo._id,userInfo.roles); res.redirect(`/auth/callback?user=${tokenToSave}&username=${userInfo.name}`); console.info(`L'utilisateur '${userInfo.name}' vient de se connecter`) } async register(userInfos){ + console.log(userInfos); if (!userInfos.email || !userInfos.password) { throw new AppError(MISSING_REQUIRED_PARAMETER); } diff --git a/server/auth/modules/simpleauth.js b/server/auth/modules/simpleauth.js index b40f55d..b8628b5 100644 --- a/server/auth/modules/simpleauth.js +++ b/server/auth/modules/simpleauth.js @@ -32,7 +32,7 @@ class SimpleAuth { email: req.body.email, password: req.body.password, roles: req.body.roles - } + }; let user = await self.authmanager.register(userInfos) if (user) res.redirect("/login") } @@ -52,11 +52,8 @@ class SimpleAuth { error.statusCode = 400; throw error; } - - const userModel = self.authmanager.getUserModel(); - const user = userModel.login(email, password); - - await self.authmanager.login(user, req, res, next); + + await self.authmanager.login(email, password, req, res, next); } catch (error) { const statusCode = error.statusCode || 500; const message = error.message || "An internal server error occurred"; diff --git a/server/auth_config.json.example b/server/auth_config.json.example index 2a8fb11..ba8c10c 100644 --- a/server/auth_config.json.example +++ b/server/auth_config.json.example @@ -14,7 +14,7 @@ } } ], - "simple-login": { + "simpleauth": { "enabled": true, "name": "provider3", "SESSION_SECRET": "your_session_secret" diff --git a/server/models/users.js b/server/models/users.js index f18e708..d048d9f 100644 --- a/server/models/users.js +++ b/server/models/users.js @@ -53,20 +53,6 @@ class Users { return user; } - async login(userid) { - await this.db.connect(); - const conn = this.db.getConnection(); - - const userCollection = conn.collection("users"); - const user = await userCollection.findOne({ _id: userid }); - - if (!user) { - return false; - } - - return user; - } -/* async login(email, password) { try { await this.db.connect(); @@ -95,7 +81,7 @@ class Users { throw error; } } -*/ + async resetPassword(email) { const newPassword = this.generatePassword(); From 44c023e02363fb1f9d109ce22f8e173e23ef3e43 Mon Sep 17 00:00:00 2001 From: Eddi3_As Date: Sun, 2 Mar 2025 17:57:49 -0500 Subject: [PATCH 04/10] FIX error on user model not being init --- .../providers/SimpleLogin/Register.tsx | 2 +- server/auth/auth-manager.js | 12 +++++++++--- server/auth/modules/passport-providers/oauth.js | 15 +++++++-------- server/auth/modules/passport-providers/oidc.js | 13 ++++++------- server/auth/modules/passportjs.js | 4 ++-- server/auth/modules/simpleauth.js | 2 +- 6 files changed, 26 insertions(+), 22 deletions(-) diff --git a/client/src/pages/AuthManager/providers/SimpleLogin/Register.tsx b/client/src/pages/AuthManager/providers/SimpleLogin/Register.tsx index d33527d..46a8c85 100644 --- a/client/src/pages/AuthManager/providers/SimpleLogin/Register.tsx +++ b/client/src/pages/AuthManager/providers/SimpleLogin/Register.tsx @@ -12,7 +12,7 @@ const Register: React.FC = () => { const [name, setName] = useState(''); // State for name const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); - const [roles, setRoles] = useState(['student']); // Set 'student' as the default role + const [roles, setRoles] = useState(['teacher']); // Set 'student' as the default role const [connectionError, setConnectionError] = useState(''); const [isConnecting] = useState(false); diff --git a/server/auth/auth-manager.js b/server/auth/auth-manager.js index e09b8c4..170d35a 100644 --- a/server/auth/auth-manager.js +++ b/server/auth/auth-manager.js @@ -41,7 +41,7 @@ class AuthManager{ async registerAuths(){ for(const module of this.modules){ try{ - module.registerAuth(this.app) + module.registerAuth(this.app, this.simpleregister); } catch(error){ console.error(`L'enregistrement du module ${module} a échoué.`); console.error(`Error: ${error} `); @@ -50,8 +50,14 @@ class AuthManager{ } // eslint-disable-next-line no-unused-vars - async login(email,pswd,req,res,next){ //passport and simpleauth use next - + async login(userInfo,req,res,next){ //passport and simpleauth use next + const tokenToSave = jwt.create(userInfo.email, userInfo._id,userInfo.roles); + res.redirect(`/auth/callback?user=${tokenToSave}&username=${userInfo.name}`); + console.info(`L'utilisateur '${userInfo.name}' vient de se connecter`) + } + + // eslint-disable-next-line no-unused-vars + async loginSimple(email,pswd,req,res,next){ //passport and simpleauth use next const userInfo = await this.simpleregister.login(email, pswd); const tokenToSave = jwt.create(userInfo.email, userInfo._id,userInfo.roles); res.redirect(`/auth/callback?user=${tokenToSave}&username=${userInfo.name}`); diff --git a/server/auth/modules/passport-providers/oauth.js b/server/auth/modules/passport-providers/oauth.js index b05a5be..b32076d 100644 --- a/server/auth/modules/passport-providers/oauth.js +++ b/server/auth/modules/passport-providers/oauth.js @@ -1,6 +1,5 @@ var OAuth2Strategy = require('passport-oauth2') var authUserAssoc = require('../../../models/authUserAssociation') -var users = require('../../../models/users') var { hasNestedValue } = require('../../../utils') class PassportOAuth { @@ -9,8 +8,8 @@ class PassportOAuth { this.auth_name = auth_name } - register(app, passport, endpoint, name, provider) { - const cb_url = `${process.env['BACKEND_URL']}${endpoint}/${name}/callback` + register(app, passport, endpoint, name, provider, userModel) { + const cb_url = `${process.env['OIDC_URL']}${endpoint}/${name}/callback` const self = this const scope = 'openid profile email offline_access' + ` ${provider.OAUTH_ADD_SCOPE}`; @@ -43,14 +42,14 @@ class PassportOAuth { let user_account if (user_association) { - user_account = await users.getById(user_association.user_id) + user_account = await userModel.getById(user_association.user_id) } else { - let user_id = await users.getId(received_user.email) + let user_id = await userModel.getId(received_user.email) if (user_id) { - user_account = await users.getById(user_id); + user_account = await userModel.getById(user_id); } else { - received_user.password = users.generatePassword() + received_user.password = userModel.generatePassword() user_account = await self.passportjs.register(received_user) } await authUserAssoc.link(self.auth_name, received_user.auth_id, user_account._id) @@ -58,7 +57,7 @@ class PassportOAuth { user_account.name = received_user.name user_account.roles = received_user.roles - await users.editUser(user_account) + await userModel.editUser(user_account) // Store the tokens in the session req.session.oauth2Tokens = { diff --git a/server/auth/modules/passport-providers/oidc.js b/server/auth/modules/passport-providers/oidc.js index 4b6e990..5fda361 100644 --- a/server/auth/modules/passport-providers/oidc.js +++ b/server/auth/modules/passport-providers/oidc.js @@ -1,6 +1,5 @@ var OpenIDConnectStrategy = require('passport-openidconnect'); var authUserAssoc = require('../../../models/authUserAssociation'); -var users = require('../../../models/users'); var { hasNestedValue } = require('../../../utils'); const { MISSING_OIDC_PARAMETER } = require('../../../constants/errorCodes.js'); const AppError = require('../../../middleware/AppError.js'); @@ -22,7 +21,7 @@ class PassportOpenIDConnect { } } - async register(app, passport, endpoint, name, provider) { + async register(app, passport, endpoint, name, provider, userModel) { const config = await this.getConfigFromConfigURL(name, provider); const cb_url = `${process.env['OIDC_URL']}${endpoint}/${name}/callback`; @@ -62,14 +61,14 @@ class PassportOpenIDConnect { let user_account if (user_association) { - user_account = await users.getById(user_association.user_id) + user_account = await userModel.getById(user_association.user_id) } else { - let user_id = await users.getId(received_user.email) + let user_id = await userModel.getId(received_user.email) if (user_id) { - user_account = await users.getById(user_id); + user_account = await userModel.getById(user_id); } else { - received_user.password = users.generatePassword() + received_user.password = userModel.generatePassword() user_account = await self.passportjs.register(received_user) } await authUserAssoc.link(self.auth_name, received_user.auth_id, user_account._id) @@ -77,7 +76,7 @@ class PassportOpenIDConnect { user_account.name = received_user.name user_account.roles = received_user.roles - await users.editUser(user_account); + await userModel.editUser(user_account); return done(null, user_account); } catch (error) { diff --git a/server/auth/modules/passportjs.js b/server/auth/modules/passportjs.js index d88488b..c651eff 100644 --- a/server/auth/modules/passportjs.js +++ b/server/auth/modules/passportjs.js @@ -9,7 +9,7 @@ class PassportJs{ this.endpoint = "/api/auth" } - async registerAuth(expressapp){ + async registerAuth(expressapp, userModel){ expressapp.use(passport.initialize()); expressapp.use(passport.session()); @@ -21,7 +21,7 @@ class PassportJs{ this.registerProvider(provider.type,auth_id) } try{ - this.registeredProviders[provider.type].register(expressapp,passport,this.endpoint,name,provider) + this.registeredProviders[provider.type].register(expressapp,passport,this.endpoint,name,provider,userModel) authprovider.create(auth_id) } catch(error){ console.error(`La connexion ${name} de type ${provider.type} n'as pu être chargé.`); diff --git a/server/auth/modules/simpleauth.js b/server/auth/modules/simpleauth.js index b8628b5..e2c9300 100644 --- a/server/auth/modules/simpleauth.js +++ b/server/auth/modules/simpleauth.js @@ -53,7 +53,7 @@ class SimpleAuth { throw error; } - await self.authmanager.login(email, password, req, res, next); + await self.authmanager.loginSimple(email, password, req, res, next); } catch (error) { const statusCode = error.statusCode || 500; const message = error.message || "An internal server error occurred"; From c5d4368816bfa5710a60ea0f8a419bc7feb19c98 Mon Sep 17 00:00:00 2001 From: "C. Fuhrman" Date: Tue, 4 Mar 2025 13:50:12 -0500 Subject: [PATCH 05/10] Console logs --- server/auth/modules/passport-providers/oidc.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/server/auth/modules/passport-providers/oidc.js b/server/auth/modules/passport-providers/oidc.js index 5fda361..c2e3698 100644 --- a/server/auth/modules/passport-providers/oidc.js +++ b/server/auth/modules/passport-providers/oidc.js @@ -46,6 +46,8 @@ class PassportOpenIDConnect { }, // patch pour la librairie permet d'obtenir les groupes, PR en cours mais "morte" : https://github.com/jaredhanson/passport-openidconnect/pull/101 async function (req, issuer, profile, times, tok, done) { + console.log(`oidc.js: register: issuer: ${JSON.stringify(issuer)}`); + console.log(`oidc.js: register: profile: ${JSON.stringify(profile)}`); try { const received_user = { auth_id: profile.id, @@ -57,25 +59,35 @@ class PassportOpenIDConnect { if (hasNestedValue(profile, provider.OIDC_ROLE_TEACHER_VALUE)) received_user.roles.push('teacher') if (hasNestedValue(profile, provider.OIDC_ROLE_STUDENT_VALUE)) received_user.roles.push('student') - const user_association = await authUserAssoc.find_user_association(self.auth_name, received_user.auth_id) + console.log(`oidc.js: register: received_user: ${JSON.stringify(received_user)}`); + const user_association = await authUserAssoc.find_user_association(self.auth_name, received_user.auth_id); + console.log(`oidc.js: register: user_association: ${JSON.stringify(user_association)}`); let user_account if (user_association) { + console.log(`oidc.js: register: user_association: ${JSON.stringify(user_association)}`); user_account = await userModel.getById(user_association.user_id) + console.log(`oidc.js: register: user_account: ${JSON.stringify(user_account)}`); } else { + console.log(`oidc.js: register: user_association: ${JSON.stringify(user_association)}`); let user_id = await userModel.getId(received_user.email) + console.log(`oidc.js: register: user_id: ${JSON.stringify(user_id)}`); if (user_id) { user_account = await userModel.getById(user_id); + console.log(`oidc.js: register: user_account: ${JSON.stringify(user_account)}`); } else { received_user.password = userModel.generatePassword() user_account = await self.passportjs.register(received_user) + console.log(`oidc.js: register: user_account: ${JSON.stringify(user_account)}`); } + console.log(`oidc.js: register: authUserAssoc.ling.`); await authUserAssoc.link(self.auth_name, received_user.auth_id, user_account._id) } user_account.name = received_user.name user_account.roles = received_user.roles + console.log(`oidc.js: register: calling userModel.editUser: ${JSON.stringify(user_account)}`); await userModel.editUser(user_account); return done(null, user_account); From bb43eca7230a8a25055a95747dbf80e35a800a9a Mon Sep 17 00:00:00 2001 From: "C. Fuhrman" Date: Tue, 4 Mar 2025 14:03:43 -0500 Subject: [PATCH 06/10] fix profile displayName --- server/auth/modules/passport-providers/oidc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/auth/modules/passport-providers/oidc.js b/server/auth/modules/passport-providers/oidc.js index c2e3698..551123f 100644 --- a/server/auth/modules/passport-providers/oidc.js +++ b/server/auth/modules/passport-providers/oidc.js @@ -52,7 +52,7 @@ class PassportOpenIDConnect { const received_user = { auth_id: profile.id, email: profile.emails[0].value, - name: profile.name.givenName, + name: profile.displayName, roles: [] }; From c098d002c80cc6d152e2a7efc5b2ca0b0265981f Mon Sep 17 00:00:00 2001 From: "C. Fuhrman" Date: Tue, 4 Mar 2025 14:24:36 -0500 Subject: [PATCH 07/10] userModel traces --- server/app.js | 3 +-- server/auth/auth-manager.js | 4 +++- server/auth/modules/passport-providers/oidc.js | 14 +++++++++----- server/auth/modules/passportjs.js | 3 ++- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/server/app.js b/server/app.js index d2634c7..19ba3f9 100644 --- a/server/app.js +++ b/server/app.js @@ -103,8 +103,7 @@ app.use(session({ cookie: { secure: process.env.NODE_ENV === 'production' } })); -let authManager = new AuthManager(app,null,userModel); -authManager.getUserModel(); +let _authManager = new AuthManager(app,null,userModel); app.use(errorHandler); // Start server diff --git a/server/auth/auth-manager.js b/server/auth/auth-manager.js index 170d35a..96e75cf 100644 --- a/server/auth/auth-manager.js +++ b/server/auth/auth-manager.js @@ -7,6 +7,8 @@ const AppError = require('../middleware/AppError.js'); class AuthManager{ constructor(expressapp,configs=null,userModel){ + console.log(`AuthManager: constructor: configs: ${JSON.stringify(configs)}`); + console.log(`AuthManager: constructor: userModel: ${JSON.stringify(userModel)}`); this.modules = [] this.app = expressapp @@ -75,4 +77,4 @@ class AuthManager{ } } -module.exports = AuthManager; \ No newline at end of file +module.exports = AuthManager; diff --git a/server/auth/modules/passport-providers/oidc.js b/server/auth/modules/passport-providers/oidc.js index 551123f..f9cfd88 100644 --- a/server/auth/modules/passport-providers/oidc.js +++ b/server/auth/modules/passport-providers/oidc.js @@ -23,16 +23,20 @@ class PassportOpenIDConnect { async register(app, passport, endpoint, name, provider, userModel) { + console.log(`oidc.js: register: endpoint: ${endpoint}`); + console.log(`oidc.js: register: name: ${name}`); + console.log(`oidc.js: register: provider: ${JSON.stringify(provider)}`); + console.log(`oidc.js: register: userModel: ${JSON.stringify(userModel)}`); + const config = await this.getConfigFromConfigURL(name, provider); const cb_url = `${process.env['OIDC_URL']}${endpoint}/${name}/callback`; const self = this; const scope = 'openid profile email ' + `${provider.OIDC_ADD_SCOPE}`; - console.log(config); - console.log(''); - console.log(cb_url); - console.log(''); - console.log(scope); + console.log(`oidc.js: register: config: ${JSON.stringify(config)}`); + console.log(`oidc.js: register: cb_url: ${cb_url}`); + console.log(`oidc.js: register: scope: ${scope}`); + passport.use(name, new OpenIDConnectStrategy({ issuer: config.issuer, authorizationURL: config.authorization_endpoint, diff --git a/server/auth/modules/passportjs.js b/server/auth/modules/passportjs.js index c651eff..7eda887 100644 --- a/server/auth/modules/passportjs.js +++ b/server/auth/modules/passportjs.js @@ -10,6 +10,7 @@ class PassportJs{ } async registerAuth(expressapp, userModel){ + console.log(`PassportJs: registerAuth: userModel: ${JSON.stringify(userModel)}`); expressapp.use(passport.initialize()); expressapp.use(passport.session()); @@ -62,4 +63,4 @@ class PassportJs{ } -module.exports = PassportJs; \ No newline at end of file +module.exports = PassportJs; From fd160aaba719668fe50fd04907cc6284fe50f7e0 Mon Sep 17 00:00:00 2001 From: "C. Fuhrman" Date: Tue, 4 Mar 2025 14:47:44 -0500 Subject: [PATCH 08/10] order of init --- server/auth/auth-manager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/auth/auth-manager.js b/server/auth/auth-manager.js index 96e75cf..bdcc4d7 100644 --- a/server/auth/auth-manager.js +++ b/server/auth/auth-manager.js @@ -14,8 +14,8 @@ class AuthManager{ this.configs = configs ?? (new AuthConfig()).loadConfig() this.addModules() - this.registerAuths() this.simpleregister = userModel; + this.registerAuths() } getUserModel(){ @@ -41,6 +41,7 @@ class AuthManager{ } async registerAuths(){ + console.log(``); for(const module of this.modules){ try{ module.registerAuth(this.app, this.simpleregister); From 06797822b04e015cd9ecf82943929df7b0c816ed Mon Sep 17 00:00:00 2001 From: "C. Fuhrman" Date: Tue, 4 Mar 2025 15:41:58 -0500 Subject: [PATCH 09/10] hard-code teacher role --- client/src/services/ApiService.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/client/src/services/ApiService.tsx b/client/src/services/ApiService.tsx index 6d6e561..aae8823 100644 --- a/client/src/services/ApiService.tsx +++ b/client/src/services/ApiService.tsx @@ -73,6 +73,8 @@ class ApiService { return false; } + console.log("ApiService: isLoggedIn: Token:", token); + // Update token expiry this.saveToken(token); @@ -88,11 +90,19 @@ class ApiService { } try { + console.log("ApiService: isLoggedInTeacher: Token:", token); const decodedToken = jwtDecode(token) as { roles: string[] }; + /////// REMOVE BELOW + // automatically add teacher role if not present + if (!decodedToken.roles.includes('teacher')) { + decodedToken.roles.push('teacher'); + } + ////// REMOVE ABOVE const userRoles = decodedToken.roles; const requiredRole = 'teacher'; + console.log("ApiService: isLoggedInTeacher: UserRoles:", userRoles); if (!userRoles || !userRoles.includes(requiredRole)) { return false; } @@ -968,4 +978,4 @@ public async login(email: string, password: string): Promise { } const apiService = new ApiService(); -export default apiService; \ No newline at end of file +export default apiService; From e817746801223e883a59d1882d507ab4a6d42ccb Mon Sep 17 00:00:00 2001 From: "C. Fuhrman" Date: Tue, 4 Mar 2025 15:54:14 -0500 Subject: [PATCH 10/10] lowercase email to match the mongo user key --- server/auth/modules/passport-providers/oidc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/auth/modules/passport-providers/oidc.js b/server/auth/modules/passport-providers/oidc.js index f9cfd88..03da065 100644 --- a/server/auth/modules/passport-providers/oidc.js +++ b/server/auth/modules/passport-providers/oidc.js @@ -55,7 +55,7 @@ class PassportOpenIDConnect { try { const received_user = { auth_id: profile.id, - email: profile.emails[0].value, + email: profile.emails[0].value.toLowerCase(), name: profile.displayName, roles: [] };