/** * This router handles things related to the web browser experience... */ // This is the mock data we working with... module.exports = function (options) { const config = require('config'); var QRCode = require('qrcode'); var express = options.express; const db = options.db; const hdAuthUtil = options.hdAuthUtil; var router = express.Router(); router.route('/') .get(function(request, response, next) { response.render("home", { user: request.user, pageTitle: "HDAuth - Account" }) }); router.route('/authenticate') .get(function(request, response, next) { if(request.user) { response.redirect('/account'); } else { response.render("login-displayName", { user: request.user, pageTitle: "HDAuth - Login" }) } }) .post(function(request, response, next) { if(request.user) { response.redirect('/account'); } else { db.User.findOne({ where: { displayName: request.body.displayName }, include: [ { association: db.User.ExtendedPublicKeys, required: true } ] }).then(user => { if(user) { // TODO: Support multiple login options... const loginMessage = { action: "authenticate", url: config.get("server.domain"), userIdentifier: user.displayName, } const challenge = hdAuthUtil.createChallenge( user.extendedPublicKeys[0].xpub, JSON.stringify(loginMessage) // TODO: Create a login body... ) QRCode.toDataURL(JSON.stringify(challenge), function (err, url) { if(err) { console.error(err); } response.render("xpub-login", { // challenge user to sign thier xpub challenge: challenge, qrCode: url, user: request.user }) }) } else { // User doesn't exist register account response.render("login-signup", { user: request.user, displayName: request.body.displayName, pageTitle: "HD Auth - Signup", }); } }).catch(error => { console.error("Failed to fulfill account/authenticate post", request.body); console.error("Reason: ", error); response.render("error", { message: "This site didn't have the time for error handling." }) }) } }); router.route('/authenticate/response') .post(function(request, response, next) { if(request.user) { response.redirect('/account'); } else { // Verify challenge if(hdAuthUtil.verifyHDAuthChallengeResponse(request.body)) { // user passed challenge... var loginMessage = JSON.parse(request.body.message); db.User.findOne({ where: { displayName: loginMessage.userIdentifier, }, include: [ { association: db.User.ExtendedPublicKeys } ] }).then(user => { if(user) { // User created we can authenticate them on the site... request.logIn(user, function(err) { if (err) { return next(err); } return response.redirect('/'); }); } else { console.error("Authenticated user doesn't exist: ", loginMessage); } }).catch(error => { console.error("Failed to create authenticated user"); console.error("Error: ", error); next(error); }) } else { // user failed challenge console.error("User failed to authenticate"); // Create new challenge and try again... return response.redirect('/authenticate'); } } }) router.route('/register') .get(function(request, response, next) { if(request.user) { response.redirect('/account'); } else { response.render("account-registration", { user: request.user, newUser: {}, pageTitle: "HDAuth - Registration" }) } }) router.route('/register/xpub') .post(function(request, response, next) { if(request.user) { response.redirect('/account'); } else { db.User.build({ displayName: request.body.displayName, extendedPublicKeys: [ { xpub: request.body.xpub } ] }, { include: [ { association: db.User.ExtendedPublicKeys } ] }).validate() .then(xpubUser => { if (xpubUser) { // Challenge const registerationMessage = { action: "register", url: config.get("server.domain"), userIdentifier: xpubUser.displayName, // identifier the user supplies on the login page user: xpubUser, serviceExtendedPublicKey: config.get("bip32.serviceAuthenticatingExtendedPublicKey") } const challenge = hdAuthUtil.createChallenge( request.body.xpub, // update this to identifier... JSON.stringify(registerationMessage) ) QRCode.toDataURL(JSON.stringify(challenge), function (err, url) { if(err) { console.error(err); } response.render("xpub-account-registeration-challenge", { xpubUser: xpubUser, // challenge user to sign thier xpub challenge: challenge, qrCode: url, user: request.user }) }) } else { console.log("Empty User") // TODO: error handling.. response.render("error", { user: request.user, message: "VOID" }) } }).catch(error => { console.error("Failed to create user"); console.error("Reason: ", error); // TODO: error handling.. response.render("error", { user: request.user, message: "Failed to create user" }) }) } }) router.route('/register/xpub/response') .post(function(request, response, next) { if(request.user) { response.redirect('/account'); } else { // Verify challenge if(hdAuthUtil.verifyHDAuthChallengeResponse(request.body)) { // user passed challenge... // TODO: Load registration request from challenge.message // TODO: build and validate that user owns xpub... var xpubUser = JSON.parse(request.body.message).user; // Possibility that username is taken... // TODO: Create user without username db.User.create(xpubUser, { include: [ { association: db.User.ExtendedPublicKeys } ] }).then(user => { if(user) { // User created we can authenticate them on the site... request.logIn(user, function(err) { if (err) { return next(err); } return response.redirect('/'); }); } }).catch(error => { console.error("Failed to create authenticated user"); console.error("Error: ", error); next(error); }) } else { // user failed challenge // TODO: Validate input // TODO: Createa new challenge console.error("User failed to authenticate"); // Create new challenge and try again... } } }) router.route('/logout') .post(function(request, response, next) { if(request.user) { request.logout(); response.redirect('/'); // db.Session.destroy({ // where: { // sid: request.sessionID // } // }).then(() => { // console.log("") // }).catch(error => { // next(error); // console.error("Log out error: ", error); // }) } else { // No user... response.redirect('/'); } }); // TODO: add other endpoints return router; };