diff --git a/src/server/admin/2fa.js b/src/server/admin/2fa.js new file mode 100644 index 0000000..0d0962d --- /dev/null +++ b/src/server/admin/2fa.js @@ -0,0 +1,66 @@ +/* +* libreevent - 2fa.js +* +* Created by Janis Hutz 07/11/2023, Licensed under the GPL V3 License +* https://janishutz.com, development@janishutz.com +* +* +*/ + +const token = require( '../backend/token.js' ); +// let createSSRApp = require( 'vue' ).createSSRApp; +// let renderToString = require( 'vue/server-renderer' ).renderToString; + +class TwoFA { + constructor () { + this.tokenStore = {}; + this.references = {}; + } + + registerStandardAuthentication () { + let tok = token.generateToken( 60 ); + while ( this.tokenStore[ tok ] ) { + tok = token.generateToken( 60 ); + } + this.tokenStore[ tok ] = { 'mode': 'standard' }; + return { 'token': tok }; + } + + registerEnhancedAuthentication () { + let tok = token.generateToken( 60 ); + while ( this.tokenStore[ tok ] ) { + tok = token.generateToken( 60 ); + } + let code = token.generateNumber( 6 ); + this.tokenStore[ tok ] = { 'mode': 'enhanced', 'code': code }; + return { 'code': code, 'token': tok }; + } + + storeTokenReference ( token, sessionID ) { + this.references[ token ] = sessionID; + } + + getTokenReference ( token ) { + return this.references[ token ]; + } + + verifyEnhanced ( token, number = '' ) { + if ( this.tokenStore[ token ]?.mode === 'standard' ) return true; + else if ( this.tokenStore[ token ]?.mode === 'enhanced' ) { + if ( this.tokenStore[ token ].code == number ) { + delete this.tokenStore[ token ]; + return true; + } else return false; + } else return false; + } + + verifySimple ( token ) { + if ( this.tokenStore[ token ]?.mode === 'standard' ) { + delete this.tokenStore[ token ]; + return 'standard'; + } else if ( this.tokenStore[ token ]?.mode === 'enhanced' ) return 'enhanced'; + else return 'invalid'; + } +} + +module.exports = TwoFA; \ No newline at end of file diff --git a/src/server/admin/pwdmanager.js b/src/server/admin/pwdmanager.js index e7fc2be..e794491 100644 --- a/src/server/admin/pwdmanager.js +++ b/src/server/admin/pwdmanager.js @@ -20,7 +20,7 @@ const db = require( '../backend/db/db.js' ); module.exports.checkpassword = function checkpassword ( username, password ) { return new Promise( resolve => { - db.getData( 'admin', username ).then( data => { + db.getDataSimple( 'admin', 'email', username ).then( data => { resolve( bcrypt.compareSync( password, data ) ); } ); } ); diff --git a/src/server/admin/routes.js b/src/server/admin/routes.js index 0e87cc3..24048de 100644 --- a/src/server/admin/routes.js +++ b/src/server/admin/routes.js @@ -7,7 +7,13 @@ * */ +// const db = require( './db/db.js' ); const pwdmanager = require( './pwdmanager.js' ); +const auth = require( './2fa.js' ); +const twoFA = new auth(); +const path = require( 'path' ); + +let responseObjects = {}; module.exports = ( app, settings ) => { /* @@ -15,19 +21,68 @@ module.exports = ( app, settings ) => { */ app.post( '/admin/auth', ( request, response ) => { - pwdmanager.checkpassword( request.body.mail, request.body.pwd ).then( data => { - if ( data ) { - if ( settings.twoFA ) { - // TODO: Support both methods of 2fa - response.send( '2fa' ); + if ( request.body.mail && request.body.password ) { + pwdmanager.checkpassword( request.body.mail, request.body.password ).then( data => { + request.session.username = request.body.mail; + if ( data ) { + // TODO: Send mails + // TODO: Check if user has 2fa enabled + if ( settings.twoFA === 'standard' ) { + let tok = twoFA.registerStandardAuthentication()[ 'token' ]; + request.session.token = tok; + console.log( 'http://localhost:8081/admin/2fa?token=' + tok ); + response.send( { 'status': '2fa' } ); + } else if ( settings.twoFA === 'enhanced' ) { + let res = twoFA.registerEnhancedAuthentication(); + console.log( 'http://localhost:8081/admin/2fa?token=' + res.token ); + request.session.token = res.token; + response.send( { 'status': '2fa+', 'code': res.code } ); + } else { + request.session.loggedInUser = true; + response.send( { 'status': 'ok' } ); + } } else { - request.session.loggedInAdmin = true; - response.send( 'ok' ); + response.send( { 'status': 'pwErr' } ); } - } else { - response.send( 'pwErr' ); - } + } ); + } else { + response.send( 'missingCredentials' ); + } + } ); + + app.get( '/admin/2fa', ( request, response ) => { + // TODO: Add multi language + let tokType = twoFA.verifySimple( request.query.token ); + if ( tokType === 'standard' ) { + request.session.loggedInAdmin = true; + responseObjects[ request.query.token ].write( 'data: authenticated\n\n' ); + response.sendFile( path.join( __dirname + '/../ui/en/2fa/2faSimple.html' ) ); + } else if ( tokType === 'enhanced' ) { + response.sendFile( path.join( __dirname + '/../ui/en/2fa/2faEnhancedAdmin.html' ) ); + } else { + response.sendFile( path.join( __dirname + '/../ui/en/2fa/2faInvalid.html' ) ); + } + } ); + + app.post( '/admin/2fa/verify', ( request, response ) => { + let verified = twoFA.verifyEnhanced( request.body.token, request.body.code ); + if ( verified ) { + request.session.loggedInAdmin = true; + responseObjects[ request.body.token ].write( 'data: authenticated\n\n' ); + response.send( 'ok' ); + } else response.send( 'wrong' ); + } ); + + app.get( '/admin/2fa/check', ( request, response ) => { + response.writeHead( 200, { + 'Content-Type': 'text/event-stream', + 'Cache-Control': 'no-cache', + 'Connection': 'keep-alive', } ); + response.status( 200 ); + response.flushHeaders(); + response.write( 'data: connected\n\n' ); + responseObjects[ request.session.token ] = response; } ); app.get( '/test/login', ( request, response ) => { diff --git a/src/server/ui/en/2fa/2faEnhancedAdmin.html b/src/server/ui/en/2fa/2faEnhancedAdmin.html new file mode 100644 index 0000000..0752faf --- /dev/null +++ b/src/server/ui/en/2fa/2faEnhancedAdmin.html @@ -0,0 +1,132 @@ + + + + + + Two Factor Authentication Invalid + + + +
+

Two-Factor Authen­tication

+

Please enter the code displayed on the login page down below to finish the Two-Factor Authentication.

+
+
+ +
+ + +
+ +
+
+
+ + + + \ No newline at end of file diff --git a/src/webapp/src/router/mainRoutes.js b/src/webapp/src/router/mainRoutes.js index 26e3019..0777b73 100644 --- a/src/webapp/src/router/mainRoutes.js +++ b/src/webapp/src/router/mainRoutes.js @@ -48,6 +48,14 @@ export default [ title: 'Login :: Admin - libreevent' } }, + { + path: '/admin/twoFactors', + name: 'admin2FA', + component: () => import( '../views/admin/TwoFA.vue' ), + meta: { + title: 'Two Factor Authentication :: Admin - libreevent' + } + }, { path: '/signup', name: 'signup', diff --git a/src/webapp/src/views/admin/AdminLoginView.vue b/src/webapp/src/views/admin/AdminLoginView.vue index a9afef5..21e4d5a 100644 --- a/src/webapp/src/views/admin/AdminLoginView.vue +++ b/src/webapp/src/views/admin/AdminLoginView.vue @@ -1,7 +1,7 @@