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:
-
Joe Doe is a Customer User (Customer Community Plus License)
-
Connected App has these scopes: api, web, full, refresh_token, offline_access
-
Permitted users: Admin approved users are
pre-authorized -
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.
Best Answer
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:
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
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):
Hope it helps anyone in the future!