Merge remote-tracking branch 'origin/dev-configuration-auth' into adds-configuration-to-oauth-integration

This commit is contained in:
Gabriel Matte 2024-09-28 12:18:10 -04:00
commit ec9adc1440
7 changed files with 380 additions and 0 deletions

55
auth_config.json Normal file
View file

@ -0,0 +1,55 @@
{
"auth": {
"passportjs": [
{
"provider1": {
"type": "oauth",
"OAUTH_AUTHORIZATION_URL": "https://www.testurl.com/oauth2/authorize",
"OAUTH_TOKEN_URL": "https://www.testurl.com/oauth2/token",
"OAUTH_CLIENT_ID": "your_oauth_client_id",
"OAUTH_CLIENT_SECRET": "your_oauth_client_secret",
"OAUTH_CALLBACK_URL": "https://localhost:3000/auth/provider/callback",
"OAUTH_ADD_SCOPE": "scopes",
"OAUTH_ROLE_TEACHER_VALUE": "teacher-claim-value",
"OAUTH_ROLE_STUDENT_VALUE": "student-claim-value"
}
},
{
"provider2": {
"type": "oidc",
"OIDC_CLIENT_ID": "your_oidc_client_id",
"OIDC_CLIENT_SECRET": "your_oidc_client_secret",
"OIDC_ISSUER_URL": "https://your-issuer.com",
"OIDC_CALLBACK_URL": "http://localhost:3000/auth/oidc/callback"
}
},
{
"provider3": {
"type": "oauth",
"OAUTH_AUTHORIZATION_URL": "https://www.testurl.com/oauth2/authorize",
"OAUTH_TOKEN_URL": "https://www.testurl.com/oauth2/token",
"OAUTH_CLIENT_ID": "your_oauth_client_id",
"OAUTH_CLIENT_SECRET": "your_oauth_client_secret",
"OAUTH_CALLBACK_URL": "https://localhost:3000/auth/provider/callback",
"OAUTH_ADD_SCOPE": "scopes",
"OAUTH_ROLE_TEACHER_VALUE": "teacher-claim-value",
"OAUTH_ROLE_STUDENT_VALUE": "student-claim-value"
}
},
{
"provider4": {
"type": "oidc",
"OIDC_CLIENT_ID": "your_oidc_client_id",
"OIDC_CLIENT_SECRET": "your_oidc_client_secret",
"OIDC_ISSUER_URL": "https://your-issuer.com",
"OIDC_CALLBACK_URL": "http://localhost:3000/auth/oidc/callback"
}
}
],
"simple-login": {
"enabled": true,
"name": "provider3",
"SESSION_SECRET": "your_session_secret"
}
}
}

View file

@ -23,6 +23,8 @@ services:
EMAIL_PSW: 'vvml wmfr dkzb vjzb'
JWT_SECRET: haQdgd2jp09qb897GeBZyJetC8ECSpbFJe
FRONTEND_URL: "http://localhost:5173"
volumes:
- ./auth_config.json:/usr/src/app/serveur/config/auth_config.json
depends_on:
- mongo
restart: always

View file

