LoginSignup
0
2

More than 5 years have passed since last update.

golangでaws Cognito User Pools 認証やれるかな

Last updated at Posted at 2017-04-30

golangで Cognito User Pools認証をやりたいので調査中..

javascriptの場合

User Pool情報とキーとなるUsernameを使ってCognitoUserオブジェクトを作ります。また認証に必要になるUsernameとPasswordを使ってプロバイダのAuthenticationDetailsというものを作ります。最後にAuthenticationDetailsを使ってCognitoUserオブジェクトを認証させます。認証に成功するとTokenが取れます。CognitoのTokenは3種類(AccessToken, IdToken, RefreshToken)あります。User Poolsが認証するのに必要なのはIdTokenなのでこれをいろいろな画面に引き継いで使ってもOKですね。

引用元: http://dev.classmethod.jp/cloud/aws/login-form-by-using-aws-sdk-for-javascript/

aws/amazon-cognito-identity-js での認証の実装

CognitoUser.js
  /**
   * This is used for authenticating the user. it calls the AuthenticationHelper for SRP related
   * stuff
   * @param {AuthenticationDetails} authDetails Contains the authentication data
   * @param {object} callback Result callback map.
   * @param {onFailure} callback.onFailure Called on any error.
   * @param {newPasswordRequired} callback.newPasswordRequired new
   *        password and any required attributes are required to continue
   * @param {mfaRequired} callback.mfaRequired MFA code
   *        required to continue.
   * @param {customChallenge} callback.customChallenge Custom challenge
   *        response required to continue.
   * @param {authSuccess} callback.onSuccess Called on success with the new session.
   * @returns {void}
   */
  authenticateUser(authDetails, callback) {
    const authenticationHelper = new AuthenticationHelper(
      this.pool.getUserPoolId().split('_')[1]);
    const dateHelper = new DateHelper();

    let serverBValue;
    let salt;
    const authParameters = {};

    if (this.deviceKey != null) {
      authParameters.DEVICE_KEY = this.deviceKey;
    }

    authParameters.USERNAME = this.username;
    authParameters.SRP_A = authenticationHelper.getLargeAValue().toString(16);

    if (this.authenticationFlowType === 'CUSTOM_AUTH') {
      authParameters.CHALLENGE_NAME = 'SRP_A';
    }

    this.client.makeUnauthenticatedRequest('initiateAuth', {
      AuthFlow: this.authenticationFlowType,
      ClientId: this.pool.getClientId(),
      AuthParameters: authParameters,
      ClientMetadata: authDetails.getValidationData(),
    }, (err, data) => {
      if (err) {
        return callback.onFailure(err);
      }

      const challengeParameters = data.ChallengeParameters;

      this.username = challengeParameters.USER_ID_FOR_SRP;
      serverBValue = new BigInteger(challengeParameters.SRP_B, 16);
      salt = new BigInteger(challengeParameters.SALT, 16);
      this.getCachedDeviceKeyAndPassword();

      const hkdf = authenticationHelper.getPasswordAuthenticationKey(
        this.username,
        authDetails.getPassword(),
        serverBValue,
        salt);

      const dateNow = dateHelper.getNowString();

      const signatureString = util.crypto.hmac(hkdf, util.buffer.concat([
        new util.Buffer(this.pool.getUserPoolId().split('_')[1], 'utf8'),
        new util.Buffer(this.username, 'utf8'),
        new util.Buffer(challengeParameters.SECRET_BLOCK, 'base64'),
        new util.Buffer(dateNow, 'utf8'),
      ]), 'base64', 'sha256');

      const challengeResponses = {};

      challengeResponses.USERNAME = this.username;
      challengeResponses.PASSWORD_CLAIM_SECRET_BLOCK = challengeParameters.SECRET_BLOCK;
      challengeResponses.TIMESTAMP = dateNow;
      challengeResponses.PASSWORD_CLAIM_SIGNATURE = signatureString;

      if (this.deviceKey != null) {
        challengeResponses.DEVICE_KEY = this.deviceKey;
      }

      const respondToAuthChallenge = (challenge, challengeCallback) =>
        this.client.makeUnauthenticatedRequest('respondToAuthChallenge', challenge,
          (errChallenge, dataChallenge) => {
            if (errChallenge && errChallenge.code === 'ResourceNotFoundException' &&
                errChallenge.message.toLowerCase().indexOf('device') !== -1) {
              challengeResponses.DEVICE_KEY = null;
              this.deviceKey = null;
              this.randomPassword = null;
              this.deviceGroupKey = null;
              this.clearCachedDeviceKeyAndPassword();
              return respondToAuthChallenge(challenge, challengeCallback);
            }
            return challengeCallback(errChallenge, dataChallenge);
          });

      respondToAuthChallenge({
        ChallengeName: 'PASSWORD_VERIFIER',
        ClientId: this.pool.getClientId(),
        ChallengeResponses: challengeResponses,
        Session: data.Session,
      }, (errAuthenticate, dataAuthenticate) => {
        if (errAuthenticate) {
          return callback.onFailure(errAuthenticate);
        }

        const challengeName = dataAuthenticate.ChallengeName;
        if (challengeName === 'NEW_PASSWORD_REQUIRED') {
          this.Session = dataAuthenticate.Session;
          let userAttributes = null;
          let rawRequiredAttributes = null;
          const requiredAttributes = [];
          const userAttributesPrefix = authenticationHelper
            .getNewPasswordRequiredChallengeUserAttributePrefix();

          if (dataAuthenticate.ChallengeParameters) {
            userAttributes = JSON.parse(
              dataAuthenticate.ChallengeParameters.userAttributes);
            rawRequiredAttributes = JSON.parse(
              dataAuthenticate.ChallengeParameters.requiredAttributes);
          }

          if (rawRequiredAttributes) {
            for (let i = 0; i < rawRequiredAttributes.length; i++) {
              requiredAttributes[i] = rawRequiredAttributes[i].substr(userAttributesPrefix.length);
            }
          }
          return callback.newPasswordRequired(userAttributes, requiredAttributes);
        }
        return this.authenticateUserInternal(dataAuthenticate, authenticationHelper, callback);
      });
      return undefined;
    });
  }

やっぱり無理だな・・・

AuthenticationHelperが重すぎて無理・・・

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2