I am using PKCE ( proof key for code exchange ) flow in salesforce and trying to authenticate but getting below error

"error": "invalid_grant",
"error_description": "invalid code verifier"

Step 1 - Authorization code URL Below is the URL for the authorization code URL

https://login.salesforce.com/services/oauth2/authorize?client_id=3MVG97quAmFZJfVxm0NIj75FamFbSpgt8VgBNTKCprAD2ThUXvs8LfUwzunQZkdGzabnxu0w6ckZeX8rlGvG6&redirect_uri=https://www.sfdcpanther.com/&response_type=code&scope=full refresh_token&state=redirect_uri=https://www.sfdcpanther.com/&code_challenge=23cc1e54c8e06b1f8d69724fdd1fca1d5b0f38313c4b3bf9f1ca4cd7865b5816

I am using "23cc1e54c8e06b1f8d69724fdd1fca1d5b0f38313c4b3bf9f1ca4cd7865b5816" as a code challenge which is SHA256 of 73t874jdshfbhj value.

Step 2 - Access Token Code.

I am using the below body for the access token request.


I have tried 23cc1e54c8e06b1f8d69724fdd1fca1d5b0f38313c4b3bf9f1ca4cd7865b5816 and 73t874jdshfbhj both value for the code_verifier.

Please let me know if you have any suggestions for the same.

Edit 1

I also have tried to pass the code_challenge by base64Url Encode and still not working.

Edit 2

After some research and help from Mohit, I was able to make it work. Adding the solution for all those who are looking to implement the PKCE flow for salesforce.

I got huge help from This link.

The salesforce document is missing one parameter which is code_challenge_method=S256 in the authorization URL.

Here is the full URL for the authorization request.


Once you will hit the above URL in your browser and after providing the consent you will be able to see the code and use the same code in the below request.


And you will be able to see the access token with additional details.

The doc says that the value for code_challenge must be base64Url-encode of code_verifer and salesforce does not provide a direct way to base64Url-encode so you can use the below code for the same.

public class PKCEOAuthHelper {

public static void printDetails(){
    String code_verifier  = generateRandomString(34);
    Blob sha256           = Crypto.generateDigest('SHA-256', Blob.valueOf(code_verifier));
    String code_challenge = base64URLencode(sha256);
    System.debug('**** code_verifier **** \n  '+code_verifier);
    System.debug('**** code_challenge **** \n '+code_challenge);

private static String base64URLencode(Blob input){
    String output = encodingUtil.base64Encode(input);
    output = output.replace('+', '-');
    output = output.replace('/', '_');
    while ( output.endsWith('=')){
        output = output.subString(0,output.length()-1);
    return output;

private static String generateRandomString(Integer len) {
    final String chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
    String randStr = '';
    while (randStr.length() < len) {
        Integer idx = Math.mod(Math.abs(Crypto.getRandomInteger()), chars.length());
        randStr += chars.substring(idx, idx+1);
    return randStr; 

Hope this will be helpful for the people who are willing to implement PKCE flow.

Thanks & Regards,

Amit Singh

1 Answer 1


As per the docs it is clearly stated that your code_challenge value should be base64url encoded and also the code verifier should be 128 bytes random string!

Also looks like the docs have missed mentioning about parameter code_challenge_method=S256 in the authorization request. This needs to be corrected!

Try to base64 URL encode your code_challenge in the auth flow!

Try the below tool to make sure you have matching values when you write your algorithm


  • Thanks for replying. I have tried the same but that is not working.
    – Amit Singh
    Jan 1, 2021 at 13:10
  • 1
    Thank you, Mohit for all the help that you did. I was able to make it work.
    – Amit Singh
    Jan 1, 2021 at 15:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .