Amazon Cognitoのサインインに使えるユーザー属性の設定とその挙動について
Amazon Cognitoはサインインに使える識別子の選択肢がある
AWS Management Consoleから作成しようとすると「Cognito ユーザープールのサインインオプション」として、いくつかの選択肢が出てくる。
これは、ユーザープールを作成する際に設定し、途中で変更できない。このスクリーンショットでは、「ユーザー名」のみ選択した状態になっている。この場合にのみ「ユーザー名の要件」のオプションが表示される。
実は、チェックする選択肢の数によっても異なる挙動になる、らしいので、どうなるのかを検証してみたい。
サインインオプションのドキュメント
これらの選択肢の意味や、選択した時の挙動などについて書かれたドキュメントは、下記のページになる。度ドキュメントの目次で言うと、ユーザーの管理 -> 属性となるので、場所が分かりづらい。
ユーザー名として使える属性
Cognitoでは、サインインに利用可能な属性として「ユーザー名属性」と「エイリアス属性」の2種類の属性を定義している。
ユーザー名属性とエイリアス属性の違いは、ドキュメントに下記のように整理されている。
- ユーザーが複数の属性を使ってサインアップまたはサインイン可能にするには、エイリアス属性を使う
- メールアドレス(email)、電話番号(phone_number)、優先ユーザー名(preferred_username)
- エイリアス属性にemailとphone_numberを使う場合は、ユーザーはそれらを所有していることを確認する必要がある
- サインアップする際に、メールまたは電話に対して確認コードが送られてくる方式
- エイリアス属性にemailとphone_numberを使う場合は、サインアップ時には他のユーザーが同じ値を使っていたとしても、エラーにはならない
- つまり、エイリアス属性の場合、同じemailまたはphone_numberを登録することができる
- エイリアス属性は登録後に変更できる
つまり、ユーザー名属性の場合は、エイリアス属性と違って、下記のような特徴がある。
- ユーザー名属性以外の属性値でサインインできない
- 重複した値を登録することができない(サインアップできない)
- サインインするのに、emailやphone_numberの所有権の確認は不要
- ユーザー名属性がemailとphone_numberの両方が有効になっている場合、サインインに使う識別子をemailからphone_numberに変更できない
- emailやphone_number自体を変更することはできる
これをみても、何をどうしたらどうなるのかが、よくわからないので、実際に試してみることにする。
ユーザープールを作成するAPIはどうなっているのか
AWS Management Consoleでユーザープールを作成しようとすると、何をどう選択するとどうなるのかがとても分かりづらいので、APIの仕様を調べてみる。この場合、AWS CLIのドキュメントがわかりやすい。
関連するオプションは--username-attributes
と--alias-attributes
である。
--username-attributes
説明には、下記のように書いてある。
Specifies whether a user can use an email address or phone number as a username when they sign up.
つまり、ユーザーを作成する際に、ユーザー名としてemailまたはphone_numberのどちらかを使う設定ということになる。有効な値は、emailまたはphone_numberとある。つまり、ユーザー名属性にはpreferred_usernameは使えない、ということだ。
AWS Management Consoleでは、ユーザー名のみを指定することができたので、これは直感に反する。それについては一旦脇においておく。
--alias-attributes
説明には、下記のように書いてある。
Attributes supported as an alias for this user pool. Possible values: phone_number , email , or preferred_username .
phone_numberとemailとpreferred_usernameが使える、と書いてある。
AWS Management Consoleでの指定は、こちらの方のような気がする。
AWS CLIでユーザープールを作成してみる
では、実際にAWS CLIを使ってユーザープールを作成してみることにする。とりあえず全部入りにしたらどうなるか。
aws cognito-idp create-user-pool --pool-name usernametest --username-attributes email --alias-attributes phone_number preferred_username
しかしこれは、エラーになる。
An error occurred (InvalidParameterException) when calling the CreateUserPool operation: Only one of the aliasAttributes or usernameAttributes can be set in a User pool.
つまり、--username-attributes
と--alias-attributes
は同時に指定できない。なるほど。
では、気を取り直して、ユーザー名属性だけにしてみよう。
aws cognito-idp create-user-pool --pool-name usernametest --username-attributes email
結果が返された。
{
"UserPool": {
"Id": "us-west-2_xxxxxxxxxxx",
"Name": "usernametest",
"Policies": {
"PasswordPolicy": {
"MinimumLength": 8,
"RequireUppercase": true,
"RequireLowercase": true,
"RequireNumbers": true,
"RequireSymbols": true,
"TemporaryPasswordValidityDays": 7
}
},
"DeletionProtection": "INACTIVE",
"LambdaConfig": {},
"LastModifiedDate": "2024-01-25T13:38:33.287000+09:00",
"CreationDate": "2024-01-25T13:38:33.287000+09:00",
"SchemaAttributes": [
{
"Name": "sub",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": false,
"Required": true,
"StringAttributeConstraints": {
"MinLength": "1",
"MaxLength": "2048"
}
},
{
"Name": "name",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "given_name",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "family_name",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "middle_name",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "nickname",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "preferred_username",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "profile",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "picture",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "website",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "email",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "email_verified",
"AttributeDataType": "Boolean",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false
},
{
"Name": "gender",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "birthdate",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "10",
"MaxLength": "10"
}
},
{
"Name": "zoneinfo",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "locale",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "phone_number",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "phone_number_verified",
"AttributeDataType": "Boolean",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false
},
{
"Name": "address",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "updated_at",
"AttributeDataType": "Number",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"NumberAttributeConstraints": {
"MinValue": "0"
}
}
],
"UsernameAttributes": [
"email"
],
"VerificationMessageTemplate": {
"DefaultEmailOption": "CONFIRM_WITH_CODE"
},
"UserAttributeUpdateSettings": {
"AttributesRequireVerificationBeforeUpdate": []
},
"MfaConfiguration": "OFF",
"EstimatedNumberOfUsers": 0,
"EmailConfiguration": {
"EmailSendingAccount": "COGNITO_DEFAULT"
},
"AdminCreateUserConfig": {
"AllowAdminCreateUserOnly": false,
"UnusedAccountValidityDays": 7
},
"Arn": "arn:aws:cognito-idp:us-west-2:966281585925:userpool/us-west-2_ocZLX8XJd",
"AccountRecoverySetting": {
"RecoveryMechanisms": [
{
"Priority": 1,
"Name": "verified_email"
},
{
"Priority": 2,
"Name": "verified_phone_number"
}
]
}
}
}
UsernameAttributesがemailになっている。他に気になる点としては、email属性がMutable: trueになっていることだ。ユーザー名をメールアドレスにしても、email属性とは関係ないらしい。
ユーザーを作成してみる
では、ユーザーを作成してみる。あえてユーザー名をメールアドレスではないものにしてみる。
aws cognito-idp admin-create-user --user-pool-id $USER_POOL_ID --username foo
当然エラーになる。
An error occurred (InvalidParameterException) when calling the AdminCreateUser operation: Username should be an email.
ちゃんと作成してみる。
aws cognito-idp admin-create-user --user-pool-id $USER_POOL_ID --username foo@example.com
結果が返ってきた。
```json
{
"User": {
"Username": "990e8246-8f3b-489d-83fa-665da23bf781",
"Attributes": [
{
"Name": "sub",
"Value": "990e8246-8f3b-489d-83fa-665da23bf781"
},
{
"Name": "email",
"Value": "foo@example.com"
}
],
"UserCreateDate": "2024-01-25T13:42:46.263000+09:00",
"UserLastModifiedDate": "2024-01-25T13:42:46.263000+09:00",
"Enabled": true,
"UserStatus": "FORCE_CHANGE_PASSWORD"
}
}
どうやら、Username属性はメールアドレスではなく、自動生成されたUUIDになるらしい。
見えてきたこと
ここまでで見えてきたこと。
- ユーザープール作成時のパラメータとして、ユーザー名属性とエイリアス属性は排他的である
- つまり、ユーザープールの設定として、ユーザーの認証方式としてユーザー名属性を使うか、エイリアス属性を使うか、どちらかを選択する必要がある
- ユーザーを作成したときに、
--username
のパラメータとして渡した値が、User.Username
になるわけではない- 内部的にはUUIDが自動生成されて割り振られる。こと値は変更できない。
Usernameの扱われ方
AWS CLIを使ってユーザーを操作する際には、--username
を指定する。例えば、ユーザーの情報を取得する場合はこうなる。
aws cognito-idp admin-get-user --user-pool-id $USER_POOL_ID --username foo@example.com
メールアドレスがユーザー名属性と指定されているので、メールアドレスを使うことができる。一方で、内部的なusernameとして発行されたUUIDを使うこともできる。
aws cognito-idp admin-get-user --user-pool-id $USER_POOL_ID --username 990e8246-8f3b-489d-83fa-665da23bf781
これは、どちらも同じ結果を返す。このことから、ユーザープールはユーザー名属性として設定された属性値を、ユーザー名としてみなす、という挙動になっているということがわかる。
ユーザー名属性がemailの場合に、下記のようにメールアドレスを変更できる。
❯ aws cognito-idp admin-update-user-attributes --user-pool-id $USER_POOL_ID --username foo@example.com --user-attributes "Name=email,Value=bar@example.com"
そして、もちろん、情報を取得する場合は、変更後のメールアドレスが使える。
エイリアス属性を使ったユーザープール
エイリアス属性を使ったユーザープールを作成する。
❯ aws cognito-idp create-user-pool --pool-name usernametest --alias-attributes email phone_number preferred_username