I use auth0.js in angular application.
The new auth0.WebAuth method work well but when I want use new auth0.Management method I receive an 401 Unauthorized response.
In detail, after create new WebAuth, I use Parse method of WebAuth to get access Token and Id token.
When I use my function management I have an error in dev console :
PATCH https://xxxx.eu.auth0.com/api/v2/users/auth0|5ad8b180b09f330xxxxxx
private setSession(authResult): void {
// Set the time that the access token will expire at
const expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
localStorage.setItem(‘access_token’, authResult.accessToken);
localStorage.setItem(‘id_token’, authResult.idToken);
localStorage.setItem(‘expires_at’, expiresAt);
}
private get management() {
return new auth0.Management({
domain: this.auth0Config.domain,
token: this.getIdToken()
});
}
@mike31 when you are calling the management API you need to use the access_token. It seems from this code you are using the id_token. Also, to get an access_token from Auth0 that is capable of using with the Management API you need to trigger authentication with the audience for the Management API.
@mike31, it seems you are using the 32 character opaque token for an access token. When you are authenticating users are you sending the audience https://{your-tenant}.auth0.com/api/v2/ with this? If so you should have received a JWT access_token instead. I suspect this error is failing because the access_token is not a JWT.
Can you share the code you are using to trigger authentication to fetch tokens? Particularly, I would like to see how the SDK, Lock, or whatever you are using for trigger auth is setup.
Ok after tested, I added in auth0.WebAuth this line :
audience: ‘https://’ + this.auth0Config.domain + ‘/api/v2/’,
And my access token is now in jwt format but I have now a 403 forbidden error when I use new auth0.Management…
The email and paswword are good and the user is not blocked
In access token, the scope is “scope”: “openid profile email” and I have “aud”:
[
“https://[mydomain].eu.auth0.com/api/v2/”,
“https://[mydomain].eu.auth0.com/userinfo”
],
@Mike31 nice work so far. I think the last piece you need is to specify the scopes required to call the endpoint. In your example you are calling the update user endpoint. According to the API explorer docs (Auth0 Management API v2) you need to request the update:users scope. This will inform the Auth0 to specify the authorization policy for the JWT/access_token.
@mike31, I don’t think you actually need update:users_app_metadata, but I am curious… can you share the decoded body of your JWT? Also, are you still getting the same error?
@mike31 the access_token is still missing the necessary scope. If you look at the scope claim you have only openid profile email. It is missing the user scopes. You mentioned you had this webauth configured as so:
scope: ‘openid profile roles user_id name email update:users update:users_app_metadata’,
Any chance you have a rule or something filtering out scopes? From what I can tell your JWT is not being issued with the necessary scopes. Since you are doing web auth can you capture the call to /authorize endpoint? This will have quite a few get params. I want to make sure those params are being sent to authorize. Then also, can you let me know if any rules might be modifying the inbound scopes?
@sgmeyer You are right , the scope is not good.
Yes I added update:users update:users_app_metadata in webauth but the access token returned contain only openid profile email (the scope standard of v9).
The /autorize (the scope seems good) :
GET https://[myDomain].eu.auth0.com/authorize?client_id=VhguTED3M5I0iaFwYY0RqXFrcsEpl0Vu&response_type=token%20id_token&redirect_uri=http%3A%2F%2F[myDomain].local%3A4200&scope=openid%20profile%20roles%20user_id%20name%20email%20update%3Ausers%20update%3Ausers_app_metadata&audience=https%3A%2F%2F[myDomain].eu.auth0.com%2Fapi%2Fv2%2F&state=OBQk_gz1oabZgCbb~bjfPUnps6IAunlE&nonce=nwmkLFU-CBA~v9I0-ELqHpBHdwCDlH5o&auth0Client=eyJuYW1lIjoiYXV0aDAuanMiLCJ2ZXJzaW9uIjoiOS41LjAifQ%3D%3D
For autorize method I just call this function :
public login() {
this.webAuth.authorize();
};
I try to add scope update:users in this function but I have still the same scope in access Token
I use 2 rules but which have no impact on scope (I think)
The first connect and update to couchDB to add some informations ans update app_metadata to add couchDB informations.
the second is used to pass custom claims in app_metadata:
function (user, context, callback) {
const namespace = ‘http://[My local domain]:4200/’;
context.idToken = context.idToken || {};
context.idToken[namespace + ‘app_metadata’] = user.app_metadata;
context.idToken[namespace + ‘user_metadata’] = user.user_metadata;
callback(null, user, context);
}
I think I must have a bad parameters in my Tenant, I don’t know where …
The specification only defines scopes for the user_info endpoint. These do not need to be namespaced in the same way as the specification requires claims. Since these scopes will be stored as part of the value of the scope claim. I actually think Auth0 might be skimming these scopes automatically as a measure from issuing a token to manage on behalf of a user.
I have to play around, but it might be required to manually add these scopes to the scope claim.
Ok here is what I’ve found. There is a scope called update:current_user_metadata is the only thing Auth0 will permit a user to have scope access to. The reason for this is that is the only property on the profile a user can update directly. You should be careful to allow a user to directly update a profile considering those details could be used to make authorization details.
So unless you want to patch information that isn’t in user_metadata you will need to build a proxy (if you will) that your application can talk to. Then that proxy would, via client_credentials, get its own token to update a user. This prevents the user from having a token that could update sensitive information used in rules to determine what the user is and is not allowed to do.
Oh perfect !! thank you Shawn
I added in scope update:current_user_metadata and I can see it in access_token.
The profil update work fine now !!
Just when you said “those details could be used to make authorization details” , if a user change his email , it could be an impact with authentification ?? the token will be expired ?
Just when you said “those details could be used to make authorization details” , if a user change his email , it could be an impact with authentication ?? the token will be expired ?
The token is stateless and will not expire if profile data changes. Let’s say we had a rule that would allow a scope to be added if the user.roles array contained admin. If we issued a token to a user that allowed them to update:users we effectively have given the user a token that has enough power to change their authorization policy. This is not desirable. By design user.user_metadata is allowed to be editable by the user. Any data in there should not influence authorization decisions. In other words we don’t want the user to be able to define their own authorization policies.
There is a scope called update:current_user_metadata
Thank you, @sgmeyer! Right after I had posted my question I was wondering if update:users would allow updates to any user, not just the current one - but update:current_user_metadata solves that