Amazon Cognito User Poolsの管理者APIをPowerShellから呼び出してユーザーを追加する

# リファレンス
[開発者ガイド](http://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-user-identity-pools.html)
[API Reference](http://docs.aws.amazon.com/ja_jp/cognito-user-identity-pools/latest/APIReference/API_Operations.html)
[AWS Tools for PowerShell Cmdlet Reference](http://docs.aws.amazon.com/powershell/latest/reference/Index.html)(User Poolsは__Amazon Cognito Identity Provider__の項)

# Admin Create User

管理者によるユーザー追加は**Admin Create User**、ユーザー自身によるユーザー登録は**Sign-up**。ユーザーがサインインできるようになるまでのフローが違う。[ユーザーアカウントのサインアップと確認](http://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/signing-up-users-in-your-app.html)の図がわかりやすい。

**AdminCreateUser**ではCognitoからユーザーへメッセージ(*invitation*)が送信される。メッセージにはユーザー名とパスワードが含まれる。指定しなかった場合、パスワードは自動で生成される。

```ps1
$desiredDeliveryMediums = "EMAIL"
$username = "username"
$userAttributes = @(
        @{Name="email"; Value="example@example.com"})

# AdminCreateUser 
New-CGIPUserAdmin `
    -AccessKey $accesskey `
    -SecretKey $secretKey `
    -Region $region `
    `
    -UserPoolId $userPoolId `
    -ForceAliasCreation $FALSE`
    -MessageAction $NULL`
    `
    -DesiredDeliveryMediums $desiredDeliveryMediums `
    -Username $username `
    -UserAttributes $userAttributes

```


### 最初のサインイン
管理者が追加したユーザーは最初のサインインのときにパスワードの変更が必要。

``` ps1
# AdminInitiateAuth
$res1 =
Start-CGIPAuthAdmin `
    -AccessKey $accesskey `
    -SecretKey $secretKey `
    -Region $region `
    `
    -UserPoolId $userPoolId `
    -ClientId $clientId `
    `
    -AuthFlow ADMIN_NO_SRP_AUTH `
    -AuthParameters @{USERNAME=$username; PASSWORD=$password}

#$res1

$challengeResponses = @{ 
    USERNAME=$userName;
    NEW_PASSWORD=$password;
}

# AdminRespondToAuthChallenge
$res2 = 
Send-CGIPAuthChallengeResponseAdmin `
    -AccessKey $accesskey `
    -SecretKey $secretKey `
    -Region $region `
    `
    -UserPoolId $userPoolId `
    -ClientId $clientId `
    `
    -Session $res1.Session `
    -ChallengeName NEW_PASSWORD_REQUIRED `
    -ChallengeResponses $challengeResponses

$res2
```

※invitaionでのみユーザーにパスワードを知らせるのであれば、サインイン成功でverification成功とみなしてよいのでは。verificationの成功は属性`email_verified`[^1]の値`true`で表す。admin APIではverified属性を直接設定できる。

```ps1
$challengeResponses = @{ 
    USERNAME=$userName;
    NEW_PASSWORD=$password;
    EMAIL_VERIFIED=$TRUE;
}
```

# 確認コードの送信による電話番号、メールアドレスの確認
admin APIではない。ユーザーのAccessTokenで実行する処理。

**Get-CGIPUserAttributeVerificationCode**コマンドでCognitoからユーザーに確認コードが送信される。**Test-CGIPUserAttribute**コマンドが成功の場合、Cognitoによりユーザーの属性`email_verified`[^1]が`true`に設定される。

[^1]: SMSの場合は属性`phone_number_verified`が`true`に設定される

```ps1
# AdminInitiateAuth
$res1 =
Start-CGIPAuthAdmin `
    -AccessKey $accesskey `
    -SecretKey $secretKey `
    -Region $region `
    `
    -UserPoolId $userPoolId `
    -ClientId $clientId `
    `
    -AuthFlow ADMIN_NO_SRP_AUTH `
    -AuthParameters @{USERNAME=$username; PASSWORD=$password}

$res1

# GetUserAttributeVerificationCode
Get-CGIPUserAttributeVerificationCode `
    -Region $region `
    `
    -AccessToken $res1.AuthenticationResult.AccessToken `
    -AttributeName email

# VerifyUserAttribute
Test-CGIPUserAttribute `
    -Region $region `
    `
    -AccessToken $res1.AuthenticationResult.AccessToken `
    -AttributeName email `
    -code (Read-Host -Prompt 'Code')
```

# Secret Hash
**app client**に**client secret**がある場合には必要になる。

```ps1
$clientId = ""
$appClientSecret = ""
$userName = ""

$hmac = new-object System.Security.Cryptography.HMACSHA256
$hmac.Key = [Text.Encoding]::ASCII.GetBytes($appClientSecret)
$signature = $hmac.ComputeHash([Text.Encoding]::ASCII.GetBytes($userName + $clientId))
$secretHash = [Convert]::ToBase64String($signature)
```

---