Open blakelthaus opened 2 years ago
@blakelthaus you don't need to generate jwt on your own, Restforce already provides a JWT middleware for you that generates proper jwt, see: https://github.com/restforce/restforce/blob/main/lib/restforce/middleware/authentication/jwt_bearer.rb
If I understand correctly, the first step is to create the certificate and the private key:
# valid for 10 years, 1024 or 4096 for rsa
openssl req -x509 -newkey rsa:1024 -nodes -keyout sf_key.pem -out sf_cert.pem -sha256 -days 3650
Follow the README at https://github.com/restforce/restforce#jwt-bearer-token , upload the certificate, in your code load the private key:
class SalesforceClient
def jwt_key
@jwt_key ||= open('sf_key.pem') { _1.read.strip }
end
def client
# make sure SALESFORCE_USERNAME, SALESFORCE_CLIENT_ID, SALESFORCE_CLIENT_SECRET variables are set
# in ENV so you can skip them below, restforce will read them
@client ||= Restforce.new(
jwt_key: jwt_key,
instance_url: "FIXME"
)
end
end
README does not describe it in too many details though. Apparently you may need to authorize the app first by opening this URL in the browser:
https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id=<your_client_id>&redirect_uri=https://localhost:3000&scope=api+refresh_token+offline_access
or
https://login.salesforce.com/services/oauth2/authorize?response_type=token&client_id=<your_client_id>&redirect_uri=<your_redirect_uri>
to avoid this error:
Restforce::AuthenticationError: invalid_grant: user hasn't approved this consumer (400)
See: https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_jwt_flow.htm&type=5
This flow uses a certificate to sign the JWT request and doesn’t require explicit user interaction. However, this flow does require prior approval of the client app.
What is absolutely critical for this to work is setting up correct OAuth scopes in Salesforce (Edit Connected App):
Selected OAuth Scopes
Manage user data via APIs (api)
Perform requests at any time (refresh_token, offline_access)
An alternative to the error
Restforce::AuthenticationError: invalid_grant: user hasn't approved this consumer (400)
Is to
Permitted Users
setting Admin approved users are pre-authorized
PR #886 might be having fix for the root cause of it.
Have spent the last couple of days trying to get the restforce client to work to no avail. Included my code below, if I dump out my JWT Token and make an auth request to salesforce with postman with the exact same parameters I get a successful response from the salesforce API with an access_token. Have tried multiple different API versions and variations of passing the token/other params but when calling
SalesforceService.new.test
from irb I always end up with theOpenSSL::PKey::RSAError (Neither PUB key nor PRIV key: nested asn1 error)
Additionally, I have tried just passing a string of the key private key file name to the
jwt_key
param thinking maybe restforce handles the signing but with that I receive a similar errorOpenSSL::PKey::RSAError (Neither PUB key nor PRIV key: not enough data)
Any advice here would be greatly appreciated, at this point thinking I might just have to do a manual integration but would really like to use this client as it makes things much simpler!