From f648d028ab601db321a94831b93b86e4c7b4a5f1 Mon Sep 17 00:00:00 2001 From: Bruno Roesner Date: Sat, 19 Oct 2024 18:18:01 -0400 Subject: [PATCH 1/5] added environment variable to set room authentication --- docker-compose.yaml | 1 + server/.env.example | 2 ++ 2 files changed, 3 insertions(+) diff --git a/docker-compose.yaml b/docker-compose.yaml index 898a78a..770f6db 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -30,6 +30,7 @@ services: 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: diff --git a/server/.env.example b/server/.env.example index 8553a4b..3ab7212 100644 --- a/server/.env.example +++ b/server/.env.example @@ -19,3 +19,5 @@ SESSION_Secret='session_secret' SITE_URL=http://localhost FRONTEND_PORT=5173 USE_PORTS=false + +AUTHENTICATED_ROOMS=false From 98e3887bcd561a9925c28d8bf3d501d51ee98e4a Mon Sep 17 00:00:00 2001 From: Bruno Roesner Date: Sat, 19 Oct 2024 18:24:28 -0400 Subject: [PATCH 2/5] added route to check if rooms need authentication --- server/config/auth.js | 11 +++++++++++ server/controllers/auth.js | 11 +++++++++++ server/routers/auth.js | 1 + 3 files changed, 23 insertions(+) diff --git a/server/config/auth.js b/server/config/auth.js index 864d747..9497ea6 100644 --- a/server/config/auth.js +++ b/server/config/auth.js @@ -175,6 +175,17 @@ class AuthConfig { } } + // Check if students must be authenticated to join a room + getRoomsRequireAuth() { + const roomRequireAuth = process.env.AUTHENTICATED_ROOMS; + + if (!roomRequireAuth || roomRequireAuth !== "true") { + return false; + } + + return true; + } + } diff --git a/server/controllers/auth.js b/server/controllers/auth.js index 21fa3b1..76769fb 100644 --- a/server/controllers/auth.js +++ b/server/controllers/auth.js @@ -20,6 +20,17 @@ class authController { } } + async getRoomsRequireAuth(req, res, next) { + const authC = new AuthConfig(); + const roomsRequireAuth = authC.getRoomsRequireAuth(); + + const response = { + roomsRequireAuth + } + + return res.json(response); + } + } module.exports = new authController; \ No newline at end of file diff --git a/server/routers/auth.js b/server/routers/auth.js index c560864..7260669 100644 --- a/server/routers/auth.js +++ b/server/routers/auth.js @@ -5,5 +5,6 @@ const jwt = require('../middleware/jwtToken.js'); const authController = require('../controllers/auth.js') router.get("/getActiveAuth",authController.getActive); +router.get("/getRoomsRequireAuth", authController.getRoomsRequireAuth); module.exports = router; \ No newline at end of file From c04558e13972ffb2bd9c9c3c749b9a7aa369d5bb Mon Sep 17 00:00:00 2001 From: Bruno Roesner Date: Sat, 19 Oct 2024 18:31:43 -0400 Subject: [PATCH 3/5] added frontend room authentication navigation --- client/src/App.tsx | 9 ++++++++- client/src/services/ApiService.tsx | 11 +++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/client/src/App.tsx b/client/src/App.tsx index 5199afa..3fad6fd 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -28,6 +28,7 @@ import OAuthCallback from './pages/AuthManager/callback/AuthCallback'; const App: React.FC = () => { const [isAuthenticated, setIsAuthenticated] = useState(ApiService.isLoggedIn()); const [isTeacherAuthenticated, setIsTeacherAuthenticated] = useState(ApiService.isLoggedInTeacher()); + const [isRoomRequireAuthentication, setRoomsRequireAuth] = useState(null); const location = useLocation(); // Check login status every time the route changes @@ -37,7 +38,13 @@ const App: React.FC = () => { setIsTeacherAuthenticated(ApiService.isLoggedInTeacher()); }; + const fetchAuthenticatedRooms = async () => { + const data = await ApiService.getRoomsRequireAuth(); + setRoomsRequireAuth(data); + }; + checkLoginStatus(); + fetchAuthenticatedRooms(); }, [location]); const handleLogout = () => { @@ -76,7 +83,7 @@ const App: React.FC = () => { {/* Pages espace étudiant */} : } + element={( !isRoomRequireAuthentication || isAuthenticated ) ? : } /> {/* Pages authentification */} diff --git a/client/src/services/ApiService.tsx b/client/src/services/ApiService.tsx index d5c0b28..909f29b 100644 --- a/client/src/services/ApiService.tsx +++ b/client/src/services/ApiService.tsx @@ -105,6 +105,17 @@ class ApiService { } } + // Route to know if rooms need authentication to join + public async getRoomsRequireAuth(): Promise { + const url: string = this.constructRequestUrl(`/auth/getRoomsRequireAuth`); + const result: AxiosResponse = await axios.get(url); + + if (result.status == 200) { + return result.data.roomsRequireAuth; + } + return false; + } + public logout(): void { return localStorage.removeItem("jwt"); } From 80a56e9735ad81f7d60e6706aa9ee428a2aee5d2 Mon Sep 17 00:00:00 2001 From: Bruno Roesner Date: Sun, 20 Oct 2024 13:41:10 -0400 Subject: [PATCH 4/5] added unit tests for AUTHENTICATED_ROOM variable --- server/__tests__/auth.test.js | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/server/__tests__/auth.test.js b/server/__tests__/auth.test.js index 0099d03..f3f92d5 100644 --- a/server/__tests__/auth.test.js +++ b/server/__tests__/auth.test.js @@ -205,3 +205,40 @@ describe( }); }) ); + +describe( + "Rooms requiring authentication", () => { + // Making a copy of env variables to restore them later + const OLD_ENV_VARIABLES = process.env; + + let authConfigInstance; + + beforeAll(() => { + authConfigInstance = new AuthConfig(); + }); + + // Clearing cache just in case + beforeEach(() => { + jest.resetModules(); + process.env = { ...OLD_ENV_VARIABLES }; + }); + + // Resetting the old values + afterAll(() => { + process.env = OLD_ENV_VARIABLES; + }); + + // tests cases as [environment variable value, expected value] + const cases = [["true", true], ["false", false], ["", false], ["other_than_true_false", false]]; + test.each(cases)( + "Given %p as AUTHENTICATED_ROOMS environment variable value, returns %p", + (envVarArg, expectedResult) => { + process.env.AUTHENTICATED_ROOMS = envVarArg; + const isAuthRequired = authConfigInstance.getRoomsRequireAuth(); + + expect(isAuthRequired).toEqual(expectedResult); + } + ); + + } +) From 9f0ee05768c0e1af69d23cf2e5ee2eca1bc3392c Mon Sep 17 00:00:00 2001 From: Bruno Roesner Date: Tue, 22 Oct 2024 10:24:17 -0400 Subject: [PATCH 5/5] populate join-room username if authenticated (temp solution) --- .../AuthManager/callback/AuthCallback.tsx | 2 ++ .../src/pages/Student/JoinRoom/JoinRoom.tsx | 4 ++- client/src/services/ApiService.tsx | 25 +++++++++++++++++++ server/auth/auth-manager.js | 2 +- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/client/src/pages/AuthManager/callback/AuthCallback.tsx b/client/src/pages/AuthManager/callback/AuthCallback.tsx index 6ba290d..046abc7 100644 --- a/client/src/pages/AuthManager/callback/AuthCallback.tsx +++ b/client/src/pages/AuthManager/callback/AuthCallback.tsx @@ -9,9 +9,11 @@ const OAuthCallback: React.FC = () => { useEffect(() => { const searchParams = new URLSearchParams(location.search); const user = searchParams.get('user'); + const username = searchParams.get('username'); if (user) { apiService.saveToken(user); + apiService.saveUsername(username || ""); navigate('/'); } else { navigate('/login'); diff --git a/client/src/pages/Student/JoinRoom/JoinRoom.tsx b/client/src/pages/Student/JoinRoom/JoinRoom.tsx index e29bfb7..75516b0 100644 --- a/client/src/pages/Student/JoinRoom/JoinRoom.tsx +++ b/client/src/pages/Student/JoinRoom/JoinRoom.tsx @@ -15,9 +15,11 @@ import LoadingButton from '@mui/lab/LoadingButton'; import LoginContainer from '../../../components/LoginContainer/LoginContainer' +import ApiService from '../../../services/ApiService' + const JoinRoom: React.FC = () => { const [roomName, setRoomName] = useState(''); - const [username, setUsername] = useState(''); + const [username, setUsername] = useState(ApiService.getUsername()); const [socket, setSocket] = useState(null); const [isWaitingForTeacher, setIsWaitingForTeacher] = useState(false); const [question, setQuestion] = useState(); diff --git a/client/src/services/ApiService.tsx b/client/src/services/ApiService.tsx index 909f29b..b63bbdd 100644 --- a/client/src/services/ApiService.tsx +++ b/client/src/services/ApiService.tsx @@ -105,6 +105,30 @@ class ApiService { } } + public saveUsername(username: string): void { + if (!username || username.length === 0) { + return; + } + + const object = { + username: username + } + + localStorage.setItem("username", JSON.stringify(object)); + } + + public getUsername(): string { + const objectStr = localStorage.getItem("username"); + + if (!objectStr) { + return ""; + } + + const object = JSON.parse(objectStr) + + return object.username; + } + // Route to know if rooms need authentication to join public async getRoomsRequireAuth(): Promise { const url: string = this.constructRequestUrl(`/auth/getRoomsRequireAuth`); @@ -117,6 +141,7 @@ class ApiService { } public logout(): void { + localStorage.removeItem("username"); return localStorage.removeItem("jwt"); } diff --git a/server/auth/auth-manager.js b/server/auth/auth-manager.js index fce031e..27082f9 100644 --- a/server/auth/auth-manager.js +++ b/server/auth/auth-manager.js @@ -44,7 +44,7 @@ class AuthManager{ async login(userInfo,req,res,next){ const tokenToSave = jwt.create(userInfo.email, userInfo._id,userInfo.roles); - res.redirect(`/auth/callback?user=${tokenToSave}`); + res.redirect(`/auth/callback?user=${tokenToSave}&username=${userInfo.name}`); console.info(`L'utilisateur '${userInfo.name}' vient de se connecter`) }