implemented sending of one-time-passwords
This commit is contained in:
parent
e36689600c
commit
d20e40203e
@ -7,19 +7,21 @@ module.exports = [
|
|||||||
{
|
{
|
||||||
tablename: apiname + '_private_keys',
|
tablename: apiname + '_private_keys',
|
||||||
idname: 'id',
|
idname: 'id',
|
||||||
unique: ['id'],
|
|
||||||
indices: baseFields.concat([ 'kty', 'kid' ]),
|
indices: baseFields.concat([ 'kty', 'kid' ]),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
tablename: apiname + '_codes',
|
||||||
|
idname: 'id',
|
||||||
|
indices: baseFields.concat([ 'code', 'expires' ]),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
tablename: apiname + '_jwks',
|
tablename: apiname + '_jwks',
|
||||||
idname: 'id',
|
idname: 'id',
|
||||||
unique: ['id'],
|
|
||||||
indices: baseFields.concat([ 'kty', 'kid', 'sub' ]),
|
indices: baseFields.concat([ 'kty', 'kid', 'sub' ]),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tablename: apiname + '_grants',
|
tablename: apiname + '_grants',
|
||||||
idname: 'id',
|
idname: 'id',
|
||||||
unique: ['id'],
|
|
||||||
indices: baseFields.concat([ 'sub', 'azp', 'azpSub', 'scope' ]),
|
indices: baseFields.concat([ 'sub', 'azp', 'azpSub', 'scope' ]),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
77
rest.js
77
rest.js
@ -212,6 +212,22 @@ module.exports.create = function (bigconf, deps, app) {
|
|||||||
app.handlePromise(req, res, promise, '[issuer@oauth3.org] save grants');
|
app.handlePromise(req, res, promise, '[issuer@oauth3.org] save grants');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Tokens.retrieveOtpCode = function (codeStore, codeId) {
|
||||||
|
return codeStore.get(codeId).then(function (code) {
|
||||||
|
if (!code) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var expires = (new Date(code.expires)).valueOf();
|
||||||
|
if (!expires || Date.now() > expires) {
|
||||||
|
return codeStore.destroy(codeId).then(function () {
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
});
|
||||||
|
};
|
||||||
Tokens.getPrivKey = function (store, experienceId) {
|
Tokens.getPrivKey = function (store, experienceId) {
|
||||||
return store.IssuerOauth3OrgPrivateKeys.get(experienceId).then(function (jwk) {
|
return store.IssuerOauth3OrgPrivateKeys.get(experienceId).then(function (jwk) {
|
||||||
if (jwk) {
|
if (jwk) {
|
||||||
@ -235,6 +251,66 @@ module.exports.create = function (bigconf, deps, app) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Tokens.restful.sendOtp = function (req, res) {
|
||||||
|
var params = req.body;
|
||||||
|
var promise = PromiseA.resolve().then(function () {
|
||||||
|
if (!params || !params.username) {
|
||||||
|
throw new Error("must provide the email address as 'username' in the body");
|
||||||
|
}
|
||||||
|
if ((params.username_type && 'email' !== params.username_type) || !/@/.test(params.username)) {
|
||||||
|
throw new Error("only email one-time login codes are supported at this time");
|
||||||
|
}
|
||||||
|
params.username_type = 'email';
|
||||||
|
|
||||||
|
return req.getSiteStore();
|
||||||
|
}).then(function (store) {
|
||||||
|
var codeStore = store.IssuerOauth3OrgCodes;
|
||||||
|
var codeId = crypto.createHash('sha256').update(params.username_type+':'+params.username).digest('base64');
|
||||||
|
codeId = makeB64UrlSafe(codeId);
|
||||||
|
|
||||||
|
return Tokens.retrieveOtpCode(codeStore, codeId).then(function (code) {
|
||||||
|
if (code) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = '';
|
||||||
|
while (!/^\d{4}-\d{4}-\d{4}$/.test(token)) {
|
||||||
|
// Most of the number we can generate this was start with 1 (and no matter what can't
|
||||||
|
// start with 0), so we don't use the very first digit. Also basically all of the
|
||||||
|
// numbers are too big to accurately store in JS floats, so we limit the trailing 0's.
|
||||||
|
token = (parseInt(crypto.randomBytes(8).toString('hex'), 16)).toString()
|
||||||
|
.replace(/0+$/, '0').replace(/\d(\d{4})(\d{4})(\d{4}).*/, '$1-$2-$3');
|
||||||
|
}
|
||||||
|
code = {
|
||||||
|
id: codeId,
|
||||||
|
code: token,
|
||||||
|
expires: new Date(Date.now() + 20*60*1000),
|
||||||
|
};
|
||||||
|
return codeStore.upsert(codeId, code).then(function (){
|
||||||
|
return code;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}).then(function (code) {
|
||||||
|
var emailParams = {
|
||||||
|
to: params.username,
|
||||||
|
from: 'login@daplie.com', // opts.mailer.defaults.system
|
||||||
|
replyTo: 'hello@daplie.com',
|
||||||
|
subject: "Use " + code.code + " as your Login Code", // message.Subject
|
||||||
|
text: code.code + " is your Login Code." // message['stripped-html']
|
||||||
|
};
|
||||||
|
emailParams['h:Reply-To'] = emailParams.replyTo;
|
||||||
|
|
||||||
|
return req.getSiteMailer().sendMailAsync(emailParams).then(function () {
|
||||||
|
return {
|
||||||
|
id: code.id,
|
||||||
|
expires: code.expires,
|
||||||
|
created: new Date(parseInt(code.createdAt, 10) || code.createdAt),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.handlePromise(req, res, promise, '[issuer@oauth3.org] send one-time-password');
|
||||||
|
};
|
||||||
Tokens.restful.create = function (req, res) {
|
Tokens.restful.create = function (req, res) {
|
||||||
var store;
|
var store;
|
||||||
var promise = req.getSiteStore().then(function (_store) {
|
var promise = req.getSiteStore().then(function (_store) {
|
||||||
@ -288,6 +364,7 @@ module.exports.create = function (bigconf, deps, app) {
|
|||||||
app.get( '/grants/:sub/:azp', Grants.restful.getOne);
|
app.get( '/grants/:sub/:azp', Grants.restful.getOne);
|
||||||
app.post( '/grants/:sub/:azp', Grants.restful.saveNew);
|
app.post( '/grants/:sub/:azp', Grants.restful.saveNew);
|
||||||
|
|
||||||
|
app.post( '/access_token/send_otp', Tokens.restful.sendOtp);
|
||||||
app.use( '/access_token/:sub', authorizeIssuer);
|
app.use( '/access_token/:sub', authorizeIssuer);
|
||||||
app.post( '/access_token/:sub/:aud/:azp', Tokens.restful.create);
|
app.post( '/access_token/:sub/:aud/:azp', Tokens.restful.create);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user