From 79de47f12216753b0a2d36e519997ee7046f1b5d Mon Sep 17 00:00:00 2001
From: "narindra.rajohnso" <narindra-hasimanjaka-david.rajohnson@etu.hesge.ch>
Date: Thu, 8 Jun 2023 10:29:32 +0200
Subject: [PATCH] add token sign and verify

---
 API/.env                                      |   2 ++
 API/src/database/database.sqlite              | Bin 20480 -> 20480 bytes
 API/src/routes/BaseRoutes.ts                  |   2 +-
 API/src/routes/middleware.ts                  |  31 ++++++++++++++++--
 API/src/routes/router-admin.ts                |  28 +++++++---------
 API/src/routes/router-gamer.ts                |   6 ++--
 API/src/routes/router-guest.ts                |   9 ++++-
 .../quizz-game/src/app/login/session-model.ts |   0
 8 files changed, 55 insertions(+), 23 deletions(-)
 create mode 100644 Frontend/quizz-game/src/app/login/session-model.ts

diff --git a/API/.env b/API/.env
index 48e75ec..c2da4ed 100644
--- a/API/.env
+++ b/API/.env
@@ -1,3 +1,5 @@
 ########################### Server env vars
 API_PORT=30992
+########################### (openssl rand -hex 32)
+SECRET_KEY="d8e730bd53c2cb0b9271bded343dd19ceef04e58e6a10eafe29c8f4a9a99f488"
 
