Auth0 Home Blog Docs

Ensuring unique username across different connections

username-password-co
hooks
unique-property
user-metadata
username

#1

I do believe Auth0 can be the miracle cure for my pains of user credentials in future apps. However, I have a few teething problems getting to use it how I want.

In short, I want all my users to have a public username property, (it’s a social project).

That’s very easy with the database connection setting. That updates the ‘username’ on the user profile which is checked for uniqueness on any signup using that method.

If then, I have another user log in with a social account, e.g. Facebook, I want to request for them to have a username. Once I have that, I want to update the user profile, but the only place I can do that is in the user_metadata. This then leads the first problem. which is, the check for a unique username via the Auth0 username-password method at sign up only uses the root username, thus ignoring any set in user_metadata, so I could get a conflict.

Therefore, I believe one way to fix this is to use a pre-registration hook, that sets a user_metadata.username property on sign up. But…it should check to see if any other user has that username in the user_metadata already set. An example of the illegal state is below:

e.g. User A signups with password and username ‘IAmUser’…

*{username: 'IAmUser', user_metadata: {username: 'IAmUser'}}*

User B signups with Facebook, middle tier sets the user_metadata to chosen username ‘IBeUser’

*{username: , user_metadata: {username: 'IBeUser'}}*

User C signsups with password and username ‘IBeUser’

*{username: 'IBeUser', user_metadata: {username: 'IBeUser'}}*

User C succeeds by default because Auth0.com process only checks the root username.

I am unsure how, during the pre-registration hook, to search other users metadata for the existing of the proposed username (kinda overriding auth0’s default unique check)

However, what I find strange, is that the root username, will then be irrelevant as the Social vs Database identities would have to use the common user_metadata. Why is it a social account can’t write to the root username property, as this would avoid all this headache!

The other option I am thinking, is to create a database connection account for anyone who logs in with a social media account, assigning them a random password (they can click forget password to reset) and a best guess username (e.g. their fullname concatenated). This would be done in my own middle tier, therefore can ensure unique username etc using the ManagementClient SDK.

Can you please advise on

  1. How to search all users metadata from within a hook, and on a match, raise a conflict exception to send back to the calling auth
  2. which option out of the two above you think is advisable
  3. explain why the username at root level on user profile is tied only database connections (and how does it differ to nickname)?

#2

1. (search all users metadata)

You can treat your hook as a non-interactive client application and assign to it a client identifier and client secret. You would then authorize this non-interactive client application to be able to call the Management API which would mean the hook could now obtain a Management API access token and perform a user search query to check if the username already exists.

In your example you mention that you plan to store this information at the user_metadata level so have in mind that this is directly editable by the end-user themselves. If you plan to have some control over the data (employ unique validations) then you store it at the app_metadata level because end-users can’t edit that directly.

2. (which option)

You’re much better fit to answer this one as you know much more about all the details and requirements. Having said that, my opinion is the following, if users don’t authenticate with username/password credentials then I would try to make the metadata approach work instead of creating a fake account, but each carries their own different implementation costs and other different characteristics so don’t take this as definitive recommendation. If I were you I would even prototype the two options and see if there was any major pain points when associated with your full requirements.

3. (root level user profile properties)

If you take in consideration that Auth0 plays two similar, but nevertheless different roles you’ll see why there’s some distinction for database connections. In a database connection, the identity of the user is verified by the connection itself and the username is an active part of that. With most of the other connections (for example social) the identity of the user is verified by an external identity provider that Auth0 trusts. In essence at the root level you’ll see identity provider attributes which are specific to each provider (in most of them there’s no notion of username). This means for database connection you have username because it’s a core attribute of the associated identity provider (the database) and for social connections and others you’ll see the core attributes of the respective identity provider (which may have no notion of usernames).


#3

Firstly, thank you for your great reply.

The approach to 1 seems going down the microservice rabbit hole! But I do understand the principle stated.

With regards to 3, I think a user would expect if they logged in as ‘IamUserA’, connected facebook, changed username to ‘IamUserB’ then would expect to use the latter with the password authentication method?

That said, I had a discussion with a friend who uses Auth0 in a commercial environment, and convinced me the best approach is to manage the username aspect in my own custom database alongside the Auth0 service which has proven successful.


#4