419 lines
18 KiB
JavaScript
Raw Normal View History

2019-11-23 23:08:03 +02:00
/**
* 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 = {
2019-12-02 07:47:36 +02:00
action: "authenticate",
2019-12-04 21:46:42 +02:00
responseEndpoint: `http://${config.get("server.domain")}/xpub-auth/sign`,
2019-12-02 07:47:36 +02:00
url: config.get("server.domain"),
2019-11-23 23:08:03 +02:00
userIdentifier: user.displayName,
}
const challenge = hdAuthUtil.createChallenge(
user.extendedPublicKeys[0].xpub,
JSON.stringify(loginMessage) // TODO: Create a login body...
)
2019-12-04 21:46:42 +02:00
return db.Challenge.create(challenge);
} else {
// User doesn't exist register account
response.render("login-signup", {
user: request.user,
displayName: request.body.displayName,
pageTitle: "HD Auth - Signup",
});
}
}).then(challenge => {
if(challenge) {
2019-11-23 23:08:03 +02:00
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
})
})
}
}).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."
})
})
}
});
2019-12-04 21:46:42 +02:00
router.route('/authenticate/signed')
.post(function(request, response, next) {
if(request.user) {
response.redirect('/account');
} else {
// Verify challenge
db.Challenge.findByPk(request.body.id, {
where: {
response: {
[db.Sequelize.Op.ne]: null
}
}
}).then(challenge => {
if (challenge) {
if(hdAuthUtil.verifyHDAuthChallengeResponse(challenge)) {
// user passed challenge...
var loginMessage = JSON.parse(challenge.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); }
challenge.destroy()
.then(() => {
console.log("Deleted Challege: ", request.body.id);
})
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
// TODO: Validate input
// TODO: Createa new challenge
response.redirect("/register");
console.error("User failed to authenticate");
// Create new challenge and try again...
}
} else {
console.error("User challenge not signed: ", request.body);
}
});
}
})
2019-11-23 23:08:03 +02:00
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 = {
2019-12-02 07:47:36 +02:00
action: "register",
2019-12-04 21:46:42 +02:00
responseEndpoint: `http://${config.get("server.domain")}/xpub-auth/sign`,
serviceExtendedPublicKey: config.get("bip32.serviceAuthenticatingExtendedPublicKey"),
2019-12-02 07:47:36 +02:00
url: config.get("server.domain"),
2019-11-23 23:08:03 +02:00
userIdentifier: xpubUser.displayName, // identifier the user supplies on the login page
2019-12-04 21:46:42 +02:00
user: xpubUser
2019-11-23 23:08:03 +02:00
}
const challenge = hdAuthUtil.createChallenge(
request.body.xpub, // update this to identifier...
JSON.stringify(registerationMessage)
)
2019-12-04 21:46:42 +02:00
return db.Challenge.create(challenge);
} else {
console.log("Empty User")
// TODO: error handling..
response.render("error", {
user: request.user,
message: "VOID"
});
return null;
}
}).then(challenge => {
if(challenge) {
// send user a challenge...
2019-11-23 23:08:03 +02:00
QRCode.toDataURL(JSON.stringify(challenge), function (err, url) {
if(err) {
console.error(err);
}
response.render("xpub-account-registeration-challenge", {
// challenge user to sign thier xpub
challenge: challenge,
qrCode: url,
user: request.user
})
})
} else {
2019-12-04 21:46:42 +02:00
console.error("Couldn't create new challenge");
2019-11-23 23:08:03 +02:00
response.render("error", {
user: request.user,
2019-12-04 21:46:42 +02:00
message: "Failed to create challenge"
2019-11-23 23:08:03 +02:00
})
}
}).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
2019-12-04 21:46:42 +02:00
response.redirect("/register");
2019-11-23 23:08:03 +02:00
console.error("User failed to authenticate");
// Create new challenge and try again...
}
}
})
2019-12-04 21:46:42 +02:00
router.route('/register/xpub/signed')
.post(function(request, response, next) {
if(request.user) {
response.redirect('/account');
} else {
// Verify challenge
db.Challenge.findByPk(request.body.id, {
where: {
response: {
[db.Sequelize.Op.ne]: null
}
}
}).then(challenge => {
if (challenge) {
if(hdAuthUtil.verifyHDAuthChallengeResponse(challenge)) {
// user passed challenge...
// TODO: Load registration request from challenge.message
// TODO: build and validate that user owns xpub...
var xpubUser = JSON.parse(challenge.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); }
challenge.destroy()
.then(() => {
console.log("Deleted Challege: ", request.body.id);
})
return response.redirect('/');
});
// TODO: delete challenge...
}
}).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
response.redirect("/register");
console.error("User failed to authenticate");
// Create new challenge and try again...
}
} else {
console.error("User challenge not signed: ", request.body);
}
});
}
})
2019-11-23 23:08:03 +02:00
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;
};