概要

原来有个网站,存在完善的账号管理,现在要增加一个网站,希望能使用统一的账号管理。

理想的方案是增加一个OAuth2服务,两个网站分别接入这个服务。但是由于特别的原因,旧网站只能进行微小的发动,于是要求这个 OAuth2 要能够支持自定义流程以旧网站的顺利接入而且不需要多少的变化。最终选择了使用 AWS Cognito 服务

参考文档:使用 Lambda 触发器自定义用户池工作流

设计方案

  1. 使用旧网站的登陆做为主登陆界面,所有的登陆请求重定向到旧网站的登陆界面,并带上来源地址。
  2. 登陆完成后,跳转到新网站的登陆校验 api 地址
  3. 在新的网站完成 Cognito 的自定义用户登陆过程来保持用户的统一.

实现过程

新网站中用户管理相关全部 Redirect 到旧网站的相关链接,使用旧有的用户管理和注册登陆不再改变。
旧网站中增加一个链接,用于跳转新网站并告诉新的网站当前登陆的账号

  • 新网站增加 Get /auth/sign_in
  • 并使用 Cognito 的 initiateAuth 访问 Cognito 获取授权
  • 流程 AuthFlow 设定为 CUSTOM_AUTH
  • 通过 UserPool 设置 Define Auth Challenge,Create Auth Challenge,Verify Auth Challenge Response 以响应授权询问过程
  • 获取授权成功后转跳到首页
  • 旧网站在转跳到新网站时,通过约定的授权方式(api-key)访问该地址,并带上当前登陆的账户标识。

    
    initiateAuth([
       'AuthFlow' => 'CUSTOM_AUTH',
       'AuthParameters' => [
           'USERNAME' => <Username>,
          'SECRET_HASH' => <hash(ClientId,Username)>,
      ],
      'ClientId' => ClientId,
    ])
    exports.handler = (event, context, callback) => {
    /**
     * triggerSource
     * Define auth challenge    DefineAuthChallenge_Authentication    Define Auth Challenge.
     * Create auth challenge    CreateAuthChallenge_Authentication    Create Auth Challenge.
     * Verify auth challenge    VerifyAuthChallengeResponse_Authentication    Verify Auth Challenge Response.
     * 
     */
    
    const { request, response } = event;
    const {session} = request;
    switch (event.triggerSource) {
      case 'DefineAuthChallenge_Authentication':
        if (session.length === 0) { // custom auth return token
          response.issueTokens = true;
          response.failAuthentication = false;
        } else {
          if (session.length == 1 && session[0].challengeName == 'SRP_A') {
            response.issueTokens = false;
            response.failAuthentication = false;
            response.challengeName = 'PASSWORD_VERIFIER';
          } else if (session.length == 2 && session[1].challengeName == 'PASSWORD_VERIFIER' && session[1].challengeResult == true) {
            response.issueTokens = false;
            response.failAuthentication = false;
            response.challengeName = 'CUSTOM_CHALLENGE';
          } else if (session.length == 3 && session[2].challengeName == 'CUSTOM_CHALLENGE' && session[2].challengeResult == true) {
            response.issueTokens = true;
            response.failAuthentication = false;
          } else {
            response.issueTokens = false;
            response.failAuthentication = false;
            response.challengeName = 'CUSTOM_CHALLENGE';
          }
        }
        break;
      case 'CreateAuthChallenge_Authentication':
        if (request.challengeName == 'CUSTOM_CHALLENGE') {
          response.publicChallengeParameters = {};
          response.publicChallengeParameters.captchaUrl = 'url/123.jpg';
          response.privateChallengeParameters = {};
          response.privateChallengeParameters.answer = '5';
          response.challengeMetadata = 'CAPTCHA_CHALLENGE';
        }
    
        break;
      case 'VerifyAuthChallengeResponse_Authentication':
        if (request.privateChallengeParameters.answer == request.challengeAnswer) {
          response.answerCorrect = true;
        } else {
          response.answerCorrect = false;
        }
        break;
      default:
    
    }
    
    //Return to Amazon Cognito
    callback(null, event);
    };
    

遇到过的问题

标签: AWS, Cognito

评论已关闭