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が重すぎて無理・・・