User Pool Attributes in AWS Cognito - Complete Guide

avatar
Borislav Hadzhiev

Last updated: Jan 27, 2024
8 min

banner

# Table of Contents

  1. User Attributes in AWS Cognito
  2. Update Cognito User Attributes

# User Attributes in AWS Cognito

We will learn how to store default and custom User Pool attributes on Cognito Users.

User Pool attributes in AWS Cognito are:

  • standard - the default user attributes you get with every User pool.
  • custom - user attributes specific to your application that are not supported by default.

The default Attributes are: address, birthdate, email, family_name, gender, given_name, locale, middle_name, name, nickname, phone_number, picture, preferred_username, profile, updated_at, website, zoneinfo - docs.

When you want to store a property on a user that isn't included in the default cognito-provided ones, you have to use a custom attribute, e.g. add a boolean isAdmin attribute to your user.

# Initializing the Project

We will clone a GitHub repository that creates a Cognito stack including all the default and some custom attributes we have defined ourselves.

The code for this article is available on GitHub

This stack creates the following resources in your AWS Account:

  • User Pool
  • User Pool Client
  1. Clone the GitHub repository.

  2. Change the directory and install dependencies.

shell
cd aws-cognito-user-attributes && npm install
  1. Deploy the stack.
shell
npm run cdk-create-stack
  1. The stack has been deployed to your default region. You can check the region in the cdk-exports-dev.json file created in the root directory of the project.

  2. Open the AWS console and click on the cognito-user-attributes-dev stack.

# Storing User Attributes in AWS Cognito

We have created a User Pool and a User Pool Client.

  • The User Pool is the directory where you store and manage your users in AWS Cognito. A User Pool allows your users to register and sign in to your application, and allows you to manage their profiles.

  • The User Pool Client is the part of the User Pool that actually enables unauthenticated operations like registering, signing in and the forgotten password functionality. You can't call these operations without an app client ID that you get by creating a User Pool Client.

User Pool > General Settings > Attributes

Click on the cognito-user-attributes-dev User pool in the console and select the Attributes property in the left sidebar:

standard attributes required

When creating a User Pool you can set standard attributes as required. This means that the attributes must be provided when a user registers. Note that you can't change the required attributes after creating a user pool.

We have specified the family name and given name standard attributes as required. We did this using the following code in the infra/constructs/user-pool-construct.ts:

