2

I'm implementing a JWT Bearer Token within Salesforce (Apex) so my customers can passwordlessly login to a community. Not sure if it is a good practice, but I done some research and saw some use cases like this.

For the JWT Flow I am using the following code (followed this doc):

String token_endpoint = 'https://community-domain.cs101.force.com' + '/services/oauth2/token';
Auth.JWT jwt = new Auth.JWT();
jwt.setIss('3MVG9K...Hhe');
jwt.setSub('joe.doe@community-domain.com');
jwt.setAud('https://community-domain.cs101.force.com');

Auth.JWS jws = new Auth.JWS(jwt, 'Cert_Unique_Id');

Auth.JWTBearerTokenExchange bearer = new Auth.JWTBearerTokenExchange(token_endpoint, jws);
System.debug(bearer);

String accessToken = bearer.getAccessToken();

Considerations that may be imporatant:

  1. Joe Doe is a Customer User (Customer Community Plus License)

  2. Connected App has these scopes: api, web, full, refresh_token, offline_access

  3. Permitted users: Admin approved users are pre-authorized

  4. Working on a Sandbox

When I execute this code on anonymous console, I get:

Auth.JWTBearerTokenExchange.JWTBearerTokenExchangeException: Error 400: {"error":"invalid_grant","error_description":"authentication failure"}

And in the user login history I get "Status: Failed: Invalid Token".

I googled around a lot but I didn't find anyone having the exact same thing.

Has anyone gone through the same problem?

I tried using http://mydomain.my.salesforce.com as token_endpoint and http://test.salesforce.com as audience (on setAud). It works but it doesn't actually gives me access to community, only to Salesforce itself.

1

I ended up finding what was causing the error. In the doc that I mentioned in my question they were suggesting the use of https://community.force.com/customers as the token endpoint.

But in Configure Authentication Flows with OAuth (for Communities) doc they have it (kind of) better explained:

For example, to authenticate a user using an authorize URL like the following:

https://login.salesforce.com/services/oauth2/authorize?​response_type=token&client_id=your_app_id&redirect_uri=your_redirect_uri

Replace the login.salesforce.com host name with the full path to the community URL:

https://acme.force.com/customers/services/oauth2/authorize?​response_type=token&client_id=your_app_id&redirect_uri=your_redirect_uri

Some people may understand right away that full path means really the full path to the community, that in my case is https://community-domain.cs101.force.com/MyCustomerCommunity. As I was focusing on the example they are giving, I wasn't considering that customers in their case would be MyCustomerCommunity in mine.

Anyway, the solution was to replace customers by my community name, that is MyCustomerCommunity, turning token_endpoint and audience into

String token_endpoint = 'https://community-domain.cs101.force.com/MyCustomerCommunity' + '/services/oauth2/token';
// ...
jwt.setAud('https://community-domain.cs101.force.com/MyCustomerCommunity');

That way I was able to get an access token and even use it as session id (sid) in frontdoor.jsp in my community (what I also thought that wouldn't be possible as I didn't find it documented anywhere):

https://community-domain.cs101.force.com/MyCustomerCommunity/secur/frontdoor.jsp?sid=<token>

Hope it helps anyone in the future!

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.