* @description Configuration de passport pour utiliser l'authentification LDAP
* @author kadabra
*
* on a besoin d'authentification pour 2 trucs :
* - l'acces a l'interface admin (admin_view) du back, definie dans admin_router.js
* - le contexte graphQL
*
* serializeUser permet d'obtenir une cle identifiant chaque user
* deserializeUser fait une requete vers une BDD de users en utilisant cette cle, et met dans l'objet JS req.user toutes les infos issues de la BDD
* Cette repartition permet de ne stocker dans la session (i.e. en memoire sur le serveur) que la cle des utilisateurs connectes et de ne "charger en memoire" toutes les infos de la BDD que lorsque necessaire
* et http://toon.io/understanding-passportjs-authentication-flow/
*
* Mais en fait dans notre cas c'est graphql qui communique avec la BDD, donc on s'en fiche! On peut se contenter de dire a serializeUser et deserializeUser de ne s'occuper que du champ uid)
* (on pourrait penser que passer par deserializeUser permettrait de reduire le nombre d'interactions avec la BDD, mais en fait non car deserializeUser est appele *a chaque requete*)
// (note that LdapStrategy has no default verify callback, the "verify" function (L105) is actually the "done" function that is called by the verify callback if we choose to make one)
// we leave this commented out as a template for future use
/*
function (user, done) {
// "verify callback", called after each passport.authenticate(...),
// unless missing credentials (in which case a 400 Error is returned)
// "The purpose of a verify callback is to find the user that possesses a set of credentials" (from passport doc)
// i.e. we query the database (in our case the LDAP) to get user's data
* La configuration inclut tout le _middleware_ définissant les API et les services
* La configuration inclut tout le _middleware_ définissant les API et les services
* nécessaire utilisés, comme `express-session`, GraphiQL, GraphQL Voyager.
* nécessaire utilisés, comme `express-session`, GraphiQL, GraphQL Voyager.
* @author manifold
*
* TODO: changer cette description... ^
* TODD: qu'arrive-t-il aux requetes avec un cookie expire? elles ne sont traitees ni par passport.session() ni par passport.authenticate('ldapauth')...
// WTF??? why is sessionSecret in ldap_config.json? it has nothing to do with ldap. TODO
// Config de passport : le "import './auth';" plus haut execute la configuration de l'objet passport. cf, donc, auth.js
//app.use(cookieParser()); //parses Cookie header and populate req.cookies with an object keyed by the cookie names. was necessary for express-session before its v1.5.0. on peut probablement l'enlever desormais.
// Définit les paramètres de stockage des sessions.
// defines parameters for *session store*. (adds field req.session and do some magic stuff)
// basically, searches for a session matching the received cookie and, if found, adds field req.blasomethingbla containing serialized object representing user (i.e. similar to what passport.serializeUser() could produce)
// TODO: it is important to configure this right!!! please check out https://www.npmjs.com/package/express-session and make sure you understand the way session is stored. (en vrai c'est vraiment important...)
app.use(session({
app.use(session({
secret:config.sessionSecret,
secret:config.sessionSecret,
resave:true,
resave:true,
saveUninitialized:false
saveUninitialized:false,
//store: // TODO: change this. express-session doc warns that default value is ok to use for development only
}));
}));
app.use(passport.initialize());
app.use(passport.initialize());//initialize Passport. (adds hidden field req._passport and do some magic stuff)
app.use(passport.session());
app.use(passport.session());//this is equivalent to app.use(passport.authenticate('session'))
// *aucun* effet sur les requetes n'ayant pas ete reconnues par app.use(session(...)) (e.g. les requetes sans cookie ou les requetes avec cookie expired). source: lecture directe du code passport/lib/strategies/session.js sur github... :/
/**
* FIN AUTHENTIFICATION POUR LES REQUETES POSSEDANT UN COOKIE ET PROVENANT D'UN UTILISATEUR DEJA AUTHENTIFIE
*/
// cache le fait que l'application tourne sous Express dans le header HTTP.
// Options de configuration pour le _middleware_ `cors`.
// Options de configuration pour le _middleware_ `cors`.
// CORS = Cross Origin Resource Sharing
// CORS = Cross Origin Resource Sharing
constcorsOptions={
constcorsOptions={
origin:'http://localhost:8888',// Configures the Access-Control-Allow-Origin CORS header. i.e. specifies that sigma-back wants to make resources accessible to this site (and this site only)
origin:FRONTEND_SERVER_URL_LOCAL,// Configures the Access-Control-Allow-Origin CORS header. i.e. specifies that sigma-back wants to make resources accessible to this site (and this site only)
credentials:true// Configures the Access-Control-Allow-Credentials CORS header. i.e. allows cookies to be included on cross-origin requests
credentials:true// Configures the Access-Control-Allow-Credentials CORS header. i.e. allows cookies to be included on cross-origin requests
};
};
app.use(cors(corsOptions));
app.use(cors(corsOptions));
constSECRET_KEY="azojgc;aegpfrihzcksdlmpqsqkx";
// Config de passport pour l'authentification ldap. Ne fait que *configurer* passport (aucun passport.authenticate() n'est appele, par exemple)
// If authentication failed, user will be set to false
// If authentication failed, user will be set to false
if (!user){
if (!user){
returnres.status(401).json({
returnres.status(401).json({
message:"Authentication failed: "+info.message,
message:"Authentication failed: "+info.message,
authSucceeded:false
authSucceeded:false
});
});
}
}
req.login(user,(err)=>{
req.login(user,(err)=>{
// If an exception occurred at login
// If an exception occurred at login
if (err){
if (err){
console.log(err);
console.log(err);
returnres.status(err.status).json({
returnres.status(err.status).json({
message:"Exception raised in backend process during login: "+err,
message:"Exception raised in backend process during login: "+err,
...
@@ -160,6 +178,19 @@ app.post('/login',
...
@@ -160,6 +178,19 @@ app.post('/login',
);
);
*/
*/
/**
* FIN AUTHENTIFICATION POUR LES REQUETES DE CONNEXION VIA LDAP VENANT DU FRONT
*/
/**
* @desc API GRAPHQL
*/
import{dn,passwd}from"../ldap_connexion_config.json";// default user
app.use('/graphql',
app.use('/graphql',
graphqlHTTP(async (req,res,params)=>{
graphqlHTTP(async (req,res,params)=>{
...
@@ -181,8 +212,8 @@ app.use('/graphql',
...
@@ -181,8 +212,8 @@ app.use('/graphql',
}
}
}else{
}else{
// FOR DEVELOPMENT ONLY. for production, replace with a "publicUser" or "notLoggedInUser" or something.
// FOR DEVELOPMENT ONLY. for production, replace with a "publicUser" or "notLoggedInUser" or something.
uid=defaultUser.dn.split("=")[1].split(",")[0];
uid=dn.split("=")[1].split(",")[0];
password=defaultUser.passwd;
password=passwd;
}
}
console.log("Cookies:",req.cookies);
console.log("Cookies:",req.cookies);
...
@@ -195,14 +226,50 @@ app.use('/graphql',
...
@@ -195,14 +226,50 @@ app.use('/graphql',
})
})
);
);
/**
* FIN API GRAPHQL
*/
/**
* @desc SETUP DE ADMINVIEW, L'INTERFACE ADMIN DES BDD
* Remarque: le graphiql est desormais integre a express-graphql (mai 2018), donc il n'est plus possible de le proteger par connect-ensure-login, ni donc de considerer qu'il fait partie de l'adminview.
* C'est relativement grave, car n'importe qui se connectant directement a [adresse_IP_de_roued]/graphql peut faire des requetes a la base de donnees de sigma
* Donc il faudra retirer cette fonctionnalite en production ; or elle est pratique, meme en production, pour des sanity checks.
* ...bref integrer graphiql a express-graphql etait completement con.
*/
// setting up view engine for pug, for adminview
console.log("Running at",__dirname);
letviewpath=path.resolve(__dirname,'views');
app.set('views',viewpath);
app.set('view engine','pug');
// connect-flash is middleware for flashing messages, used in adminview
app.use(flash());
// GraphQL voyager affiche une représentation sous forme de graphe du schema GraphQL
// GraphQL voyager affiche une représentation sous forme de graphe du schema GraphQL
// accessible depuis adminview
app.use('/voyager',
app.use('/voyager',
/*ensureLoggedIn('/login'),*/
/*ensureLoggedIn('/login'),*/
graphqlVoyager({endpointUrl:'/graphql'})
graphqlVoyager({endpointUrl:'/graphql'})
);
);
// connect-flash is middleware for flashing messages
// on utilise un express.Router qui sert a creer un "sous-middleware stack".
// used in sigma-back's admin interface
app.use('/adminview',router);// catches and resolves HTTP requests to paths '/adminview/*'
app.use(flash());
// catch all other GET requests.
// il est bien sur essentiel de mettre ceci a la toute fin du middleware stack !
app.get('/*',
((req,res,next)=>res.redirect('/adminview'))
);
/**
* FIN SETUP DE ADMINVIEW, L'INTERFACE ADMIN DES BDD