add auth-service not verified with Dockerfile
This commit is contained in:
parent
3a7389ba68
commit
8cf6520224
12 changed files with 304 additions and 0 deletions
44
backend/service-authentication/auth.js
Normal file
44
backend/service-authentication/auth.js
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
const sessionJwt = require ('./sessionJWT');
|
||||
const queries = require('./mongodbQueries');
|
||||
|
||||
// ici, on récupère le contenu du cookie de session JWT.
|
||||
// celui-ci contient le userId mais également des informations
|
||||
// concernant sa date d'expiration.
|
||||
function getSession (req) {
|
||||
return sessionJwt.decodeSessionCookie(req);
|
||||
}
|
||||
module.exports.getSession = getSession;
|
||||
|
||||
// cette fonction ajoute le cookie de session au headers du
|
||||
// message qui sera renvoyé à Angular. Si le cookie actuel
|
||||
// est "vieux", on en recrée ici un nouveau.
|
||||
function setSessionCookie (req, res, session) {
|
||||
sessionJwt.createSessionCookie(req, res, session);
|
||||
}
|
||||
module.exports.setSessionCookie = setSessionCookie;
|
||||
|
||||
// fonction pour récupérer le userId provenant du cookie
|
||||
// de session. Si ce dernier n'existe pas, on renvoie
|
||||
// l'ID -1.
|
||||
function getUserId(session) {
|
||||
if (typeof session.userId === 'undefined') return -1;
|
||||
return session.userId;
|
||||
}
|
||||
module.exports.getUserId = getUserId;
|
||||
|
||||
async function authenticate(req, res) {
|
||||
const login = req.body.login;
|
||||
const password = req.body.password;
|
||||
|
||||
const userList = await queries.checkLoginQuery(login, password);
|
||||
if (userList !== undefined && userList[0] !== undefined && userList[0].idUtilisateur > 0){
|
||||
setSessionCookie (req, res, { userId: userList[0].idUtilisateur });
|
||||
// return userList[0].idUtilisateur;
|
||||
return getUserId(getSession(req));
|
||||
} else {
|
||||
setSessionCookie (req, res, {userId: -1});
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
module.exports.authenticate = authenticate;
|
||||
18
backend/service-authentication/checkLogin.js
Normal file
18
backend/service-authentication/checkLogin.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
const {sendError, sendMessage} = require ("./message");
|
||||
const auth = require ('./auth');
|
||||
|
||||
async function checkLogin (req,res) {
|
||||
if (typeof req.body.login === 'undefined')
|
||||
return sendError(res, 'Vous n\'avez pas envoyé le champ login');
|
||||
if (typeof req.body.password === 'undefined')
|
||||
return sendError(res, 'Vous n\'avez pas envoyé le champ password');
|
||||
|
||||
const result = await auth.authenticate(req, res);
|
||||
if (result){
|
||||
return sendMessage(res, result);
|
||||
}
|
||||
else{
|
||||
return sendError(res, 'Invalid username or password');
|
||||
}
|
||||
}
|
||||
module.exports = checkLogin;
|
||||
15
backend/service-authentication/config.js
Normal file
15
backend/service-authentication/config.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
const config = {
|
||||
// paramètres de connexion à la base de données
|
||||
mongodbDatabase: 'chat',
|
||||
mongodbHost: 'mongodb://localhost:27017/',
|
||||
charset: 'utf8',
|
||||
mongodbLogin: '',
|
||||
mongodbPassword: '',
|
||||
|
||||
// les noms des tables
|
||||
mongodbUtilisateurs: 'users'
|
||||
};
|
||||
module.exports = config;
|
||||
|
||||
|
||||
|
||||
27
backend/service-authentication/keys/jwtRS256.key
Normal file
27
backend/service-authentication/keys/jwtRS256.key
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAvtgwBVQ26VNO1XD+PTZDdZJdWXufontRZIO/ev7OkvH8qM6g
|
||||
mZDJOZQRrbaMI2w3jGr/x1uDhIaafRtyRsQ9Jdjb2GVjQc9deiNMfeEvA1YJZjiC
|
||||
LDy4igtmitPup3WrG+xb9asNAuQUtn1bXKM/3ecVxIKq6j/wh1578ra9WGpcTZjx
|
||||
+1u+3LjviWehb9Gwu8FOIPBu9bcIf48JZLr3Zq/0Fv0Atw7gTJBDAb2B9Zsjxc59
|
||||
oKKyWguRQG6COUaxZ/Lsyczv0FIFFsfAKzuihqfI+EsVGJ1nsFBH3gAdeUW2RX7/
|
||||
z+7cmR305sf3cdN7kcK8ZwgrG7/lnszSUf79uQIDAQABAoIBAAKKDdmETVa9bQca
|
||||
Acf+uNcPo35VTsJysZqMxjd0vHroDVyRo0Fn08WYWsPc8fBmuDZ+FfkpFo7k25le
|
||||
jB607btbL1Gpx7BQegXuAk6KeH2q32Uky1abWDk9/ZdLSpmfzy8H7hFOvVWUg1IK
|
||||
SPTqlyb0tC1xL6T+RM0ITM3l8I8ElWHKzhs5H9jLlhOng0sW9RbLjWtBRXPp48tB
|
||||
YFhx/wuSNpTOVGZAKpWVMaCgOizeL0yT6t+z/QL7Pvq3IhlcFMLz5K6f6/mZ+ODV
|
||||
W/TpbwC7ll204vmgHsYY6tdpDAKqZK0ayPxm018QCCtCsYawDyk2HjYYnytXSsNu
|
||||
UNPt+KECgYEA6WkKd5Nh8K0m9LVL3Gpbep9MKTqGgBVo8z4UV6iSDQdCBUSU8cFi
|
||||
2ntsyAh0PCvQHxvn/DwqCcKafbFQMX+S1jpkZsoqA0OUjYRxQYOEn1iIGJdspzYl
|
||||
cv2637p3Aza6x75eFLOZvFa3C1rCFQxJHvAYolN/FnhBx9D3QnaDydsCgYEA0VCJ
|
||||
z4kVFm35poBEAVJOO3fdmFUvAn3bFhgI5zfzC/e4dPs9beiWo9XmpeOapu9D7F3M
|
||||
1OFITUw1yQBoDtG5Gt/cIp39wdPNLfDM3kgv/djQGa/EZO1NkDrk/AGDZqyzDTUV
|
||||
vGB/d8dGQdP9buiZFcy9D3HSsNVD9RP547+mfPsCgYEAywfa2f6yr/b+LthQ368I
|
||||
WdadGjPVcS6udv+mFEYGnRyWGhz47n4IbgH0st9ftENsKtNMbQUskAbd+b22Awh0
|
||||
grKSSTNLbkFnw93T4mfzgeQxpip5kc2wr6Dz387D3WDLAhqenaVIciJ/4HmW31Yr
|
||||
eKTi2LiGkNYUaipkGkUbCAcCgYEAmHvCmWT07s0ZJLmmUQwjn+D3lqTfxUHoW9UQ
|
||||
j1jL/3jscJQisTHSo/IMv+bqYBhH9CZ1NNQVdvJA8HgSVlFkNvbECJfuJ8jjXUdi
|
||||
B8Cw7Y2INF4+hYP2kE7HR+rWTfMb0VBN0FjAI4MRZJ1JsAVUmHP5ewnhgh8rDZwK
|
||||
3GZepAcCgYEA1LwjdqCg3LJzXVSJ6gWwNNB9gRX2bb2l7iMHxaTEyRFvJFW7cuL9
|
||||
Y7iCKw+9EpGqSZesIHk1V+TCj77nXKpsyO+/tmiyyeqa1DT+AvvG+IgB0aJto7kU
|
||||
f2oxn02dX9hN51tRhHZ6PDV/43GnJ3ltaXLBhCxq/MQZFXztYkUd6Z0=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
9
backend/service-authentication/keys/jwtRS256.key.pub
Normal file
9
backend/service-authentication/keys/jwtRS256.key.pub
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvtgwBVQ26VNO1XD+PTZD
|
||||
dZJdWXufontRZIO/ev7OkvH8qM6gmZDJOZQRrbaMI2w3jGr/x1uDhIaafRtyRsQ9
|
||||
Jdjb2GVjQc9deiNMfeEvA1YJZjiCLDy4igtmitPup3WrG+xb9asNAuQUtn1bXKM/
|
||||
3ecVxIKq6j/wh1578ra9WGpcTZjx+1u+3LjviWehb9Gwu8FOIPBu9bcIf48JZLr3
|
||||
Zq/0Fv0Atw7gTJBDAb2B9Zsjxc59oKKyWguRQG6COUaxZ/Lsyczv0FIFFsfAKzui
|
||||
hqfI+EsVGJ1nsFBH3gAdeUW2RX7/z+7cmR305sf3cdN7kcK8ZwgrG7/lnszSUf79
|
||||
uQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
5
backend/service-authentication/keys/jwtRS256.sh
Normal file
5
backend/service-authentication/keys/jwtRS256.sh
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key
|
||||
# Don't add passphrase
|
||||
openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub
|
||||
cat jwtRS256.key
|
||||
cat jwtRS256.key.pub
|
||||
13
backend/service-authentication/message.js
Normal file
13
backend/service-authentication/message.js
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// renvoie un message au format JSON. On a besoin de passer en paramètre
|
||||
// res, la réponse que l'on envoie au client (Angular). Le paramètre
|
||||
// data est un objet JavaScript. Globalement, cette fonction est
|
||||
// équivalente au "echo json_encode(data);" que vous utilisiez en PHP
|
||||
function sendMessage (res, data) {
|
||||
res.json ({ status: 'ok', data: data });
|
||||
}
|
||||
|
||||
function sendError (res, reason) {
|
||||
res.json ({ status: 'error', data: {reason: reason }});
|
||||
}
|
||||
|
||||
module.exports = { sendMessage, sendError };
|
||||
18
backend/service-authentication/mongodbConnect.js
Normal file
18
backend/service-authentication/mongodbConnect.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
const config = require('./config');
|
||||
const MongoClient = require( 'mongodb' ).MongoClient;
|
||||
const uri = config.mongodbHost;
|
||||
let db;
|
||||
|
||||
module.exports = {
|
||||
connectToServer: function( callback ) {
|
||||
MongoClient.connect( uri, { useNewUrlParser: true, useUnifiedTopology: true }, function( err, client ) {
|
||||
db = client.db(config.mongodbDatabase);
|
||||
return callback( err );
|
||||
});
|
||||
},
|
||||
|
||||
getDB: function() {
|
||||
return db;
|
||||
}
|
||||
};
|
||||
|
||||
16
backend/service-authentication/mongodbQueries.js
Normal file
16
backend/service-authentication/mongodbQueries.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
const config = require('./config');
|
||||
const mongoDB = require ('./mongodbConnect').getDB();
|
||||
|
||||
function checkLoginQuery(login, password){
|
||||
// SELECT idUtilisateurs
|
||||
// FROM utilisateurs
|
||||
// WHERE login = ? AND password = ?;
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(mongoDB.collection(config.mongodbUtilisateurs).find(
|
||||
{login: login, password: password},
|
||||
{projection: {idUtilisateur: 1, _id: 0}}).toArray());
|
||||
});
|
||||
}
|
||||
module.exports.checkLoginQuery = checkLoginQuery;
|
||||
|
||||
|
||||
19
backend/service-authentication/package.json
Normal file
19
backend/service-authentication/package.json
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "service-authentication",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Van Khai PHAN",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.17.1",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"mongodb": "^3.6.9"
|
||||
}
|
||||
}
|
||||
32
backend/service-authentication/server.js
Normal file
32
backend/service-authentication/server.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
const express = require('express');
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
const cookieParser = require('cookie-parser');
|
||||
app.use(cookieParser());
|
||||
|
||||
const bodyParser = require('body-parser');
|
||||
app.use(bodyParser.urlencoded({extended:true}));
|
||||
app.use(bodyParser.json());
|
||||
|
||||
const cors = require('cors');
|
||||
app.use(cors({origin: 'http://127.0.0.1:4200', credentials: true}));
|
||||
|
||||
const mongoConnect = require('./mongodbConnect');
|
||||
|
||||
mongoConnect.connectToServer(function( err, client ) {
|
||||
if (err)
|
||||
console.log(err);
|
||||
|
||||
const checkLogin = require('./checkLogin');
|
||||
|
||||
app.post('/checkLogin', (req, res) => {
|
||||
checkLogin(req,res);
|
||||
});
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log (`listening on port ${port}`);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
88
backend/service-authentication/sessionJWT.js
Normal file
88
backend/service-authentication/sessionJWT.js
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
const sessionJWT = require ('jsonwebtoken');
|
||||
const fs = require ('fs');
|
||||
|
||||
// renvoie un nouveau token JWT
|
||||
function createSessionJWT (userId) {
|
||||
// ci-dessous, on met en place le cookie de session JWT :
|
||||
// 1/ on recupere notre clef privee
|
||||
const RSA_PRIVATE_KEY = fs.readFileSync('./keys/jwtRS256.key');
|
||||
|
||||
// 2/ on signe un token JWT. Le payload est l'identifiant de
|
||||
// l'utilisateur ainsi qu'une date d'expiration à mi-parcours :
|
||||
// on récupérra ultérieurement ces informations, qui permettront
|
||||
// de savoir si le token est valide ou non et de connaître l'ID
|
||||
// de l'utilisateur. Dans le token, le champ exp indique la date
|
||||
// de validité du token (pas besoin de se relogguer tant que la
|
||||
// date actuelle est inférieure à exp) et le champ midExp indique
|
||||
// à partir de quel moment on doit recréer un nouveau cookie de
|
||||
// session.
|
||||
const jwtToken = sessionJWT.sign(
|
||||
{
|
||||
userId: userId,
|
||||
midExp: Math.floor(Date.now() / 1000) + 1800 // validité: 30mn
|
||||
},
|
||||
RSA_PRIVATE_KEY,
|
||||
{
|
||||
algorithm: 'RS256',
|
||||
expiresIn: '1h' // champ exp: validité 1h
|
||||
});
|
||||
|
||||
return jwtToken;
|
||||
}
|
||||
|
||||
|
||||
// crée un cookie de session JWT (Si le JWT de la requête est encore valide,
|
||||
// on l'utilise, sinon on en recrée un nouveau)
|
||||
function createSessionCookie(req, res, payload) {
|
||||
// on regarde si le payload contient les champs userId et midExp. Si c'est le
|
||||
// cas, c'est qu'on a reçu dans la request un cookie. On va donc vérifier si
|
||||
// ce cookie est encore valide ou non : si la date actuelle est inférieure à
|
||||
// midExp, alors le cookie est encore valide et on peut le renvoyer. Sinon,
|
||||
// on doit recalculer un nouveau cookie.
|
||||
let jwtToken = '';
|
||||
if ((typeof payload.userId !== 'undefined') &&
|
||||
(typeof payload.midExp !== 'undefined') &&
|
||||
(Math.floor(Date.now() / 1000) <= payload.midExp)) {
|
||||
jwtToken = req.cookies.SESSIONID;
|
||||
}
|
||||
else {
|
||||
// on crée un nouveau cookie
|
||||
jwtToken = createSessionJWT(payload.userId);
|
||||
}
|
||||
|
||||
// on renvoie le cookie au client
|
||||
// on met le secure à false afin de pouvoir utiliser http plutôt que https
|
||||
res.cookie('SESSIONID', jwtToken, {httpOnly:true, secure:false});
|
||||
}
|
||||
module.exports.createSessionCookie = createSessionCookie;
|
||||
|
||||
|
||||
// décode un cookie de session et renvoie les informations contenues dans ce
|
||||
// cookie, notamment le userId. Si le cookie n'existe pas, la fonction renvoie
|
||||
// juste un objet avec un userId égal à -1.
|
||||
function decodeSessionCookie(req) {
|
||||
// si l'on n'a pas de cookie de session, on renvoie une session avec vide,
|
||||
// avec juste un userId à -1
|
||||
console.log(req.cookies);
|
||||
if (typeof req.cookies.SESSIONID === 'undefined') {
|
||||
return { userId: -1 };
|
||||
}
|
||||
const sessionid = req.cookies.SESSIONID;
|
||||
|
||||
// on lit la clef publique
|
||||
const RSA_PUBLIC_KEY = fs.readFileSync('./keys/jwtRS256.key.pub');
|
||||
|
||||
// on récupère les données du cookie
|
||||
try {
|
||||
const token = sessionJWT.verify(
|
||||
sessionid,
|
||||
RSA_PUBLIC_KEY,
|
||||
{algorithms: ['RS256']});
|
||||
return token;
|
||||
}
|
||||
catch (err) {
|
||||
return {userId: -1};
|
||||
}
|
||||
}
|
||||
module.exports.decodeSessionCookie = decodeSessionCookie;
|
||||
|
||||
Reference in a new issue