diff --git a/rest.js b/rest.js index 3f2abc5..e713574 100644 --- a/rest.js +++ b/rest.js @@ -212,7 +212,7 @@ module.exports.create = function (bigconf, deps, app) { app.handlePromise(req, res, promise, '[issuer@oauth3.org] save grants'); }; - Tokens.retrieveOtpCode = function (codeStore, codeId) { + Tokens.retrieveOtp = function (codeStore, codeId) { return codeStore.get(codeId).then(function (code) { if (!code) { return null; @@ -228,6 +228,44 @@ module.exports.create = function (bigconf, deps, app) { return code; }); }; + Tokens.validateOtp = function (codeStore, codeId, token) { + if (!codeId) { + return PromiseA.reject(new Error("Must provide authcode ID")); + } + if (!token) { + return PromiseA.reject(new Error("Must provide authcode code")); + } + return codeStore.get(codeId).then(function (code) { + if (!code) { + throw new Error('authcode specified does not exist or has expired'); + } + + return PromiseA.resolve().then(function () { + var attemptsLeft = 3 - (code.attempts && code.attempts.length || 0); + if (attemptsLeft <= 0) { + throw new Error('you have tried to authorize this code too many times'); + } + if (code.code !== token) { + throw new Error('you have entered the code incorrectly. '+attemptsLeft+' attempts remaining'); + } + // TODO: maybe impose a rate limit, although going fast doesn't help you break the + // system when you can only try 3 times total. + }).then(function () { + return codeStore.destroy(codeId).then(function () { + return code; + }); + }, function (err) { + code.attempts = code.attempts || []; + code.attempts.unshift(new Date()); + + return codeStore.upsert(codeId, code).then(function () { + return PromiseA.reject(err); + }, function () { + return PromiseA.reject(err); + }); + }); + }); + }; Tokens.getPrivKey = function (store, experienceId) { return store.IssuerOauth3OrgPrivateKeys.get(experienceId).then(function (jwk) { if (jwk) { @@ -268,7 +306,7 @@ module.exports.create = function (bigconf, deps, app) { var codeId = crypto.createHash('sha256').update(params.username_type+':'+params.username).digest('base64'); codeId = makeB64UrlSafe(codeId); - return Tokens.retrieveOtpCode(codeStore, codeId).then(function (code) { + return Tokens.retrieveOtp(codeStore, codeId).then(function (code) { if (code) { return code; }