infra/constructs/user-pool-construct.ts
this.userPool = new cognito.UserPool(this, 'userpool', { //... rest standardAttributes: { givenName: { required: true, mutable: true, }, familyName: { required: true, mutable: true, }, }, });

Notice how the attributes are set to both required and mutable. The mutable property specifies whether the value of the attribute can be changed. You can't edit the mutable property after creating the attribute.

In the Attributes tab in the console, scroll down to the "Do you want to add custom attributes?" section:

custom attributes

We have set 4 custom attributes: bio, country, city and isAdmin. Note that you can create new custom attributes after User Pool creation, however, you can't edit the existing ones.

The code defining the custom attributes is located in the infra/constructs/user-pool-construct.ts file again:

infra/constructs/user-pool-construct.ts
this.userPool = new cognito.UserPool(this, 'userpool', { // ... rest customAttributes: { bio: new cognito.StringAttribute({mutable: true}), country: new cognito.StringAttribute({mutable: true}), city: new cognito.StringAttribute({mutable: true}), isAdmin: new cognito.StringAttribute({mutable: true}), }, });

Note that we set the mutable attribute to true again because we want to be able to change these values.

Notice that all of our custom attributes are of type string. You could say, why would isAdmin be of type string, it should be a boolean.

That would make sense, however, the only truly supported type for custom attributes is the string type. If you read the cognito docs they say you can use string or number if you read the cdk docs they say you can use boolean, datetime, number, string.

However, at the time of writing both are wrong and the only truly supported type is string. If you're interested to learn more check out the Custom attributes section of my cognito bugged article.

User Pool > General Settings > App clients

Let's move on to the User Pool Client, click on "App clients" in the sidebar. The User Pool Client is the part of the User Pool that enables unauthenticated operations like register, sign in and the forgotten password flow.

In the User Pool Client, we can set the read and write permissions for our standard and custom attributes.

The section concerning Attributes is "hidden" and a common source of confusion, you have to first click on Show Details.

app client show details

Then you have to scroll to the bottom and click on Set attribute read and write permissions.

The Attributes table will be shown where you can see the read/write permissions for our attributes:

app client show details

Both standard and custom attributes can be marked as readable or writable. An application can only read attributes that are set as readable. If an attribute is not readable it wouldn't be included in the API response.

If an application tries to update an attribute that's not set as writable, you would get a NotAuthorizedException error.

We have set the read attributes in our code in the infra/constructs/user-pool-client-construct.ts file.

infra/constructs/user-pool-client-construct.ts
const clientReadAttributes = new cognito.ClientAttributes() .withStandardAttributes({ givenName: true, familyName: true, email: true, emailVerified: true, address: true, birthdate: true, gender: true, locale: true, middleName: true, fullname: true, nickname: true, phoneNumber: true, phoneNumberVerified: true, profilePicture: true, preferredUsername: true, profilePage: true, timezone: true, lastUpdateTime: true, website: true, }) .withCustomAttributes(...['bio', 'country', 'city', 'isAdmin']);

And the write attributes:

infra/constructs/user-pool-client-construct.ts
const clientWriteAttributes = new cognito.ClientAttributes() .withStandardAttributes({ givenName: true, familyName: true, email: true, // 👇 users can't update their emailVerified attribute emailVerified: false, address: true, birthdate: true, gender: true, locale: true, middleName: true, fullname: true, nickname: true, phoneNumber: true, profilePicture: true, preferredUsername: true, profilePage: true, timezone: true, lastUpdateTime: true, website: true, }) .withCustomAttributes(...['bio', 'country', 'city']);

One difference is the isAdmin property. We don't want users to be able to update this property. Since the property is set as mutable, we can update it using the CLI.

The emailVerified property is also set to false because we don't want users to be able to verify their email without clicking on the verification link.

Another thing to note is that since we set the family name and given name attributes to required in our User Pool, these attributes are always going to be set to writable.

# Testing Cognito User Attributes

Make sure to update the YOUR_USER_POOL_ID placeholder in the command below.

You can find the user pool ID in the cdk-exports-dev.json file in the root directory, or in the General settings tab in the User Pool console.

First, let's create the Cognito user:

shell
aws cognito-idp admin-create-user \ --user-pool-id YOUR_USER_POOL_ID \ --username john@example.com \ --user-attributes Name="given_name",Value="john" \ Name="family_name",Value="smith"

User Pool > General Settings > Users and groups

If you now click in the Users and Groups section of your user pool and refresh the page you will see the user we've created.

user john

If you click on the user you will see that we have successfully initialized the user with the given_name and family_name attribute:

user john details

Let's now update some of the other standard (default) user attributes using the CLI (replace your-user-pool-id):

shell
aws cognito-idp admin-update-user-attributes \ --user-pool-id YOUR_USER_POOL_ID \ --username john@example.com \ --user-attributes Name="gender",Value="m" \ Name="name",Value="john smith"

If you're wondering how I got the names of the default attributes, you can find them all in the docs.

If you were to refresh the Users page and click on your user, you would see the other standard attributes included in the user profile:

user additional default attributes

Let's update the custom attributes now. Note that when working with custom attributes you have to prefix the attribute name with custom:.

Make sure to replace the YOUR_USER_POOL_ID placeholder with your actual user pool id.

shell
aws cognito-idp admin-update-user-attributes \ --user-pool-id YOUR_USER_POOL_ID \ --username john@example.com \ --user-attributes Name="custom:bio",Value="Loves long walks on the beach" \ Name="custom:country",Value="Chile" \ Name="custom:city",Value="Santiago" \ Name="custom:isAdmin",Value="yes"

If you refresh the page of the user with the email john@example.com you will see that our custom attributes have been updated on the user object:

user john custom attributes


# Cleanup

Delete the CDK stack.

shell
npm run cdk-destroy

Note that the default behavior for User Pools provisioned via CDK is for them to be retained after stack deletion. However, I've explicitly set the removal policy of this User pool to DESTROY, so it will get deleted when the stack is deleted.

# Conclusion

We need both default and custom User Pool attributes in order to collect and store user information. Common attributes include shipping address, country, city, etc.

The code for this article is available on GitHub

# Update Cognito User Attributes

User pool attributes in Cognito are of 2 types:

  • standard - the default user attributes you get with every user pool
  • custom - user attributes specific to your application that are not supported by default

This article shows how to update both types.

To update a Cognito user's attributes use the admin-update-user-attributes command, specifying the user-pool-id, username and user-attributes parameters.

Let's look at an example of how to update the standard attributes of a Cognito user:

shell
aws cognito-idp admin-update-user-attributes --user-pool-id YOUR_USER_POOL_ID --username john@example.com --user-attributes Name="gender",Value="m" Name="name",Value="john smith"

update standard user attributes

In the example above, we've set the gender attribute of the user to m and their name attribute to john smith.

The admin-update-user-attributes command enables us to update a Cognito user's attributes, including verifying their email.

The --user-attributes parameter expects space-separated name-value pairs, representing user attributes.

To find a complete list of all standard user attributes visit the docs.

Let's now look at an example of how to update the custom attributes of a cognito user:

shell
aws cognito-idp admin-update-user-attributes --user-pool-id YOUR_USER_POOL_ID --username john@example.com --user-attributes Name="custom:bio",Value="Hello World" Name="custom:country",Value="Chile"

update custom user attributes

In the example above, we've set the user's custom bio attribute to Hello World and their custom country attribute to Chile.

When updating custom user attributes, you must prefix the name of the attribute with custom:.

To verify that the Cognito user's attributes have been updated successfully, run the admin-get-user command.

shell
aws cognito-idp admin-get-user --user-pool-id YOUR_USER_POOL_ID --username john@example.com

verify user attributes updated

The admin-get-user command returns information about the user, including the complete list of the user's attributes.

The output of the command shows that the standard and custom Cognito user attributes have been updated successfully.

I've also written a complete tutorial on how to use AWS Amplify Auth with React.js.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.