11require ( "dotenv" ) . config ( ) ;
22const https = require ( "https" ) ;
33const express = require ( "express" ) ;
4+ const syslogPro = require ( "syslog-pro" ) ;
45const rateLimit = require ( "express-rate-limit" ) ;
56
67const { execFile, execFileSync } = require ( "child_process" ) ;
@@ -24,10 +25,23 @@ PassportProfileMapper.prototype.getClaims = function() {
2425 } ;
2526} ;
2627
28+ // Load page settings
2729const customPages = require ( "./websites.json" ) ;
30+ for ( let websiteIndex of Object . keys ( customPages ) ) {
31+ const thisPage = customPages [ websiteIndex ] ;
32+
33+ if ( thisPage . hasOwnProperty ( "syslog" ) ) {
34+ // Load syslog handler
35+ // Documentation: https://cyamato.github.io/SyslogPro/module-SyslogPro-Syslog.html
36+ thisPage . syslog = new syslogPro . Syslog ( thisPage . syslog ) ;
37+ console . log ( "Loaded syslog for website key" , websiteIndex ) ;
38+ }
39+ }
2840
2941// Custom classes
42+ const packageList = require ( "./package.json" ) ;
3043const { DB , User, PwUtil, Audit, Mailer} = require ( "./utils" ) ;
44+ Audit . prepareLoggers ( customPages , packageList . version ) ;
3145
3246const expressPort = process . env . BACKENDPORT || 3000 ;
3347const frontendPort = process . env . FRONTENDPORT || 8080 ;
@@ -37,8 +51,6 @@ const emailFrom = process.env.SMTPUSER || process.env.FALLBACKEMAILFROM;
3751
3852// Configure Fido2
3953if ( hostname == "localhost" && ! disableLocalhostPatching ) {
40- const packageList = require ( "./package.json" ) ;
41-
4254 const utilsLocation = require . resolve ( "fido2-lib/lib/utils.js" ) ;
4355 if ( packageList . dependencies [ "fido2-lib" ] == "^2.1.1" && fs . statSync ( utilsLocation ) . size == 7054 ) {
4456 // FIDO2-Lib does not natively support localhost and due to little maintenance this issue hasn't been fixed yet. See https://github.com/apowers313/fido2-lib/pull/19/files
@@ -170,7 +182,7 @@ PwUtil.createRandomString(30).then(tempJwtToken => {
170182 } ) ;
171183 } ) ;
172184 app . post ( "/authenticator/delete" , isAuthenticated , ( req , res , next ) => {
173- Audit . add ( req . user . id , getIP ( req ) , "authenticator" , "remove" , req . body . handle ) . then ( aID => {
185+ Audit . add ( req , "authenticator" , "remove" , req . body . handle ) . then ( aID => {
174186 User . removeAuthenticator ( req . body . type , req . user . id , req . body . handle ) . then ( ( ) => {
175187 next ( ) ;
176188 } ) . catch ( err => {
@@ -182,9 +194,15 @@ PwUtil.createRandomString(30).then(tempJwtToken => {
182194 } , showSuccess ) ;
183195 app . get ( "/email-confirm" , onEmailConfirm , createAuthToken ) ;
184196
185- // JWT flow
197+ // User SSO flow
186198 app . route ( "/flow/in" ) . get ( onFlowIn , showSuccess ) . post ( onFlowIn , showSuccess ) ;
187199 app . post ( "/flow/out" , isAuthenticated , onFlowOut , showSuccess ) ;
200+ app . get ( "/default-page" , ( req , res , next ) => {
201+ const defaultPage = customPages [ "default" ] ;
202+ return res . status ( 200 ) . json ( {
203+ branding : defaultPage . branding ,
204+ } ) ;
205+ } ) ;
188206
189207 // SAML
190208 // Test flow: https://samltest.id/start-idp-test/
@@ -277,7 +295,7 @@ PwUtil.createRandomString(30).then(tempJwtToken => {
277295 app . post ( "/local/change" , onChange , createAuthToken ) ;
278296 app . post ( "/local/session-clean" , isAuthenticated , ( req , res , next ) => {
279297 const token = req . user . token ;
280- Audit . add ( req . user . id , getIP ( req ) , "session" , "clean" , null ) . then ( ( ) => {
298+ Audit . add ( req , "session" , "clean" , null ) . then ( ( ) => {
281299 User . cleanSession ( req . user . id , token ) . then ( ( ) => {
282300 next ( ) ;
283301 } ) . catch ( err => {
@@ -311,12 +329,12 @@ PwUtil.createRandomString(30).then(tempJwtToken => {
311329 console . error ( err ) ;
312330 res . status ( 404 ) . send ( "No user with this username/password combination found" ) ;
313331 } ) . then ( ( ) => {
314- return Audit . add ( req . user . id , getIP ( req ) , "login" , "password" , null ) ;
332+ return Audit . add ( req , "login" , "password" , null ) ;
315333 } ) . then ( ( ) => {
316334 req . loginEmail = req . body . username ;
317335 next ( ) ;
318336 } ) . catch ( err => {
319- // console.error(err)
337+ console . error ( err ) ;
320338 res . status ( 500 ) . send ( "Internal error during login" ) ;
321339 } ) ;
322340 } , createLoginToken ) ;
@@ -328,7 +346,7 @@ PwUtil.createRandomString(30).then(tempJwtToken => {
328346 } ) , isLoggedIn , ( req , res , next ) => {
329347 const email = req . user . username ;
330348
331- User . requestEmailActivation ( email , getIP ( req ) , "login" ) . then ( token => {
349+ User . requestEmailActivation ( email , Audit . getIP ( req ) , "login" ) . then ( token => {
332350 Mailer . sendMail ( {
333351 from : "OWASP Single Sign-On <" + emailFrom + ">" ,
334352 to : email ,
@@ -407,7 +425,7 @@ PwUtil.createRandomString(30).then(tempJwtToken => {
407425 publicKey : authnrData . get ( "credentialPublicKeyPem" ) ,
408426 } ;
409427
410- return Audit . add ( userId , getIP ( req ) , "authenticator" , "add" , label + " (" + credId + ")" ) ;
428+ return Audit . add ( req , "authenticator" , "add" , label + " (" + credId + ")" ) ;
411429
412430 } ) . then ( ( ) => {
413431 return User . addAuthenticator ( "fido2" , req . user . username , label , {
@@ -505,7 +523,7 @@ PwUtil.createRandomString(30).then(tempJwtToken => {
505523 } ;
506524 return Promise . all ( [
507525 User . updateAuthenticatorCounter ( "fido2" , thisCred . userHandle , returnObj . counter ) ,
508- Audit . add ( userId , getIP ( req ) , "authenticator" , "login" , thisCred . label + " (" + thisCred . userHandle + ")" ) ,
526+ Audit . add ( req , "authenticator" , "login" , thisCred . label + " (" + thisCred . userHandle + ")" ) ,
509527 ] ) ;
510528 } ) . then ( ( ) => {
511529 next ( ) ;
@@ -642,7 +660,7 @@ function onFlowIn(req, res, next) {
642660 User . findUserByName ( email ) . then ( userData => {
643661 req . loginEmail = email ;
644662 req . user = userData ;
645- return Audit . add ( req . user . id , getIP ( req ) , "page" , "request" , thisPage . name ) ;
663+ return Audit . add ( req , "page" , "request" , thisPage . name ) ;
646664 } ) . then ( ( ) => {
647665 // Artificially log in as this user
648666 createLoginToken ( req , res , next ) ;
@@ -656,7 +674,7 @@ function onFlowIn(req, res, next) {
656674 req . loginEmail = email ;
657675 req . user = userData ;
658676
659- return Audit . add ( req . user . id , getIP ( req ) , "page" , "registration" , thisPage . name ) ;
677+ return Audit . add ( req , "page" , "registration" , thisPage . name ) ;
660678 } ) . then ( ( ) => {
661679 createLoginToken ( req , res , next ) ;
662680 } ) . catch ( err => {
@@ -685,7 +703,7 @@ function onFlowOut(req, res, next) {
685703 return res . status ( 400 ) . send ( "Invalid session JWT" ) ;
686704 }
687705
688- Audit . add ( req . user . id , getIP ( req ) , "page" , "login" , thisPage . name ) . then ( ( ) => {
706+ Audit . add ( req , "page" , "login" , thisPage . name ) . then ( ( ) => {
689707 if ( jwtRequest . jwt ) {
690708 jwt . sign ( {
691709 sub : req . user . username ,
@@ -694,7 +712,7 @@ function onFlowOut(req, res, next) {
694712 } , thisPage . jwt , {
695713 expiresIn : shortJWTAge ,
696714 } , ( err , jwtData ) => {
697- Audit . add ( req . user . id , getIP ( req ) , "page" , "login" , thisPage . name ) . then ( ( ) => {
715+ Audit . add ( req , "page" , "login" , thisPage . name ) . then ( ( ) => {
698716 const returnObj = {
699717 redirect : thisPage . redirect ,
700718 token : jwtData ,
@@ -761,8 +779,6 @@ function onCertLogin(req, res, next) {
761779 //console.log("cert login", cert, req.user)
762780
763781 if ( ! cert . subject ) {
764- console . log ( "no subject" , req . headers [ "x-tls-verified" ] ) ;
765-
766782 // No direct connection - check header value
767783 if ( req . headers . hasOwnProperty ( "x-tls-verified" ) && req . headers [ "x-tls-verified" ] == "SUCCESS" ) {
768784 //console.log("receive certificate via proxy", req.headers["x-tls-cert"]);
@@ -847,7 +863,7 @@ function onCertLogin(req, res, next) {
847863 }
848864
849865 if ( ! certHandler . webhook || ! certHandler . webhook . url ) {
850- return Audit . add ( req . user . id , getIP ( req ) , "authenticator" , "login" , thisPage . name + " certificate" ) . then ( ( ) => {
866+ return Audit . add ( req , "authenticator" , "login" , thisPage . name + " certificate" ) . then ( ( ) => {
851867 next ( ) ;
852868 } ) . catch ( err => {
853869 console . error ( err ) ;
@@ -868,7 +884,7 @@ function onCertLogin(req, res, next) {
868884 if ( ! passCertificate ) {
869885 return res . status ( 403 ) . send ( "Certificate denied by page" ) ;
870886 } else {
871- Audit . add ( req . user . id , getIP ( req ) , "authenticator" , "login" , thisPage . name + " certificate" ) . then ( ( ) => {
887+ Audit . add ( req , "authenticator" , "login" , thisPage . name + " certificate" ) . then ( ( ) => {
872888 next ( ) ;
873889 } ) . catch ( err => {
874890 console . error ( err ) ;
@@ -902,7 +918,7 @@ function onCertLogin(req, res, next) {
902918 //console.log("allowed fingerprints", fingerprints)
903919 if ( cert . fingerprint256 in fingerprints ) {
904920 const thisCert = fingerprints [ cert . fingerprint256 ] ;
905- Audit . add ( req . user . id , getIP ( req ) , "authenticator" , "login" , thisCert . label + " (" + cert . fingerprint256 + ")" ) . then ( ( ) => {
921+ Audit . add ( req , "authenticator" , "login" , thisCert . label + " (" + cert . fingerprint256 + ")" ) . then ( ( ) => {
906922 next ( ) ;
907923 } ) ;
908924 } else {
@@ -920,7 +936,7 @@ function onEmailConfirm(req, res, next) {
920936 const token = req . query . token ;
921937 const action = req . query . action ;
922938
923- Audit . add ( req . user ? req . user . id : null , getIP ( req ) , action , "email" , null ) . then ( aID => {
939+ Audit . add ( req , action , "email" , null ) . then ( aID => {
924940 switch ( action ) {
925941 default :
926942 return res . status ( 400 ) . send ( "Invalid action" ) ;
@@ -929,7 +945,7 @@ function onEmailConfirm(req, res, next) {
929945 case "change" :
930946 return res . redirect ( 303 , "/password-change.html?" + token ) ;
931947 case "login" :
932- return User . resolveEmailActivation ( token , getIP ( req ) , action ) . then ( confirmation => {
948+ return User . resolveEmailActivation ( token , Audit . getIP ( req ) , action ) . then ( confirmation => {
933949 next ( ) ;
934950 } ) . catch ( err => {
935951 res . status ( 400 ) . send ( err ) ;
@@ -943,7 +959,7 @@ function onEmailConfirm(req, res, next) {
943959function onRegister ( req , res , next ) {
944960 const email = req . body . email ;
945961
946- User . requestEmailActivation ( email , getIP ( req ) , "registration" ) . then ( token => {
962+ User . requestEmailActivation ( email , Audit . getIP ( req ) , "registration" ) . then ( token => {
947963 Mailer . sendMail ( {
948964 from : "OWASP Single Sign-On <" + emailFrom + ">" ,
949965 to : email ,
@@ -972,6 +988,10 @@ function onCertRegister(req, res, next) {
972988 const email = req . user . username ;
973989 const label = req . body . label ;
974990
991+ if ( email . indexOf ( '"' ) != - 1 ) {
992+ return res . send ( 500 ) . send ( "Email address can't be used for generating certificates" ) ;
993+ }
994+
975995 // On Windows you can use bash.exe delivered with Git and add it to your PATH environment variable
976996 execFile ( "bash" , [
977997 "-c" , "scripts/create-client.bash '" + email + "' '" + email + "'" ,
@@ -990,7 +1010,7 @@ function onCertRegister(req, res, next) {
9901010 return res . status ( 500 ) . send ( "Internal error" ) ;
9911011 }
9921012
993- Audit . add ( req . user . id , getIP ( req ) , "authenticator" , "add" , label + " (" + certData . fingerprint256 + ")" ) . then ( ( ) => {
1013+ Audit . add ( req , "authenticator" , "add" , label + " (" + certData . fingerprint256 + ")" ) . then ( ( ) => {
9941014 res . download ( certPath , "client-certificate.p12" , async err => {
9951015 //console.log("res.download", err)
9961016 fs . unlink ( certPath , err => {
@@ -1015,7 +1035,7 @@ function onCertRegister(req, res, next) {
10151035function onChangeRequest ( req , res , next ) {
10161036 const email = req . body . email ;
10171037
1018- User . requestEmailActivation ( email , getIP ( req ) , "change" ) . then ( token => {
1038+ User . requestEmailActivation ( email , Audit . getIP ( req ) , "change" ) . then ( token => {
10191039 Mailer . sendMail ( {
10201040 from : "OWASP Single Sign-On <" + emailFrom + ">" ,
10211041 to : email ,
@@ -1052,7 +1072,7 @@ function onActivate(req, res, next) {
10521072 const password = req . body . password ;
10531073
10541074 PwUtil . checkPassword ( null , password ) . then ( ( ) => {
1055- return User . resolveEmailActivation ( token , getIP ( req ) , "registration" ) ;
1075+ return User . resolveEmailActivation ( token , Audit . getIP ( req ) , "registration" ) ;
10561076 } ) . then ( confirmation => {
10571077 req . body . username = confirmation . username ;
10581078 req . body . password = password ;
@@ -1069,7 +1089,7 @@ function onChange(req, res, next) {
10691089
10701090 let confirmation ;
10711091 let userId ;
1072- User . resolveEmailActivation ( token , getIP ( req ) , "change" , true ) . then ( confirmed => {
1092+ User . resolveEmailActivation ( token , Audit . getIP ( req ) , "change" , true ) . then ( confirmed => {
10731093 confirmation = confirmed ;
10741094 return User . findUserByName ( confirmation . username ) ;
10751095 } ) . then ( userData => {
@@ -1092,10 +1112,6 @@ function onChange(req, res, next) {
10921112 } ) ;
10931113}
10941114
1095- function getIP ( req ) {
1096- return req . headers [ "x-forwarded-for" ] || req . connection . remoteAddress ;
1097- }
1098-
10991115function str2ab ( str ) {
11001116 const enc = new TextEncoder ( ) ;
11011117 return enc . encode ( str ) ;
0 commit comments