curlでAmazon CognitoのAPIにアクセスする（デバイス追跡がONの場合）

# 対象者
curlを使用して、HTTP通信を行いAWS Cognito APIにアクセスしたい人向け。
本記事はデバイス追跡機能がONの場合ですのでOFFの設定の方は以下の記事を参考にしてください。

[curlでAmazon CognitoのAPIにアクセス](https://qiita.com/charon/items/f85c03b46c279e18b308)

# デバイス追跡機能とは
公式ドキュメントを参照ください。
セキュリティ強化のために設定しています。

[ユーザープールデバイス追跡設定の指定](https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/amazon-cognito-user-pools-device-tracking.html)

# デバイス追跡がOFFの場合と何が違うのか
コマンドを入力するとデバイス追跡OFFの場合、アクセストークン、IDトークンが再取得されますが、ONの場合は"Inbalid Refresh Token"が発生します。
コマンド：

```
$ curl https://cognito-idp.ap-northeast-1.amazonaws.com \
  -XPOST \
  -H 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
  -H 'Content-Type: application/x-amz-json-1.1' \
  -d '{"ClientId":"[クライアントID]","AuthFlow":"REFRESH_TOKEN_AUTH","AuthParameters":{"REFRESH_TOKEN":"[リフレッシュトークン]"}}'
```

# どうすればいいのか
- APIオペレーション InitiateAuth（AuthFlowパラメータ：USER_PASSWORD_AUTH）呼び出し
↓
- APIオペレーションConfirmDevice 呼び出し
↓ 以下は確認作業
- APIオペレーション InitiateAuth（AuthFlowパラメータ：REFRESH_TOKEN_AUTH）呼び出し 

トークンを更新する前に、デバイス確認を行う必要があるみたいです。

[InitiateAuthドキュメント](https://docs.aws.amazon.com/ja_jp/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)

# 手順
### ①APIオペレーション InitiateAuth（AuthFlowパラメータ：USER_PASSWORD_AUTH）呼び出し
入力コマンド：
```
$ curl https://cognito-idp.ap-northeast-1.amazonaws.com \
  -XPOST \
  -H 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
  -H 'Content-Type: application/x-amz-json-1.1' \
  -d '{"ClientId":"[クライアントID]","AuthFlow":"USER_PASSWORD_AUTH","AuthParameters":{"USERNAME":"[ユーザー名],"PASSWORD":"[パスワード]"}}'
```
出力：
```
{
  "ChallengeParameters": {},
  "AuthenticationResult": {
      "AccessToken": "[アクセストークン]",
      "ExpiresIn": 3600,
      "TokenType": "Bearer",
      "RefreshToken": "[リフレッシュトークン]",
      "IdToken": "[IDトークン]",
      "NewDeviceMetadata": {
          "DeviceKey": "[デバイスキ-]",
          "DeviceGroupKey": "[デバイスグループキー]"
      }
  }
}
```

### ②APIオペレーションConfirmDevice 呼び出し
アクセストークン、デバイスキーは①で出力した値を代入。
PasswordVerifierとSaltについては以下ドキュメントページの『CofirmDeviceを呼び出す』からパラメータを出してください
※結構手間です
[ConfirmDevice を呼び出す](https://aws.amazon.com/jp/premiumsupport/knowledge-center/cognito-user-pool-remembered-devices/)

入力コマンド：
```
$ curl https://cognito-idp.ap-northeast-1.amazonaws.com \
  -XPOST \
  -H 'X-Amz-Target: AWSCognitoIdentityProviderService.ConfirmDevice' \
  -H 'Content-Type: application/x-amz-json-1.1' \
  -d '{"AccessToken":"[アクセストークン]","DeviceKey":"[デバイスキー]","DeviceSecretVerifierConfig": { 
      "PasswordVerifier": "[PasswordVerifier]",
      "Salt": "[Salt]"
      }
```
出力：
```
{
    "UserConfirmationNecessary": false
}
```
### APIオペレーション InitiateAuth（AuthFlowパラメータ：REFRESH_TOKEN_AUTH）呼び出し
"AuthFlow":"REFRESH_TOKEN_AUTH"でもアクセストークン、IDトークンの更新ができるようになる
入力コマンド：
```
$ curl https://cognito-idp.ap-northeast-1.amazonaws.com \
  -XPOST \
  -H 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
  -H 'Content-Type: application/x-amz-json-1.1' \
  -d '{"ClientId":"[クライアントID]","AuthFlow":"REFRESH_TOKEN_AUTH","AuthParameters":{"DEVICE_KEY":"[デバイスキー],"REFRESH_TOKEN":"[リフレッシュトークン]"}}'
```

出力：
```
 {
   "ChallengeParameters": {},
   "AuthenticationResult": {
       "AccessToken": "[アクセストークン]",
       "ExpiresIn": 3600,
       "TokenType": "Bearer",
       "IdToken": "[IDトークン]"
   }
}
```
 # おわりに
トークンの扱いには注意してください

# 参考資料
https://github.com/aws/aws-sdk-java-v2/issues/3418