<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Unable to make Authorization Code with PKCE work (C#) in Spotify for Developers</title>
    <link>https://community.spotify.com/t5/Spotify-for-Developers/Unable-to-make-Authorization-Code-with-PKCE-work-C/m-p/5088063#M1686</link>
    <description>&lt;P&gt;I am trying to implement the authorization code with PKCE flow for authenticating with the spotify API. I know there are libraries out there for this, but I really want to implement it myself. The flow I am talking about is this:&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow-with-proof-key-for-code-exchange-pkce" target="_blank" rel="nofollow noopener noreferrer"&gt;https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow-with-proof-key-for-code-exchange-pkce&lt;/A&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;I am able to craft the link to redirect the user to the consent page and get a hold of the authorization code. However, when I try to exchange this code for tokens, I get a 400 Bad Request with the message "invalid client_secret". This leads me to believe that Spotify assumes I am trying to use the regular Authorization Code flow, as the client secret is not a part of the PKCE flow at all. I suspect I am encoding the code_verifier or the code_challenge wrong. I found this answer on SO (&lt;A href="https://stackoverflow.com/questions/59911194/how-to-calculate-pckes-code-verifier/59913241#59913241" target="_blank" rel="noopener"&gt;How to calculate PCKE's code_verifier?&lt;/A&gt;) and translated it to C#, yielding identical results for the Base64 encoded hash, but it still doesn't work.&lt;/P&gt;&lt;P&gt;My code for generating the code_verifier and code_challenge is below, as well as the code making the request to exchange the code.&lt;/P&gt;&lt;P&gt;CodeVerifier:&lt;/P&gt;&lt;PRE&gt;&lt;SPAN class=""&gt;&lt;SPAN class=""&gt;private&lt;/SPAN&gt; &lt;SPAN class=""&gt;string&lt;/SPAN&gt; &lt;SPAN class=""&gt;GenerateNonce&lt;/SPAN&gt;()&lt;/SPAN&gt;
{
    &lt;SPAN class=""&gt;const&lt;/SPAN&gt; &lt;SPAN class=""&gt;string&lt;/SPAN&gt; chars = &lt;SPAN class=""&gt;"abcdefghijklmnopqrstuvwxyz123456789"&lt;/SPAN&gt;;
    &lt;SPAN class=""&gt;var&lt;/SPAN&gt; random = &lt;SPAN class=""&gt;new&lt;/SPAN&gt; Random();
    &lt;SPAN class=""&gt;var&lt;/SPAN&gt; nonce = &lt;SPAN class=""&gt;new&lt;/SPAN&gt; &lt;SPAN class=""&gt;char&lt;/SPAN&gt;[&lt;SPAN class=""&gt;100&lt;/SPAN&gt;];
    &lt;SPAN class=""&gt;for&lt;/SPAN&gt; (&lt;SPAN class=""&gt;int&lt;/SPAN&gt; i = &lt;SPAN class=""&gt;0&lt;/SPAN&gt;; i &amp;lt; nonce.Length; i++)
    {
        nonce[i] = chars[random.Next(chars.Length)];
    }
    &lt;SPAN class=""&gt;return&lt;/SPAN&gt; &lt;SPAN class=""&gt;new&lt;/SPAN&gt; &lt;SPAN class=""&gt;string&lt;/SPAN&gt;(nonce);
}&lt;/PRE&gt;&lt;P&gt;CodeChallenge:&lt;/P&gt;&lt;PRE&gt;    &lt;SPAN class=""&gt;&lt;SPAN class=""&gt;private&lt;/SPAN&gt; &lt;SPAN class=""&gt;string&lt;/SPAN&gt; &lt;SPAN class=""&gt;GenerateCodeChallenge&lt;/SPAN&gt;(&lt;SPAN class=""&gt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt; codeVerifier&lt;/SPAN&gt;)&lt;/SPAN&gt;
    {
        &lt;SPAN class=""&gt;using&lt;/SPAN&gt; &lt;SPAN class=""&gt;var&lt;/SPAN&gt; sha256 = SHA256.Create();
        &lt;SPAN class=""&gt;var&lt;/SPAN&gt; hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
        &lt;SPAN class=""&gt;return&lt;/SPAN&gt; Convert.ToBase64String(hash).Replace(&lt;SPAN class=""&gt;"+/"&lt;/SPAN&gt;, &lt;SPAN class=""&gt;"-_"&lt;/SPAN&gt;).Replace(&lt;SPAN class=""&gt;"="&lt;/SPAN&gt;, &lt;SPAN class=""&gt;""&lt;/SPAN&gt;);
    }&lt;/PRE&gt;&lt;P&gt;Exchange token:&lt;/P&gt;&lt;PRE&gt;        &lt;SPAN class=""&gt;var&lt;/SPAN&gt; parameters = &lt;SPAN class=""&gt;new&lt;/SPAN&gt; List&amp;lt;KeyValuePair&amp;lt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt;, &lt;SPAN class=""&gt;string&lt;/SPAN&gt;&amp;gt;&amp;gt;
        {
            &lt;SPAN class=""&gt;new&lt;/SPAN&gt; KeyValuePair&amp;lt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt;, &lt;SPAN class=""&gt;string&lt;/SPAN&gt;&amp;gt;(&lt;SPAN class=""&gt;"client_id"&lt;/SPAN&gt;, ClientId ),
            &lt;SPAN class=""&gt;new&lt;/SPAN&gt; KeyValuePair&amp;lt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt;, &lt;SPAN class=""&gt;string&lt;/SPAN&gt;&amp;gt;(&lt;SPAN class=""&gt;"grant_type"&lt;/SPAN&gt;, &lt;SPAN class=""&gt;"authorization_code"&lt;/SPAN&gt;),
            &lt;SPAN class=""&gt;new&lt;/SPAN&gt; KeyValuePair&amp;lt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt;, &lt;SPAN class=""&gt;string&lt;/SPAN&gt;&amp;gt;(&lt;SPAN class=""&gt;"code"&lt;/SPAN&gt;, authCode),
            &lt;SPAN class=""&gt;new&lt;/SPAN&gt; KeyValuePair&amp;lt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt;, &lt;SPAN class=""&gt;string&lt;/SPAN&gt;&amp;gt;(&lt;SPAN class=""&gt;"redirect_uri"&lt;/SPAN&gt;, &lt;SPAN class=""&gt;"http://localhost:5000"&lt;/SPAN&gt;),
            &lt;SPAN class=""&gt;new&lt;/SPAN&gt; KeyValuePair&amp;lt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt;, &lt;SPAN class=""&gt;string&lt;/SPAN&gt;&amp;gt;(&lt;SPAN class=""&gt;"code_verifier"&lt;/SPAN&gt;, codeVerifier)
        };

        &lt;SPAN class=""&gt;var&lt;/SPAN&gt; content = &lt;SPAN class=""&gt;new&lt;/SPAN&gt; FormUrlEncodedContent(parameters );
        &lt;SPAN class=""&gt;var&lt;/SPAN&gt; response = &lt;SPAN class=""&gt;await&lt;/SPAN&gt; HttpClient.PostAsync(&lt;SPAN class=""&gt;$"https://accounts.spotify.com/api/token"&lt;/SPAN&gt;, content);&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Mon, 07 Dec 2020 09:05:15 GMT</pubDate>
    <dc:creator>clawcastle</dc:creator>
    <dc:date>2020-12-07T09:05:15Z</dc:date>
    <item>
      <title>Unable to make Authorization Code with PKCE work (C#)</title>
      <link>https://community.spotify.com/t5/Spotify-for-Developers/Unable-to-make-Authorization-Code-with-PKCE-work-C/m-p/5088063#M1686</link>
      <description>&lt;P&gt;I am trying to implement the authorization code with PKCE flow for authenticating with the spotify API. I know there are libraries out there for this, but I really want to implement it myself. The flow I am talking about is this:&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow-with-proof-key-for-code-exchange-pkce" target="_blank" rel="nofollow noopener noreferrer"&gt;https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow-with-proof-key-for-code-exchange-pkce&lt;/A&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;I am able to craft the link to redirect the user to the consent page and get a hold of the authorization code. However, when I try to exchange this code for tokens, I get a 400 Bad Request with the message "invalid client_secret". This leads me to believe that Spotify assumes I am trying to use the regular Authorization Code flow, as the client secret is not a part of the PKCE flow at all. I suspect I am encoding the code_verifier or the code_challenge wrong. I found this answer on SO (&lt;A href="https://stackoverflow.com/questions/59911194/how-to-calculate-pckes-code-verifier/59913241#59913241" target="_blank" rel="noopener"&gt;How to calculate PCKE's code_verifier?&lt;/A&gt;) and translated it to C#, yielding identical results for the Base64 encoded hash, but it still doesn't work.&lt;/P&gt;&lt;P&gt;My code for generating the code_verifier and code_challenge is below, as well as the code making the request to exchange the code.&lt;/P&gt;&lt;P&gt;CodeVerifier:&lt;/P&gt;&lt;PRE&gt;&lt;SPAN class=""&gt;&lt;SPAN class=""&gt;private&lt;/SPAN&gt; &lt;SPAN class=""&gt;string&lt;/SPAN&gt; &lt;SPAN class=""&gt;GenerateNonce&lt;/SPAN&gt;()&lt;/SPAN&gt;
{
    &lt;SPAN class=""&gt;const&lt;/SPAN&gt; &lt;SPAN class=""&gt;string&lt;/SPAN&gt; chars = &lt;SPAN class=""&gt;"abcdefghijklmnopqrstuvwxyz123456789"&lt;/SPAN&gt;;
    &lt;SPAN class=""&gt;var&lt;/SPAN&gt; random = &lt;SPAN class=""&gt;new&lt;/SPAN&gt; Random();
    &lt;SPAN class=""&gt;var&lt;/SPAN&gt; nonce = &lt;SPAN class=""&gt;new&lt;/SPAN&gt; &lt;SPAN class=""&gt;char&lt;/SPAN&gt;[&lt;SPAN class=""&gt;100&lt;/SPAN&gt;];
    &lt;SPAN class=""&gt;for&lt;/SPAN&gt; (&lt;SPAN class=""&gt;int&lt;/SPAN&gt; i = &lt;SPAN class=""&gt;0&lt;/SPAN&gt;; i &amp;lt; nonce.Length; i++)
    {
        nonce[i] = chars[random.Next(chars.Length)];
    }
    &lt;SPAN class=""&gt;return&lt;/SPAN&gt; &lt;SPAN class=""&gt;new&lt;/SPAN&gt; &lt;SPAN class=""&gt;string&lt;/SPAN&gt;(nonce);
}&lt;/PRE&gt;&lt;P&gt;CodeChallenge:&lt;/P&gt;&lt;PRE&gt;    &lt;SPAN class=""&gt;&lt;SPAN class=""&gt;private&lt;/SPAN&gt; &lt;SPAN class=""&gt;string&lt;/SPAN&gt; &lt;SPAN class=""&gt;GenerateCodeChallenge&lt;/SPAN&gt;(&lt;SPAN class=""&gt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt; codeVerifier&lt;/SPAN&gt;)&lt;/SPAN&gt;
    {
        &lt;SPAN class=""&gt;using&lt;/SPAN&gt; &lt;SPAN class=""&gt;var&lt;/SPAN&gt; sha256 = SHA256.Create();
        &lt;SPAN class=""&gt;var&lt;/SPAN&gt; hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
        &lt;SPAN class=""&gt;return&lt;/SPAN&gt; Convert.ToBase64String(hash).Replace(&lt;SPAN class=""&gt;"+/"&lt;/SPAN&gt;, &lt;SPAN class=""&gt;"-_"&lt;/SPAN&gt;).Replace(&lt;SPAN class=""&gt;"="&lt;/SPAN&gt;, &lt;SPAN class=""&gt;""&lt;/SPAN&gt;);
    }&lt;/PRE&gt;&lt;P&gt;Exchange token:&lt;/P&gt;&lt;PRE&gt;        &lt;SPAN class=""&gt;var&lt;/SPAN&gt; parameters = &lt;SPAN class=""&gt;new&lt;/SPAN&gt; List&amp;lt;KeyValuePair&amp;lt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt;, &lt;SPAN class=""&gt;string&lt;/SPAN&gt;&amp;gt;&amp;gt;
        {
            &lt;SPAN class=""&gt;new&lt;/SPAN&gt; KeyValuePair&amp;lt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt;, &lt;SPAN class=""&gt;string&lt;/SPAN&gt;&amp;gt;(&lt;SPAN class=""&gt;"client_id"&lt;/SPAN&gt;, ClientId ),
            &lt;SPAN class=""&gt;new&lt;/SPAN&gt; KeyValuePair&amp;lt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt;, &lt;SPAN class=""&gt;string&lt;/SPAN&gt;&amp;gt;(&lt;SPAN class=""&gt;"grant_type"&lt;/SPAN&gt;, &lt;SPAN class=""&gt;"authorization_code"&lt;/SPAN&gt;),
            &lt;SPAN class=""&gt;new&lt;/SPAN&gt; KeyValuePair&amp;lt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt;, &lt;SPAN class=""&gt;string&lt;/SPAN&gt;&amp;gt;(&lt;SPAN class=""&gt;"code"&lt;/SPAN&gt;, authCode),
            &lt;SPAN class=""&gt;new&lt;/SPAN&gt; KeyValuePair&amp;lt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt;, &lt;SPAN class=""&gt;string&lt;/SPAN&gt;&amp;gt;(&lt;SPAN class=""&gt;"redirect_uri"&lt;/SPAN&gt;, &lt;SPAN class=""&gt;"http://localhost:5000"&lt;/SPAN&gt;),
            &lt;SPAN class=""&gt;new&lt;/SPAN&gt; KeyValuePair&amp;lt;&lt;SPAN class=""&gt;string&lt;/SPAN&gt;, &lt;SPAN class=""&gt;string&lt;/SPAN&gt;&amp;gt;(&lt;SPAN class=""&gt;"code_verifier"&lt;/SPAN&gt;, codeVerifier)
        };

        &lt;SPAN class=""&gt;var&lt;/SPAN&gt; content = &lt;SPAN class=""&gt;new&lt;/SPAN&gt; FormUrlEncodedContent(parameters );
        &lt;SPAN class=""&gt;var&lt;/SPAN&gt; response = &lt;SPAN class=""&gt;await&lt;/SPAN&gt; HttpClient.PostAsync(&lt;SPAN class=""&gt;$"https://accounts.spotify.com/api/token"&lt;/SPAN&gt;, content);&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 07 Dec 2020 09:05:15 GMT</pubDate>
      <guid>https://community.spotify.com/t5/Spotify-for-Developers/Unable-to-make-Authorization-Code-with-PKCE-work-C/m-p/5088063#M1686</guid>
      <dc:creator>clawcastle</dc:creator>
      <dc:date>2020-12-07T09:05:15Z</dc:date>
    </item>
  </channel>
</rss>

