17

I know others have asked this question.  The previous solutions have not worked.  Using the OAuth JWT flow.

  1.  All Users Can Authorize is selected
  2.  User authorized via https://login.salesforce.com/services/oauth2/authorize?client_id=&redirect_uri=&response_type=code
  3.  OAuth Scopes include
    Access and manage your data (api)
    Perform requests on your behalf at any time (refresh_token, offline_access)

POST to test.salesforce.com OR login.salesforce.com return {"error":"invalid_grant","error_description":"user hasn't approved this consumer"}
Why am I receiving this error?

If I change the aud of my JWT from https://login.salesforce.com to https://XXX.force.com, I receive
{"error":"invalid_grant","error_description":"audience is invalid"} which is the standard error response for an invalid token and is what I would expect.  I take that to mean my certificates are working correctly since I only gives the error when I change audience to an invalid value.

What am I missing? Why am I getting the user hasn't approved this consumer error?

12

From the Salesforce OAuth JWT Flow documentation (hidden):

A JWT OAuth 2.0 bearer assertion request looks at all the previous approvals for the user that include a refresh_token. If matching approvals are found, the values of the approved scopes are combined and an access_token is issued (with "token_type" value "Bearer"). If no previous approvals included a refresh_token, no approved scopes are available, and the request fails as unauthorized.

The previously attempted authorization URL used the web server flow. The server flow does NOT create a refresh token.
Incorrect: https://login.salesforce.com/services/oauth2/authorize?client_id=&redirect_uri=&response_type=code

I created a one-time curl request using the User Agent Flow:
Correct:
https://login.salesforce.com/services/oauth2/authorize?response_type=token&client_id=<your_client_id>&redirect_uri=<your_redirect_uri>

The User Agent Flow request set a refresh_token and everything worked smoothly from there, allowing me to use the JWT Flow for all future requests.

7
  • For either the sub or prn value, make sure you are using a username that exists in that org.
  • For the aud make sure you are using test.salesforce.com for a sandbox environment and login.salesforce.com for production.

The issuer (iss) must be the OAuth client_id or the connected app for which the developer registered their certificate.

String iss = INT_USER_SETTINGS.Consumer_Key__c;

The audience (aud) must be https://login.salesforce.com or https://test.salesforce.com

String aud = getHostname();

The subject (sub) must be the username of the desired Salesforce user. For backward compatibility, you can use principal (prn) instead of subject (sub).

String prn = INT_USER_SETTINGS.Username__c;

The validity (exp) must be the expiration time of the assertion within 5 minutes, expressed as the number of seconds from 1970-01-01T0:0:0Z measured in UTC.

String exp = String.valueOf(System.currentTimeMillis() / 1000);

Construct a JSON Claims Set for the JWT with iss, sub, aud, and exp.

String bodyJson =  JSON.serialize(new Body(iss, prn, aud, exp));
etc..
2

"user hasn't approved this consumer" This is a common error caused when the user doesn't have a prior refresh_token associated with him/her.

The solution is to perform an Autorization grant (Web Server flow or User-Agent Flow) at least once.

I wrote in detail about it; look specifically at step #3 here - https://mannharleen.github.io/2020-03-03-salesforce-jwt/

That should solve the error.

0

{"error":"invalid_grant","error_description":"user hasn't approved this consumer"}

In my case this error occurred because I was supplying an outdated username. If you get this error, please try deleting all variable values for connected app consumer key, username, etc, and fill them one by one again. It could be, that like myself, you are supplying outdated parameter values.

0

Setting Admin approved users are pre-authorized means that you don't need to pre-authenticate, or need a prior refresh_token, so may be a preferred solution rather than going through a manual authenticate step. Don't forget to set a scope though! There's a SF walk-through video on YouTube: https://www.youtube.com/watch?v=c5OZZsVkOKY

-1

We had this problem while trying to access the connected app as a community user. We resolved it with the following steps:

  1. Go to Setup > Manage Connected Apps.
  2. Click on the connected app.
  3. Click Edit Policies.
  4. Set Permitted Users to Admin approved users are pre-authorized. (We had this part as All users may self-authorize but it wasn't working for community users)
  5. Go to the profile you wish to give access.
  6. Click Edit.
  7. In the Connected App Access check the checkbox of your connected app.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.