fxa-auth-server/routes/idp.js

301 строка
6.4 KiB
JavaScript
Исходник Обычный вид История

2013-05-16 00:42:25 +04:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
2013-05-15 03:23:36 +04:00
const Hapi = require('hapi');
const fs = require('fs');
2013-05-16 01:08:03 +04:00
const CC = require('compute-cluster');
const config = require('../lib/config').root();
2013-05-15 03:23:36 +04:00
2013-05-16 01:08:03 +04:00
const hour = 1000 * 60 * 60;
const T = Hapi.types;
2013-05-15 03:23:36 +04:00
2013-05-16 01:08:03 +04:00
var cc = new CC({ module: __dirname + '/sign.js' });
var account = require('../lib/account');
2013-05-15 03:23:36 +04:00
var routes = [
{
method: 'GET',
path: '/.well-known/browserid',
config: {
handler: wellKnown
}
},
{
method: 'GET',
path: '/sign_in.html',
config: {
handler: {
file: './sign_in.html'
}
}
},
{
method: 'GET',
path: '/provision.html',
config: {
handler: {
file: './provision.html'
}
}
},
2013-05-16 00:42:25 +04:00
{
method: 'POST',
path: '/create',
config: {
description:
"Creates an account associated with an email address, " +
"passing along SRP information (salt and verifier) " +
"and a wrapped key (used for class B data storage).",
tags: ["srp", "account"],
2013-05-16 00:42:25 +04:00
handler: create,
validate: {
payload: {
email: T.String().email().required(),
verifier: T.String().required(),
salt: T.String().required(),
params: T.Object(), // TODO: what are these?
wrapKb: T.String() // TODO: required?
2013-05-16 00:42:25 +04:00
}
}
}
},
2013-05-15 03:23:36 +04:00
{
method: 'POST',
path: '/sign',
config: {
handler: sign,
auth: {
strategy: 'hawk',
payload: 'required'
},
tags: ["account"],
2013-05-15 03:23:36 +04:00
validate: {
payload: {
publicKey: Hapi.types.String().required(),
duration: Hapi.types.Number().integer().min(0).max(24 * hour).required()
2013-05-15 03:23:36 +04:00
}
}
}
},
{
method: 'POST',
path: '/startLogin',
2013-05-15 03:23:36 +04:00
config: {
description:
"Begins an SRP login for the supplied email address, " +
"returning the temporary sessionId and parameters for " +
"key stretching and the SRP protocol for the client.",
tags: ["srp", "account"],
handler: startLogin,
2013-05-15 03:23:36 +04:00
validate: {
payload: {
email: T.String().email().required()
},
response: {
schema: {
sessionId: T.String(),
stretch: T.Object({
salt: T.String()
}),
srp: T.Object({
N_bits: T.Number(), // number of bits for prime
alg: T.String(), // hash algorithm (sha256)
s: T.String(), // salt
B: T.String() // server's public key value
})
}
2013-05-16 00:42:25 +04:00
}
}
}
},
{
method: 'POST',
path: '/finishLogin',
config: {
description:
"Finishes the SRP dance, with the client providing " +
"proof-of-knownledge of the password and receiving " +
"the bundle encrypted with the shared key.",
tags: ["srp", "account"],
2013-05-16 00:42:25 +04:00
handler: finishLogin,
validate: {
payload: {
sessionId: T.String().required(),
password: T.String().without('A'),
A: T.String().without('password').with('M'),
M: T.String().with('A')
},
response: {
schema: {
bundle: T.String().without('kA').without('wrapKb'),
accountToken: T.String(),
kA: T.String().without('bundle'),
wrapKb: T.String().without('bundle')
}
2013-05-15 03:23:36 +04:00
}
}
}
},
{
method: 'POST',
path: '/resetToken',
config: {
tags: ["account"],
handler: getResetToken,
validate: {
payload: {
accountToken: T.String().required()
},
response: {
schema: {
resetToken: T.String().required()
}
}
}
}
},
{
method: 'POST',
path: '/resetPassword',
config: {
tags: ["account"],
handler: resetPassword,
validate: {
payload: {
resetToken: T.String().required(),
verifier: T.String().required(),
params: T.Object(),
wrapKb: T.String()
}
}
}
},
2013-05-15 03:23:36 +04:00
];
function wellKnown(request) {
request.reply({
'public-key': fs.readFileSync(config.publicKeyFile),
2013-05-15 03:23:36 +04:00
'authentication': '/sign_in.html',
'provisioning': '/provision.html'
2013-05-16 01:08:03 +04:00
});
2013-05-15 03:23:36 +04:00
}
2013-05-16 00:42:25 +04:00
function create(request) {
account.create(
request.payload,
function (err) {
2013-05-16 00:42:25 +04:00
if (err) {
request.reply(err);
2013-05-16 00:42:25 +04:00
}
else {
//TODO do stuff
2013-05-16 01:08:03 +04:00
request.reply('ok');
2013-05-16 00:42:25 +04:00
}
}
2013-05-16 01:08:03 +04:00
);
2013-05-16 00:42:25 +04:00
}
2013-05-15 03:23:36 +04:00
function sign(request) {
account.getUser(
request.auth.credentials.uid,
function (err, user) {
if (err) { return request.reply(Hapi.error.internal('Unable to sign certificate', err)); }
cc.enqueue(
{
email: user.email,
publicKey: request.payload.publicKey,
duration: request.payload.duration
},
function (err, result) {
if (err || result.err) {
request.reply(Hapi.error.internal('Unable to sign certificate', err || result.err));
}
else {
request.reply(result);
}
}
);
2013-05-15 03:23:36 +04:00
}
2013-05-16 01:08:03 +04:00
);
2013-05-15 03:23:36 +04:00
}
function startLogin(request) {
account.startLogin(
2013-05-15 03:23:36 +04:00
request.payload.email,
function (err, result) {
2013-05-15 03:23:36 +04:00
if (err) {
request.reply(err);
2013-05-15 03:23:36 +04:00
}
else {
request.reply(result);
2013-05-15 03:23:36 +04:00
}
}
2013-05-16 01:08:03 +04:00
);
2013-05-15 03:23:36 +04:00
}
2013-05-16 00:42:25 +04:00
function finishLogin(request) {
2013-06-25 04:21:02 +04:00
function respond(err, result) {
if (err) {
request.reply(err);
}
2013-06-25 04:21:02 +04:00
else {
request.reply(result);
}
}
2013-06-25 04:21:02 +04:00
if (request.payload.password) {
account.finishLoginWithPassword(
request.payload.sessionId,
request.payload.password,
respond
);
}
else {
account.finishLoginWithSRP(
request.payload.sessionId,
request.payload.A,
request.payload.M,
respond
);
}
2013-05-16 00:42:25 +04:00
}
function getResetToken(request) {
account.getResetToken(
request.payload.accountToken,
function (err, result) {
if (err) {
request.reply(err);
}
else {
request.reply(result);
}
}
);
}
function resetPassword(request) {
account.resetPassword(
request.payload.resetToken,
request.payload,
function (err) {
if (err) {
request.reply(err);
}
else {
request.reply('ok');
}
}
);
}
2013-05-15 03:23:36 +04:00
module.exports = {
routes: routes
2013-05-16 01:08:03 +04:00
};