やりたいこと
Python の Requests (= 外からの HTTPS リクエスト) で、AWS Cognito の認証をしたい。
やりかた
前提
- AWS Cognito のユーザープール でアプリクライアントを作成している。
- このとき、
USER_PASSWORD_AUTH
のみをチェックしている - region は
ap-northeast-1
経緯
https://github.com/aws-amplify/amplify-js を読んで、ログインに対応する部分を見つけ出す。
以下のあたりが使えそう。
packages/src/CognitoUser.jsより抜粋
initiateAuth(authDetails, callback) {
const authParameters = authDetails.getAuthParameters();
authParameters.USERNAME = this.username;
const jsonReq = {
AuthFlow: 'CUSTOM_AUTH',
ClientId: this.pool.getClientId(),
AuthParameters: authParameters,
ClientMetadata: authDetails.getValidationData(),
};
if (this.getUserContextData()) {
jsonReq.UserContextData = this.getUserContextData();
}
this.client.request('InitiateAuth', jsonReq, (err, data) => {
if (err) {
return callback.onFailure(err);
}
const challengeName = data.ChallengeName;
const challengeParameters = data.ChallengeParameters;
if (challengeName === 'CUSTOM_CHALLENGE') {
this.Session = data.Session;
return callback.customChallenge(challengeParameters);
}
this.signInUserSession = this.getCognitoUserSession(data.AuthenticationResult);
this.cacheTokens();
return callback.onSuccess(this.signInUserSession);
});
}
packages/src/Client.jsより抜粋
/**
* Makes an unauthenticated request on AWS Cognito Identity Provider API
* using fetch
* @param {string} operation API operation
* @param {object} params Input parameters
* @param {function} callback Callback called when a response is returned
* @returns {void}
*/
request(operation, params, callback) {
const headers = {
'Content-Type': 'application/x-amz-json-1.1',
'X-Amz-Target': `AWSCognitoIdentityProviderService.${operation}`,
'X-Amz-User-Agent': this.userAgent,
};
const options = {
headers,
method: 'POST',
mode: 'cors',
cache: 'no-cache',
body: JSON.stringify(params),
};
let response;
let responseJsonData;
fetch(this.endpoint, options)
結果
以下のスクリプトで、 JWT Token を get できた。
import requests
# 初期設定
client_id = "クライアントID"
username = "ユーザネーム"
password = "パスワード"
region = "ap-northeast-1"
# リクエスト
endpoint = "https://cognito-idp.%s.amazonaws.com" % region
headers = {
'Content-Type': "application/x-amz-json-1.1",
'X-Amz-Target': "AWSCognitoIdentityProviderService.InitiateAuth",
'X-Amz-User-Agent': "python-requests"
}
res = requests.post(
endpoint,
headers=headers,
data=json.dumps({
"AuthFlow": "USER_PASSWORD_AUTH",
"ClientId": client_id,
"AuthParameters": {
"USERNAME": username,
"PASSWORD": password
},
})
)
print(res.json())