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