As a bit of background, I’m introducing Auth0 for our existing web application built using ASP.NET MVC 5, and therefore switching to using a hosted page / Universal Login for logins and signup. We are using the Auth0.net OWIN middleware. Our existing system uses GUIDs (UUIDs) for our user ID, yet Auth0 uses a different format (hexadecimal string) by default.
We need the ability to efficiently query Auth0 by our system’s user ID (GUID), and I had originally considered storing this ID in the app_metadata field. Unfortunately, Auth0 no longer allows querying users by properties in the app_metadata field following some prior incident at Auth0.
Given that our preference is not to change all our IDs in the rest of the application, how can we coerce the storage of user IDs in our preferred format in the user_id field via auth0.js (which is what our customised hosted page uses) or any step in the Auth0 pipeline from there?
We can do this via the Management API (POST to /api/v2/users), though I’m aware that the Management API is designed to be run from our controlled environment instead of anything client-side that can be abused.
I considered including the user ID in the script that calls the Authentication API via auth0.js, though for similar reasons, I do not want to have the GUID generated in script running on the client.
I considered writing a rule to set this ID, though I understand that the rules pipeline only runs after the user record has been created and stored (not before) - therefore the user_id cannot be changed.
Please let me know how we can use a GUID as our user_id. Also, how can we control the user_id when migrating existing users from our existing SQL database when each given user logs in after we go live with Auth0 integration? Many thanks.
You can’t specify the user_id in the public signup endpoint (the one used by Lock/Auth0.js). As you said, you can do so using the Management API v2 POST to /api/v2/users to provide an user_id, but you must do so from a backend server. Nothing prevents you from building a public signup endpoint on your side (e.g. https://yourapp.com/users/signup) that talks to the management API v2 to create the user. You can then make a request to that endpoint from the Universal Login page (but you won’t be able to use Lock, though).
Having said that, Auth0 lets you search by the user’s app_metadata or user_metadata fields, take a look at Searchable fields in Search v3. So a search like this is valid:
Encoded in the query string, together with the search_engine=v3 parameter, you’d have something like this:
GET {your_auth0_domain}/api/v2/users?q=app_metadata.internal_id%3D%2275bcb4ff-bab5-46ad-9258-351f81e193b0%22&search_engine=v3
Not sure, however, what’s the relationship between the users in the existing system and new users. Will you be using an Auth0 Custom DB to authenticate users with that database? If so, the custom DB script lets you assign any user_id directly in the returned profile.
If using Import Mode = ON, or if using a regular Auth0 DB (not custom), you can use the pre-user registration hook to add your internal id (if you have it available somehow at this point).
Thanks for that … I had no idea we could specify the user_id during user creation!
Regarding metadata search, on this page there’s a note that says new tenants cannot search metadata. Is that not correct? Or is there some context missing there?
That message comes from the Search v2 documentation page, but Search v3 can search metadata fields (except wildcards and ranges). I will add a callout in that v2 warning message pointing to Search v3 in order to make things less confusing.
As for user ids, the general recommendation is to architect your systems so that the user_id is an obscure string whenever possible, so that it doesn’t have any meaning at all (not even a match to other system).
Thank you for that Nicolas - especially concerning the ability to search by fields in app_metadata in Searchv3.
I have since refactored our solution to use string-based user IDs instead of GUIDs, and can confirm that Search v3 works when calling the Management API from code (using the Auth0.ManagementApi NuGet package for .NET).
Going forward, our system will be fine for newly-created users to have whatever ID Auth0 generates. I’ll raise a separate question regarding migration of existing user records.
In the meantime, is there a concise Lucene syntax for querying multiple records, in a similar manner to SQL’s IN(…) clause? E.g. app_metadata.internal_id: in("75bcb4ff-bab5-46ad-9258-351f81e193b0", "6ea1b1db-7947-4777-9e60-0dd99d7076f6", "b4aa5428-c9a5-4437-8205-493a1ae506fe", "90eb436e-9420-48b7-ab68-c78a79e7476b")
instead of: app_metadata.internal_id:"75bcb4ff-bab5-46ad-9258-351f81e193b0" OR app_metadata.internal_id:"6ea1b1db-7947-4777-9e60-0dd99d7076f6" OR app_metadata.internal_id:"b4aa5428-c9a5-4437-8205-493a1ae506fe" OR app_metadata.internal_id:"90eb436e-9420-48b7-ab68-c78a79e7476b"