Announcements

Help Wizard

Step 1

NEXT STEP

Spotify PKCE Auth Invalid Client Secret

Spotify PKCE Auth Invalid Client Secret

Plan

Premium

Country

Canada

 

Device

Chrome. Macbook Pro 2013

Operating System

Mac OS X Catalina

 

My Question or Issue

 

I am trying to set up my web application to use the Proof Key for Code Exchange. However, when I try try to get the access_token by doing a POST request to https://accounts.spotify.com/api/token, I get the following error

 

error: "invalid_request"

error_description: "Invalid client secret"

 

This message does not make sense to me since the PKCE method does not require a client secret. This is what my javascript code looks like. The code is the authorization_code from the redirect callback and the codeVerifier is used for generating the challenge as described in the docs.

 

 

 

const fetchUrl = "https://accounts.spotify.com/api/token";
  const fetchBody = {
    client_id: process.env.SPOTIFY_CLIENT_ID,
    grant_type: "authorization_code",
    code: code,
    redirect_uri: process.env.BASE_URL + "/spotify-callback",
    code_verifier: codeVerifier,
  };


  const searchParams = Object.keys(fetchBody)
    .map((key) => {
      return encodeURIComponent(key) + "=" + encodeURIComponent(fetchBody[key]);
    })
    .join("&");

  const response = await fetch(fetchUrl, {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    body: searchParams,
  });

 

 

 

Please could I get some advice on what I'm doing wrong? I have read and reread the documentation several times but I cannot figure it out.

 

More info

For calculating the sha256: https://www.npmjs.com/package/js-sha256 

For performing base64Url encoding: https://www.npmjs.com/package/base64url

For random string for code verifier: https://www.npmjs.com/package/crypto-random-string

Reply
5 Replies

I just got a proof-of-concept for PKCE running on my local machine.  I'm using Axios, but the code's almost identical to yours.  I don't think you want the parameters sent in "body".  (Yes, I know that the documentation makes it seem that you must do this.)

 

My Axios call is like this:

 

const postConfig = {
   headers: {
      'content-type': 'application/x-www-form-urlencoded',
   },
};
return await instance.post(path, qs.stringify(parameters), postConfig)
   .catch(() => ({offline: true}));

 

Notice that the parameters are sent in the path.  

 

My code that calls this looks like this:

 

const parameters = {
   client_id: use.global.clientId,
   grant_type: 'authorization_code',
   code: local.getItem('code'),
   redirect_uri: getRedirectUri() + location.pathname,
   code_verifier: local.getItem('codeVerifier'),
};
return api.call('POST', 'https://accounts.spotify.com/api/token', parameters)
   .then(response => {
      const {access_token, expires_in, refresh_token} = response.data;
      if (access_token)
         setAccessToken(access_token);
      if (expires_in)
         setAccessTokenExpiresOn((Math.floor(Date.now() / 1000)) + expires_in);
      if (refresh_token)
         setRefreshToken(refresh_token);
   });

Make sure that in your initial redirect request(step 2.), the code_challenge and code_challenge_method are specified correctly, otherwise the endpoint will assume you are trying to do the "regular" Authorization work flow. This is why it is expecting a client_secret.

Hello there! Have you succeeded solving the problem? The same issue happens to me now and I have no idea how to fix it. I double checked my code-verifier and code-challenge generation routines and body of request but still the error occurs. One thing I noticed however is that the code retrieved on the previous step can be successfully exchanged for an access token if I pass Authorization header just like in the authorization code flow and I'm not really sure if that is correct.

Hey! I just found out a way to solve this, at least it worked for me. Try resetting the client_secret through the dashboard. Probably, what could be happening is that the authorization API server thinks your are in the process of interchanging the authorization code for a pair of tokens, as in the standard authorization code flow, and by resetting the client_secret you invalidate any ongoing validation.

In order to try out the PKCE authorization flow I created a little example repository.
Don't hesitate to try it out and compare with your project:

https://github.com/tobika/spotify-auth-PKCE-example

Suggested posts