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',
 | 
			
		||||
    idname: 'id',
 | 
			
		||||
    unique: ['id'],
 | 
			
		||||
    indices: baseFields.concat([ 'kty', 'kid' ]),
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    tablename: apiname + '_codes',
 | 
			
		||||
    idname: 'id',
 | 
			
		||||
    indices: baseFields.concat([ 'code', 'expires' ]),
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    tablename: apiname + '_jwks',
 | 
			
		||||
    idname: 'id',
 | 
			
		||||
    unique: ['id'],
 | 
			
		||||
    indices: baseFields.concat([ 'kty', 'kid', 'sub' ]),
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    tablename: apiname + '_grants',
 | 
			
		||||
    idname: 'id',
 | 
			
		||||
    unique: ['id'],
 | 
			
		||||
    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');
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  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) {
 | 
			
		||||
    return store.IssuerOauth3OrgPrivateKeys.get(experienceId).then(function (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) {
 | 
			
		||||
    var 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.post(  '/grants/:sub/:azp', Grants.restful.saveNew);
 | 
			
		||||
 | 
			
		||||
  app.post(  '/access_token/send_otp', Tokens.restful.sendOtp);
 | 
			
		||||
  app.use(   '/access_token/:sub', authorizeIssuer);
 | 
			
		||||
  app.post(  '/access_token/:sub/:aud/:azp', Tokens.restful.create);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user