51

I have an authenticated user in AWS Cognito service and want to store his unique identifier in the database. Should I store user's username (it's his phone number) or his "sub" (it's his uid)? All Amazon API functions like AdminGetUser are using "username" parameter, but not sub/uid.

But I also read that article and the author said "Always generate the policy on value of 'sub' claim and not for 'username' because username is reassignable. Sub is UUID for a user which is never reassigned to another user."

So, now I'm hesitating what I have to use as unique user identifier - "username" or "sub"

Thank you.

lexa
  • 955
  • 2
  • 13
  • 18

4 Answers4

37

Update 2021

Both options are possible.

But keep in mind that if a user with the username erlich.bachman delete his account, a new user can use this same username later and your mapping will be wrong...

A username is always required to register a user, and it cannot be changed after a user is created.

However

The username must be unique within a user pool. A username can be reused, but only after it has been deleted and is no longer in use.

The sub as id

You can use the sub as ID and the username as attribute in your database. This will allow you to get a user by his/her username with AdminGetUser. But also to avoid any data loss, as mentioned by @willscripted in comment.

Referencing sub risks data loss and can make it difficult to migrate or recover a userpool. Since sub is globally unique, any restored user data will have new sub values. It will mean re-keying your app database with the new sub keys, whereas if you had used username you could restore your pool as expected. @willscripted

The username as id

If you prefer to use the username directly as id, you can either remove the user from your database when his/her account is deleted or use the "Pre Sign-up" trigger to prevent a user to use a username already in the database.

user108828
  • 1,822
  • 1
  • 14
  • 21
  • 1
    What do you think about using email as an id for the user in database? – Vitaly Zdanevich Sep 28 '17 at 15:32
  • 2
    It's not a good idea since the user can change his/her email. – user108828 Sep 28 '17 at 18:15
  • If the user changed the email on Facebook - it will be automatically changed in user pool if the user used Facebook to login? – Vitaly Zdanevich Sep 29 '17 at 06:05
  • Store the sub: https://stackoverflow.com/a/54331760/3299184 see my answer for details on `adminGetUser` by the sub. – steviesh Jan 23 '19 at 16:40
  • 5
    Referencing `sub` risks data loss and can make it difficult to migrate or recover a userpool. Since `sub` is globally unique, any restored user data will have new `sub` values. It will mean re-keying your app database with the new `sub` keys, whereas if you had used `username` you could restore your pool as expected. – willscripted Dec 22 '20 at 03:31
  • 1
    If it is a preffered way, why AWS Cognito developers didn't make it easy to retrieve users by sub? – Noname May 05 '21 at 13:36
  • @VitalyZdanevich if user used facebook login, email may not even be in the attributes of the user. Depends on attribute mapping settings & fb permissions scope – Lukas Liesis Jul 29 '21 at 13:11
15

Reference username.

  • sub: a globally unique identifier, set by aws
  • subject: a user identifier, set by you

You want a globally unique identifier, but you want to set it yourself.

Why not reference sub?

sub cannot be restored from backup.

As of writting, Cognito does not have a native backup solution. If you mistakenly delete you must have your own backup data. Since sub is not a settable field, your user identities will no longer be associated with their former arbitrary sub values.

Why set subject to a globally unique identifier?

Globally unique identifiers are good practice. Using a predictable, or out-right settable identifier in a security context is the basis for several common attack patterns. See CAPEC-21: Exploitation of Trusted Identifiers and CAPEC-60: Reusing Session IDs.

willscripted
  • 1,438
  • 1
  • 15
  • 25
  • 1
    Why do you start off by mentioning `username` and then advise to use `subject` set by ourselves? – huyz Dec 16 '22 at 11:24
14

One of the current limitations (to this date) of Cognito is listing users, if you save the sub in your own database for identify your users, and later you try to recover information of this saved user from cognito is not possible, due aws doesn't allow filter by sub or custom attributes, so use username for saving an uuid and prefered_username as alias for real username.

In javascript AWS.CognitoIdentityServiceProvider.ListUser, same for others.

user2976753
  • 935
  • 11
  • 24
  • 15
    Update: as of this date, ListUser supports filtering by ```sub```, however the Cognito User Pool console has not been updated to allow you to do so, so it is only available through the API and CLI. – Clinton Chau Sep 14 '18 at 15:46
1

If you only want to store one, the sub is probably the way to go for the reasons you provided.

It depends greatly on your use case, but if you need to use this database to call APIs like your example, keeping track of both/a mapping between the two is a totally valid solution.

Jeff Bailey
  • 5,655
  • 1
  • 22
  • 30