@ -0,0 +1,103 @@
const request = require('supertest');
const AuthConfig = require('../config/auth.js');
const mockConfig = {
"auth": {
"passportjs": [
{
"provider1": {
"type": "oauth",
"OAUTH_AUTHORIZATION_URL": "https://www.testurl.com/oauth2/authorize",
"OAUTH_TOKEN_URL": "https://www.testurl.com/oauth2/token",
"OAUTH_CLIENT_ID": "your_oauth_client_id",
"OAUTH_CLIENT_SECRET": "your_oauth_client_secret",
"OAUTH_CALLBACK_URL": "https://localhost:3000/auth/provider/callback",
"OAUTH_ADD_SCOPE": "scopes",
"OAUTH_ROLE_TEACHER_VALUE": "teacher-claim-value",
"OAUTH_ROLE_STUDENT_VALUE": "student-claim-value"
}
},
{
"provider2": {
"type": "oidc",
"OIDC_CLIENT_ID": "your_oidc_client_id",
"OIDC_CLIENT_SECRET": "your_oidc_client_secret",
"OIDC_ISSUER_URL": "https://your-issuer.com",
"OIDC_CALLBACK_URL": "http://localhost:3000/auth/oidc/callback"
}
}
],
"simple-login": {
"enabled": true,
"name": "provider3",
"SESSION_SECRET": "your_session_secret"
}
}
};
// Créez une instance de AuthConfig en utilisant la configuration mockée
describe('AuthConfig Class Tests', () => {
let authConfigInstance;
// Initialisez l'instance avec la configuration mockée
beforeAll(() => {
authConfigInstance = new AuthConfig();
authConfigInstance.loadConfigTest(mockConfig); // On injecte la configuration mockée
});
it('devrait retourner la configuration PassportJS', () => {
const config = authConfigInstance.getPassportJSConfig();
expect(config).toHaveProperty('provider1');
expect(config).toHaveProperty('provider2');
});
it('devrait retourner la configuration Simple Login', () => {
const config = authConfigInstance.getSimpleLoginConfig();
expect(config).toHaveProperty('name', 'provider3');
expect(config).toHaveProperty('SESSION_SECRET', 'your_session_secret');
});
it('devrait retourner les providers OAuth', () => {
const oauthProviders = authConfigInstance.getOAuthProviders();
expect(Array.isArray(oauthProviders)).toBe(true);
expect(oauthProviders.length).toBe(1); // Il y a un seul provider OAuth
expect(oauthProviders[0]).toHaveProperty('provider1');
});
it('devrait valider la configuration des providers', () => {
expect(() => authConfigInstance.validateProvidersConfig()).not.toThrow();
});
it('devrait lever une erreur si une configuration manque', () => {
const invalidMockConfig = {
"auth": {
"passportjs": [
{
"provider1": {
"type": "oauth",
"OAUTH_CLIENT_ID": "your_oauth_client_id" // Il manque des champs nécessaires
}
}
]
}
};
const instanceWithInvalidConfig = new AuthConfig();
instanceWithInvalidConfig.loadConfigTest(invalidMockConfig);
// Vérifiez que l'erreur est lancée avec les champs manquants corrects
expect(() => instanceWithInvalidConfig.validateProvidersConfig()).toThrow(
new Error(`Configuration invalide pour les providers suivants : [
{
"provider": "provider1",
"missingFields": [
"OAUTH_AUTHORIZATION_URL",
"OAUTH_TOKEN_URL",
"OAUTH_CLIENT_SECRET",
"OAUTH_CALLBACK_URL"
]
}
]`)
);
});
});

View file

@ -13,6 +13,7 @@ const folderRouter = require('./routers/folders.js');
const quizRouter = require('./routers/quiz.js');
const imagesRouter = require('./routers/images.js')
const AuthManager = require('./auth/auth-manager.js')
const authRouter = require('./routers/auth.js')
// Setup environement
dotenv.config();
@ -49,6 +50,7 @@ app.use('/api/user', userRouter);
app.use('/api/folder', folderRouter);
app.use('/api/quiz', quizRouter);
app.use('/api/image', imagesRouter);
app.use('/api/auth', authRouter);
// Add Auths methods
const session = require('express-session');

184
server/config/auth.js Normal file
View file

