add auth-service not verified with Dockerfile

This commit is contained in:
vankhaiphan 2021-05-28 01:01:00 +02:00
parent 3a7389ba68
commit 8cf6520224
12 changed files with 304 additions and 0 deletions

View 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;

View 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;

View 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;

View 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-----

View 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-----

View 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

View 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 };

View 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;
}
};

View 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;

View 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"
}
}

View 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}`);
});
});

View 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;