Creating, finding and updating users, and moving them in and out in bulk. For roles and permissions see RBAC; for MFA enrolment see MFA.
Assumes Management API credentials are configured — see Configuration.
The basics
alias Auth0Client.Management.User
User.all(%{q: "email:*@example.com"})
#=> {:ok, [%{"user_id" => "auth0|abc123", ...}]}
User.get("auth0|abc123", %{fields: "email,name"})
#=> {:ok, %{"email" => "someone@example.com", "name" => "Someone"}}
User.create("Username-Password-Authentication", %{
email: "someone@example.com",
password: "a-strong-password"
})
User.update("auth0|abc123", %{app_metadata: %{admin: true}})
User.delete("auth0|abc123")
#=> :okFinding a user by email
If you have an address and want the user, use by_email/2 rather than a search:
User.by_email("someone@example.com")
#=> {:ok, [%{"user_id" => "auth0|abc123", ...}]}It is an exact, case-insensitive match, and returns a list because one address can belong to several
identities across connections. User.all/1 would go through the search engine instead, with the caveats
below.
Searching
User.all/1 uses the v3 search engine, the only one Auth0 still supports. It differs from v2 in ways that
return nothing rather than erroring:
.rawsub-fields are gone — query the field directlyconnectionbecameidentities.connection- matching is case-sensitive
- results cap at 1,000 records
For anything larger, run an export rather than paginating.
Password resets
To email the user a reset link, use Auth0Client.Authentication.change_password/3 — see
Logging users in. To generate a link yourself:
Auth0Client.Management.Ticket.password_change(%{user_id: "auth0|abc123"})
#=> {:ok, %{"ticket" => "https://your-tenant.auth0.com/lo/reset?ticket=..."}}Sessions and tokens
From the user's side — everything at once:
User.sessions("auth0|abc123")
User.delete_sessions("auth0|abc123") # signs them out everywhere
User.refresh_tokens("auth0|abc123")
User.delete_refresh_tokens("auth0|abc123")
User.revoke_access("auth0|abc123") # both at onceOr one at a time, using the ids those listings return:
alias Auth0Client.Management.{RefreshToken, Session}
Session.get(session_id)
Session.delete(session_id) # ends the session
Session.revoke(session_id) # ends it AND its refresh tokens
RefreshToken.get(token_id)
RefreshToken.delete(token_id)
RefreshToken.revoke(%{ids: [token_id]}) # in bulk, up to 100delete and revoke differ where it matters
Session.delete/1 ends the session but leaves its refresh tokens alive, so an application holding one
gets a new access token immediately. After a credential compromise, Session.revoke/1 is the call that
actually locks the user out.
RefreshToken.revoke/1 takes an exclusive choice, not a set of filters: ids, or user_id, or
user_id + client_id, or those plus audience. client_id alone is rejected, and ids combines with
nothing.
RefreshToken.all/1 is the same listing as User.refresh_tokens/2 — user_id is required either way —
except that it also filters by client_id.
To revoke a refresh token as its holder rather than as an administrator, with no Management token
involved, use Auth0Client.Authentication.Token.revoke/3 — see Logging users in.
To sign a user out of every application, not just this tenant's,
Auth0Client.Authentication.global_token_revocation/3 is Auth0's Universal Logout endpoint. It authenticates
with a bearer token you supply rather than a management token, and — like everything above — it destroys
sessions and refresh tokens but leaves already-issued access tokens working until they expire.
Consent grants
A grant records that a user consented to an application's scopes. Deleting one makes Auth0 prompt for consent again and invalidates the refresh tokens issued under it.
alias Auth0Client.Management.Grant
Grant.all(user_id: "auth0|abc123")
Grant.delete("cgr_abc123") # one application
Grant.delete_by_user("auth0|abc123") # every application, all at oncedelete_by_user/1 takes the user id as a query parameter rather than a path segment, which is why it is a
separate function.
Bulk import and export
Jobs are asynchronous: they return immediately and do the work in the background, so start one, poll it, then check for errors.
alias Auth0Client.Management.Job
# Export — poll until the job carries a `location` to download from
{:ok, job} = Job.users_exports(%{connection_id: "con_abc123", format: "json"})
{:ok, %{"status" => "completed", "location" => url}} = Job.get(job["id"])
# Import — takes the contents of a JSON file, or a stream for a large one
{:ok, job} = Job.users_imports(File.read!("users.json"), "con_abc123", %{upsert: true})
{:ok, job} = Job.users_imports(File.stream!("users.json"), "con_abc123")Import is the one endpoint Auth0 accepts only as multipart/form-data; the library handles that for you,
including turning upsert: true into the string form Auth0 expects.
Checking the result
Job.errors/1 answers :ok when the import was clean and {:ok, errors} when some records failed —
Auth0 returns 204 in the first case. The success path is the surprising one, so match both:
case Job.errors(job["id"]) do
:ok -> :imported_cleanly
{:ok, errors} -> handle(errors)
end