@ -0,0 +1,184 @@
const fs = require('fs');
const path = require('path');
const pathAuthConfig = './auth_config.json';
const configPath = path.join(__dirname, pathAuthConfig);
class AuthConfig {
config = null;
// Méthode pour lire le fichier de configuration JSON
loadConfig() {
try {
const configData = fs.readFileSync(configPath, 'utf-8');
this.config = JSON.parse(configData);
} catch (error) {
console.error("Erreur lors de la lecture du fichier de configuration :", error);
return null;
}
}
// Méthode pour load le fichier de test
loadConfigTest(mockConfig) {
this.config = mockConfig;
}
// Méthode pour retourner la configuration des fournisseurs PassportJS
getPassportJSConfig() {
if (this.config && this.config.auth && this.config.auth.passportjs) {
const passportConfig = {};
this.config.auth.passportjs.forEach(provider => {
const providerName = Object.keys(provider)[0];
passportConfig[providerName] = provider[providerName];
});
return passportConfig;
} else {
return { error: "Aucune configuration PassportJS disponible." };
}
}
// Méthode pour retourner la configuration de Simple Login
getSimpleLoginConfig() {
if (this.config && this.config.auth && this.config.auth["simple-login"]) {
return this.config.auth["simple-login"];
} else {
return { error: "Aucune configuration Simple Login disponible." };
}
}
// Méthode pour retourner tous les providers de type OAuth
getOAuthProviders() {
if (this.config && this.config.auth && this.config.auth.passportjs) {
const oauthProviders = this.config.auth.passportjs.filter(provider => {
const providerName = Object.keys(provider)[0];
return provider[providerName].type === 'oauth';
});
if (oauthProviders.length > 0) {
return oauthProviders;
} else {
return { error: "Aucun fournisseur OAuth disponible." };
}
} else {
return { error: "Aucune configuration PassportJS disponible." };
}
}
// Méthode pour retourner tous les providers de type OIDC
getOIDCProviders() {
if (this.config && this.config.auth && this.config.auth.passportjs) {
const oidcProviders = this.config.auth.passportjs.filter(provider => {
const providerName = Object.keys(provider)[0];
return provider[providerName].type === 'oidc';
});
if (oidcProviders.length > 0) {
return oidcProviders;
} else {
return { error: "Aucun fournisseur OIDC disponible." };
}
} else {
return { error: "Aucune configuration PassportJS disponible." };
}
}
// Méthode pour vérifier si tous les providers ont les variables nécessaires
validateProvidersConfig() {
const requiredOAuthFields = [
'OAUTH_AUTHORIZATION_URL', 'OAUTH_TOKEN_URL', 'OAUTH_CLIENT_ID', 'OAUTH_CLIENT_SECRET', 'OAUTH_CALLBACK_URL'
];
const requiredOIDCFields = [
'OIDC_CLIENT_ID', 'OIDC_CLIENT_SECRET', 'OIDC_ISSUER_URL', 'OIDC_CALLBACK_URL'
];
const missingFieldsReport = [];
if (this.config && this.config.auth && this.config.auth.passportjs) {
this.config.auth.passportjs.forEach(provider => {
const providerName = Object.keys(provider)[0];
const providerConfig = provider[providerName];
let missingFields = [];
// Vérification des providers de type OAuth
if (providerConfig.type === 'oauth') {
missingFields = requiredOAuthFields.filter(field => !(field in providerConfig));
}
// Vérification des providers de type OIDC
else if (providerConfig.type === 'oidc') {
missingFields = requiredOIDCFields.filter(field => !(field in providerConfig));
}
// Si des champs manquent, on les ajoute au rapport
if (missingFields.length > 0) {
missingFieldsReport.push({
provider: providerName,
missingFields: missingFields
});
}
});
// Si des champs manquent, lever une exception
if (missingFieldsReport.length > 0) {
throw new Error(`Configuration invalide pour les providers suivants : ${JSON.stringify(missingFieldsReport, null, 2)}`);
} else {
console.log("Configuration auth_config.json: Tous les providers ont les variables nécessaires.")
return { success: "Tous les providers ont les variables nécessaires." };
}
} else {
throw new Error("Aucune configuration PassportJS disponible.");
}
}
// Méthode pour retourner la configuration des fournisseurs PassportJS pour le frontend
getActiveAuth() {
if (this.config && this.config.auth) {
const passportConfig = {};
// Gestion des providers PassportJS
if (this.config.auth.passportjs) {
this.config.auth.passportjs.forEach(provider => {
const providerName = Object.keys(provider)[0];
const providerConfig = provider[providerName];
passportConfig[providerName] = {};
if (providerConfig.type === 'oauth') {
passportConfig[providerName] = {
type: providerConfig.type,
authorizationUrl: providerConfig.OAUTH_AUTHORIZATION_URL,
callbackUrl: providerConfig.OAUTH_CALLBACK_URL,
};
} else if (providerConfig.type === 'oidc') {
passportConfig[providerName] = {
type: providerConfig.type,
issuerUrl: providerConfig.OIDC_ISSUER_URL,
callbackUrl: providerConfig.OIDC_CALLBACK_URL
};
}
});
}
// Gestion du Simple Login
if (this.config.auth["simple-login"] && this.config.auth["simple-login"].enabled) {
passportConfig['simple-login'] = {
type: "simple-login",
name: this.config.auth["simple-login"].name
};
}
return passportConfig;
} else {
return { error: "Aucune configuration d'authentification disponible." };
}
}
}
module.exports = AuthConfig;

View file

@ -0,0 +1,25 @@
const AuthConfig = require('../config/auth.js');
class authController {
async getActive(req, res, next) {
try {
const authC = new AuthConfig();
authC.loadConfig();
const authActive = authC.getActiveAuth();
const response = {
authActive
};
return res.json(response);
}
catch (error) {
return next(error); // Gérer l'erreur
}
}
}
module.exports = new authController;

9
server/routers/auth.js Normal file
View file

@ -0,0 +1,9 @@
const express = require('express');
const router = express.Router();
const jwt = require('../middleware/jwtToken.js');
const authController = require('../controllers/auth.js')
router.get("/getActiveAuth",jwt.authenticate, authController.getActive);
module.exports = router;