diff --git a/API/src/database/database.sqlite b/API/src/database/database.sqlite
index e7da284434d84742aed929297a91ca2b3b886e74..ed7be32ccd95fadcfdba4d8983a6d5731c58f8a2 100644
GIT binary patch
delta 412
zcmZozz}T>Wae_2s-b5K^#=MOQOZcVOd88TmmH68E`*`2-hVX3Xk>>8_`ofjQd0}JY
zR?f|rC3i5^Gfa|BWnf_F5l$5ql^6B&EKW)D()M?9H7ZZ{4GpOZwRH7xbV}AX^Uc*x
z4oUS1bxKRpH!>}8v^4Q7PxrJ<EKW%S;o`)UGzSn-TAW&BWME{hYhb2pV6I?jVr6P<
zWon^kW?`bBZD3$!V1Od4jv?JB$-$|ZDk-Th?&(=vl3JFPSXi1`GC5OLCpfqywJbHy
z3oHN;cF0IA)=SPvOv%m6gPUszw$;SS*i_Hl$Q0dHh^(cRk(r*ciP`22G9k=T?EJGC
z_%HLn<KMx5hkrKzD*j{q$N1-i;ATOGVE)O4`f^hIKNxt*@-uT14NW-tm=zh3+_q9b
in58%+jdPQM13#a+f}xp}shO3Lg`TB}(PlsUO#%R2n00ah

delta 364
zcmZozz}T>Wae_2s`a~IL#`KK|OZcVOc(ya}EAh4S_wl~v4dL0&qs%>t>kC&J=Y@@p
zTRAshmfXQuKU*?YSz4Kafq`M7c&enRqNt~5aY~wnsaI8~ep#t!Wm=)BnQ3{LcD`?M
zNK&S6V!5_KxuLOvlSgWSQJ7_9g{hmXZE;FkN^x3oN?LJoN}5A)N}66?YH4w5k&%Is
zv95usu92yNp{bRDrInG1o}q=Yg0_Kym4N|RRvTH`*j&%h)D$Ysz`!s?GF4JsS=7_B
zEI%_R(P(m&l#W1ZUUGg>YGP?gQEG8wN?P$`K3Pc)3oBDIJtG72$@;QlaL(opG9k=T
zZ2YSj_%HLn<KMx5hkq6SG5+~5xLMF4n16DizMNEAxrHegKmQK~F0j`*`F}8QL#<q?
YAIy@Hm{zjMz=40VlD+8WQ2W&a0M$Bb6aWAK

diff --git a/API/src/routes/BaseRoutes.ts b/API/src/routes/BaseRoutes.ts
index aeb0f7a..7c76bdf 100644
--- a/API/src/routes/BaseRoutes.ts
+++ b/API/src/routes/BaseRoutes.ts
@@ -4,7 +4,7 @@ import { StatusCodes } from 'http-status-codes';
 
 const router: express.Router = express.Router();
 
-router.get('/', (req: express.Request, res: express.Response) => res.status(StatusCodes.OK).json({message: "Base route"}));
+router.get('/token/login', (req: express.Request, res: express.Response) => res.status(StatusCodes.OK).json({message: "Base route"}));
 
 
 
diff --git a/API/src/routes/middleware.ts b/API/src/routes/middleware.ts
index 0c49da6..3c3164c 100644
--- a/API/src/routes/middleware.ts
+++ b/API/src/routes/middleware.ts
@@ -1,8 +1,10 @@
-import express         from 'express';
-import { StatusCodes } from 'http-status-codes';
+import express from 'express';
+import {StatusCodes} from 'http-status-codes';
 import {userType} from '../database/models/User'
 import {Database} from "../database/Database";
 
+const jwt = require('jsonwebtoken');
+
 export function checkUserFields(req: express.Request, res: express.Response, next: express.NextFunction)  {
     if (!req.body.username && !req.body.password && !req.body.accountType) {
         return res.status(400).json({ error: '"username", "password" and "accountType" required' });
@@ -41,6 +43,31 @@ export async function checkExistingUser(req: express.Request, res: express.Respo
 
 }
 
+export interface TokenRequest extends express.Request {
+    user?: any;
+}
+
+export async function verifyToken(req: TokenRequest, res: express.Response, next: express.NextFunction) {
+    const authHeader = req.headers['authorization'];
+
+    if (!authHeader) {
+        return res.status(401).json({message: 'Token not provided', header: req.headers});
+    }
+    const token = authHeader.split(" ")[1];
+
+    const secretKey = process.env.SECRET_KEY;
+
+    try {
+        req.user = jwt.verify(token, secretKey);
+        if(req.user.username !== req.params.admin)
+            return res.status(403).json({message: 'Invalid token user'});
+        //check if admin or user
+        next();
+    } catch (error) {
+        return res.status(403).json({message: 'Invalid token'});
+    }
+}
+
 
 
 export function checkQuestionFields(req: express.Request, res: express.Response, next: express.NextFunction)  {
diff --git a/API/src/routes/router-admin.ts b/API/src/routes/router-admin.ts
index 3a7672a..a8a1842 100644
--- a/API/src/routes/router-admin.ts
+++ b/API/src/routes/router-admin.ts
@@ -9,22 +9,18 @@ import {
     checkQuestionFields,
     checkUserFields,
     checkUsernameField,
-    createAccountCheck
+    createAccountCheck, verifyToken
 } from './middleware'
 import {Database} from "../database/Database";
 
 
 const router: express.Router = express.Router();
 
-router.get('/', (req: express.Request, res: express.Response) => {
-    res.status(StatusCodes.OK).json({ message: 'Admins route' })
-});
 
-router.get('/:admin', checkExistingUser, (req: express.Request, res: express.Response) => {
-    res.status(StatusCodes.OK).json({ message: 'Admin id route' })
-});
 
-router.get('/:admin/list-users', checkExistingUser,async (req: express.Request, res: express.Response) => {
+
+
+router.get('/:admin/list-users', checkExistingUser, verifyToken, async (req: express.Request, res: express.Response) => {
     try {
         const users = await Database.getAllUsers();
         res.status(StatusCodes.OK).json({users});
@@ -33,7 +29,7 @@ router.get('/:admin/list-users', checkExistingUser,async (req: express.Request,
     }
 });
 
-router.get('/:admin/list-questions',  checkExistingUser, async (req: express.Request, res: express.Response) => {
+router.get('/:admin/list-questions',  checkExistingUser, verifyToken, async (req: express.Request, res: express.Response) => {
     try {
         const questions = await Database.getAllQuestions();
         questions.forEach(q => {
@@ -48,11 +44,11 @@ router.get('/:admin/list-questions',  checkExistingUser, async (req: express.Req
     }
 });
 
-router.post('/:admin/create-user-account', checkExistingUser, checkUserFields,  (req: express.Request, res: express.Response) => {
+router.post('/:admin/create-user-account', checkExistingUser, checkUserFields, verifyToken, (req: express.Request, res: express.Response) => {
     createAccountCheck(req, res);
 });
 
-router.post('/:admin/create-question', checkExistingUser, checkQuestionFields,async (req: express.Request, res: express.Response) => {
+router.post('/:admin/create-question', checkExistingUser, checkQuestionFields, verifyToken, async (req: express.Request, res: express.Response) => {
     const data = req.body;
     const correctResponse: string = data.possibleResponse[data.correctResponse];
     if (correctResponse !== undefined) {
@@ -78,7 +74,7 @@ router.post('/:admin/create-question', checkExistingUser, checkQuestionFields,as
     }
 });
 
-router.put('/:admin/update-user-account', checkExistingUser, checkUsernameField, async (req: express.Request, res: express.Response) => {
+router.put('/:admin/update-user-account', checkExistingUser, checkUsernameField, verifyToken, async (req: express.Request, res: express.Response) => {
     const data=req.body;
     const username = data.username;
     try{
@@ -109,7 +105,7 @@ router.put('/:admin/update-user-account', checkExistingUser, checkUsernameField,
 
 });
 
-router.put('/:admin/update-question', checkExistingUser,checkIdField,async (req: express.Request, res: express.Response) => {
+router.put('/:admin/update-question', checkExistingUser,checkIdField, verifyToken, async (req: express.Request, res: express.Response) => {
     const data=req.body;
     const id = data.id;
     try{
@@ -135,7 +131,7 @@ router.put('/:admin/update-question', checkExistingUser,checkIdField,async (req:
 
 
 
-router.delete('/:admin/delete-user-account', checkExistingUser, checkUsernameField, async (req: express.Request, res: express.Response) => {
+router.delete('/:admin/delete-user-account', checkExistingUser, checkUsernameField, verifyToken, async (req: express.Request, res: express.Response) => {
     let data=req.body
     if(req.params.admin !== data.username) {
         try{
@@ -157,7 +153,7 @@ router.delete('/:admin/delete-user-account', checkExistingUser, checkUsernameFie
 
 });
 
-router.delete('/:admin/delete-question', checkExistingUser, checkIdField, async (req: express.Request, res: express.Response) => {
+router.delete('/:admin/delete-question', checkExistingUser, checkIdField, verifyToken, async (req: express.Request, res: express.Response) => {
     let data = req.body
     try {
         let questionDelete = await Database.deleteQuestion(data.id);
@@ -176,7 +172,7 @@ router.delete('/:admin/delete-question', checkExistingUser, checkIdField, async
 
 });
 
-router.post('/:admin/get-user', checkExistingUser, async (req: express.Request, res: express.Response) => {
+router.post('/:admin/get-user', checkExistingUser, verifyToken, async (req: express.Request, res: express.Response) => {
     const data = req.body
     let user=await Database.infoUser(data.username);
     user.dataValues.password="CONFIDENTIAL!!!"
diff --git a/API/src/routes/router-gamer.ts b/API/src/routes/router-gamer.ts
index cf91582..4159296 100644
--- a/API/src/routes/router-gamer.ts
+++ b/API/src/routes/router-gamer.ts
@@ -1,6 +1,6 @@
 import express         from 'express';
 import { StatusCodes } from 'http-status-codes';
-import {checkExistingUser} from "./middleware";
+import {checkExistingUser, TokenRequest, verifyToken} from "./middleware";
 
 
 const router: express.Router = express.Router();
@@ -9,8 +9,8 @@ router.get('/', (req: express.Request, res: express.Response) => {
     res.status(StatusCodes.OK).json({ message: 'Gamers route' })
 });
 
-router.get('/:username', checkExistingUser, (req: express.Request, res: express.Response) => {
-
+router.get('/:username', checkExistingUser, verifyToken, (req: TokenRequest, res: express.Response) => {
+    res.status(StatusCodes.OK).json({access_user: req.user});
 });
 
 
diff --git a/API/src/routes/router-guest.ts b/API/src/routes/router-guest.ts
index 79500bc..ad6875e 100644
--- a/API/src/routes/router-guest.ts
+++ b/API/src/routes/router-guest.ts
@@ -2,6 +2,9 @@ import express         from 'express';
 import { StatusCodes } from 'http-status-codes';
 import {checkExistingUser, checkUserFields, createAccountCheck} from './middleware'
 import {Database} from "../database/Database";
+import * as process from "process";
+import {userType} from "../database/models/User";
+const jwt = require('jsonwebtoken');
 
 
 
@@ -25,7 +28,11 @@ router.post('/:username', checkExistingUser, async (req: express.Request, res: e
     if(user){
         let usertype=user.dataValues.type === "user"?"USER":"ADMIN"
         if (user.dataValues.password === data.password) {
-            res.status(StatusCodes.OK).json({message: usertype+"_ALLOWED"})
+            // Génération du token JWT
+            const userInfo={ type: userType, username: req.params.username, firstname: user.dataValues.firstname, lastname: user.dataValues.lastname }
+            const secretKey=process.env.SECRET_KEY;
+            const token = jwt.sign(userInfo, secretKey);
+            res.status(StatusCodes.OK).json({message: usertype+"_ALLOWED", token: token, firstname: user.dataValues.firstname, lastname: user.dataValues.lastname});
         }else{
             res.status(StatusCodes.BAD_REQUEST).json({message: "USER_PASSWORD_FALSE"})
         }
diff --git a/Frontend/quizz-game/src/app/login/session-model.ts b/Frontend/quizz-game/src/app/login/session-model.ts
new file mode 100644
index 0000000..e69de29
-- 
GitLab