<?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 Is there a PKCE Example for a &amp;quot;A client-side web application (pure Javascript)&amp;quot;? in Dropbox API Support &amp; Feedback</title>
    <link>https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/Is-there-a-PKCE-Example-for-a-quot-A-client-side-web-application/m-p/504550#M24961</link>
    <description>&lt;P&gt;Hi there,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;A href="https://webcache.googleusercontent.com/search?q=cache:I6mylKjZK5sJ:https://www.dropbox.com/lp/developers/reference/oauth-guide+&amp;amp;cd=1&amp;amp;hl=en&amp;amp;ct=clnk&amp;amp;gl=de" target="_blank" rel="noopener"&gt;As said here&lt;/A&gt;&amp;nbsp;(sorry for google webcache, the original page is a 404) in the bottom table&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;EM&gt;If your app is A client-side web application (pure Javascript) It should Use the OAuth code flow with short-lived access tokens with PKCE (no refresh tokens).&lt;/EM&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;So far I have failed to implement this. (I'm using &lt;A href="https://www.npmjs.com/package/dropbox" target="_blank" rel="noopener"&gt;dropbox@9.2.0&lt;/A&gt;&amp;nbsp;from npm)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;As far as I understand, when opening the url received by&amp;nbsp;calling&lt;/P&gt;&lt;PRE&gt;auth.&lt;SPAN&gt;getAuthenticationUrl&lt;/SPAN&gt;&lt;/PRE&gt;&lt;P&gt;I can either get a redirect back to my App or a code to copy/paste&lt;/P&gt;&lt;P&gt;At first I tried to open that URL in the same window, but after digging into the code of the auth instance, I found it stores&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;SPAN&gt;this&lt;/SPAN&gt;.codeChallenge&lt;BR /&gt;&lt;SPAN&gt;this&lt;/SPAN&gt;.codeVerifier&lt;/PRE&gt;&lt;P&gt;internally. These values are lost when the page is being reloaded so from what I understand, it's necessary the page remains open.&lt;/P&gt;&lt;P&gt;Hence I decided to open the authentication URL in a new tab without providing a redirect URL, so that I need to copy/paste the code manually (which is quite unintuitive for an end user)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;In that case I can call&lt;/P&gt;&lt;PRE&gt;auth.getAccessTokenFromCode&lt;/PRE&gt;&lt;P&gt;which sends a request to&lt;/P&gt;&lt;PRE&gt;https&lt;SPAN&gt;:&lt;/SPAN&gt;&lt;SPAN&gt;//api.dropboxapi.com/oauth2/token?grant_type=authorization_code&amp;amp;code=&amp;lt;snip&amp;gt;&amp;amp;client_id=&amp;lt;snip&amp;gt;&amp;amp;code_verifier=&amp;lt;snip&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;P&gt;In that case I receive an error response (404)&lt;/P&gt;&lt;PRE&gt;{&lt;BR /&gt;  &lt;SPAN&gt;"error_description"&lt;/SPAN&gt;&lt;SPAN&gt;: &lt;/SPAN&gt;&lt;SPAN&gt;"invalid code verifier"&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  &lt;SPAN&gt;"error"&lt;/SPAN&gt;&lt;SPAN&gt;: &lt;/SPAN&gt;&lt;SPAN&gt;"invalid_grant"&lt;BR /&gt;&lt;/SPAN&gt;}&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Could you point me in the direction what I'm doing wrong?&lt;/P&gt;&lt;P&gt;An example on how to implement this would greatly be appreciated!&lt;/P&gt;&lt;P&gt;Also I'd prefer to have the user not being forced to copy/paste the token or forcing them to find the correct opened tab in which he's meant to paste the code.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;For better understanding here's the relevant part of my code:&lt;/P&gt;&lt;PRE&gt;&lt;SPAN&gt;import &lt;/SPAN&gt;{ Dropbox } &lt;SPAN&gt;from &lt;/SPAN&gt;&lt;SPAN&gt;'dropbox'&lt;/SPAN&gt;&lt;SPAN&gt;;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;const &lt;/SPAN&gt;dbx &lt;SPAN&gt;= new &lt;/SPAN&gt;Dropbox({&lt;BR /&gt;  clientId&lt;SPAN&gt;: &lt;/SPAN&gt;DROPBOX_APP_KEY&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;})&lt;SPAN&gt;;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;dbx.auth.&lt;SPAN&gt;getAuthenticationUrl&lt;/SPAN&gt;(&lt;BR /&gt;  &lt;SPAN&gt;null&lt;/SPAN&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;SPAN&gt;// redirectUri,&lt;BR /&gt;&lt;/SPAN&gt;  &lt;SPAN&gt;''&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  &lt;SPAN&gt;'code'&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  &lt;SPAN&gt;'offline'&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  [&lt;BR /&gt;    &lt;SPAN&gt;'account_info.read'&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;    &lt;SPAN&gt;'files.content.write'&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;    &lt;SPAN&gt;'files.content.read'&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  ]&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  &lt;SPAN&gt;'user'&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  &lt;SPAN&gt;true&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;)&lt;BR /&gt;  .&lt;SPAN&gt;then&lt;/SPAN&gt;((&lt;SPAN&gt;authUrl&lt;/SPAN&gt;) &lt;SPAN&gt;=&amp;gt; &lt;/SPAN&gt;{&lt;BR /&gt;    &lt;SPAN&gt;window&lt;/SPAN&gt;.&lt;SPAN&gt;open&lt;/SPAN&gt;(&lt;SPAN&gt;authUrl&lt;/SPAN&gt;)&lt;SPAN&gt;;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;    &lt;SPAN&gt;// eslint-disable-next-line no-alert&lt;BR /&gt;&lt;/SPAN&gt;    &lt;SPAN&gt;const &lt;/SPAN&gt;&lt;SPAN&gt;code &lt;/SPAN&gt;&lt;SPAN&gt;= &lt;/SPAN&gt;&lt;SPAN&gt;window&lt;/SPAN&gt;.&lt;SPAN&gt;prompt&lt;/SPAN&gt;(&lt;SPAN&gt;'Enter your received code'&lt;/SPAN&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;SPAN&gt;''&lt;/SPAN&gt;)&lt;SPAN&gt;;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;    &lt;SPAN&gt;this&lt;/SPAN&gt;.dbx.auth.&lt;SPAN&gt;getAccessTokenFromCode&lt;/SPAN&gt;(&lt;SPAN&gt;null&lt;/SPAN&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;SPAN&gt;code&lt;/SPAN&gt;)&lt;BR /&gt;      .&lt;SPAN&gt;then&lt;/SPAN&gt;(({ &lt;SPAN&gt;result &lt;/SPAN&gt;}) &lt;SPAN&gt;=&amp;gt; &lt;/SPAN&gt;{&lt;BR /&gt;        // I'd expect to receive something to work with here&lt;BR /&gt;        &lt;SPAN&gt;console&lt;/SPAN&gt;.&lt;SPAN&gt;log&lt;/SPAN&gt;(&lt;SPAN&gt;result&lt;/SPAN&gt;)&lt;SPAN&gt;;&lt;BR /&gt;&lt;/SPAN&gt;      })&lt;SPAN&gt;;&lt;BR /&gt;&lt;/SPAN&gt;  })&lt;SPAN&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Sun, 14 Mar 2021 00:26:05 GMT</pubDate>
    <dc:creator>Zatacke</dc:creator>
    <dc:date>2021-03-14T00:26:05Z</dc:date>
    <item>
      <title>Is there a PKCE Example for a "A client-side web application (pure Javascript)"?</title>
      <link>https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/Is-there-a-PKCE-Example-for-a-quot-A-client-side-web-application/m-p/504550#M24961</link>
      <description>&lt;P&gt;Hi there,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;A href="https://webcache.googleusercontent.com/search?q=cache:I6mylKjZK5sJ:https://www.dropbox.com/lp/developers/reference/oauth-guide+&amp;amp;cd=1&amp;amp;hl=en&amp;amp;ct=clnk&amp;amp;gl=de" target="_blank" rel="noopener"&gt;As said here&lt;/A&gt;&amp;nbsp;(sorry for google webcache, the original page is a 404) in the bottom table&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;EM&gt;If your app is A client-side web application (pure Javascript) It should Use the OAuth code flow with short-lived access tokens with PKCE (no refresh tokens).&lt;/EM&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;So far I have failed to implement this. (I'm using &lt;A href="https://www.npmjs.com/package/dropbox" target="_blank" rel="noopener"&gt;dropbox@9.2.0&lt;/A&gt;&amp;nbsp;from npm)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;As far as I understand, when opening the url received by&amp;nbsp;calling&lt;/P&gt;&lt;PRE&gt;auth.&lt;SPAN&gt;getAuthenticationUrl&lt;/SPAN&gt;&lt;/PRE&gt;&lt;P&gt;I can either get a redirect back to my App or a code to copy/paste&lt;/P&gt;&lt;P&gt;At first I tried to open that URL in the same window, but after digging into the code of the auth instance, I found it stores&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;SPAN&gt;this&lt;/SPAN&gt;.codeChallenge&lt;BR /&gt;&lt;SPAN&gt;this&lt;/SPAN&gt;.codeVerifier&lt;/PRE&gt;&lt;P&gt;internally. These values are lost when the page is being reloaded so from what I understand, it's necessary the page remains open.&lt;/P&gt;&lt;P&gt;Hence I decided to open the authentication URL in a new tab without providing a redirect URL, so that I need to copy/paste the code manually (which is quite unintuitive for an end user)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;In that case I can call&lt;/P&gt;&lt;PRE&gt;auth.getAccessTokenFromCode&lt;/PRE&gt;&lt;P&gt;which sends a request to&lt;/P&gt;&lt;PRE&gt;https&lt;SPAN&gt;:&lt;/SPAN&gt;&lt;SPAN&gt;//api.dropboxapi.com/oauth2/token?grant_type=authorization_code&amp;amp;code=&amp;lt;snip&amp;gt;&amp;amp;client_id=&amp;lt;snip&amp;gt;&amp;amp;code_verifier=&amp;lt;snip&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;P&gt;In that case I receive an error response (404)&lt;/P&gt;&lt;PRE&gt;{&lt;BR /&gt;  &lt;SPAN&gt;"error_description"&lt;/SPAN&gt;&lt;SPAN&gt;: &lt;/SPAN&gt;&lt;SPAN&gt;"invalid code verifier"&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  &lt;SPAN&gt;"error"&lt;/SPAN&gt;&lt;SPAN&gt;: &lt;/SPAN&gt;&lt;SPAN&gt;"invalid_grant"&lt;BR /&gt;&lt;/SPAN&gt;}&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Could you point me in the direction what I'm doing wrong?&lt;/P&gt;&lt;P&gt;An example on how to implement this would greatly be appreciated!&lt;/P&gt;&lt;P&gt;Also I'd prefer to have the user not being forced to copy/paste the token or forcing them to find the correct opened tab in which he's meant to paste the code.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;For better understanding here's the relevant part of my code:&lt;/P&gt;&lt;PRE&gt;&lt;SPAN&gt;import &lt;/SPAN&gt;{ Dropbox } &lt;SPAN&gt;from &lt;/SPAN&gt;&lt;SPAN&gt;'dropbox'&lt;/SPAN&gt;&lt;SPAN&gt;;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;const &lt;/SPAN&gt;dbx &lt;SPAN&gt;= new &lt;/SPAN&gt;Dropbox({&lt;BR /&gt;  clientId&lt;SPAN&gt;: &lt;/SPAN&gt;DROPBOX_APP_KEY&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;})&lt;SPAN&gt;;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;dbx.auth.&lt;SPAN&gt;getAuthenticationUrl&lt;/SPAN&gt;(&lt;BR /&gt;  &lt;SPAN&gt;null&lt;/SPAN&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;SPAN&gt;// redirectUri,&lt;BR /&gt;&lt;/SPAN&gt;  &lt;SPAN&gt;''&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  &lt;SPAN&gt;'code'&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  &lt;SPAN&gt;'offline'&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  [&lt;BR /&gt;    &lt;SPAN&gt;'account_info.read'&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;    &lt;SPAN&gt;'files.content.write'&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;    &lt;SPAN&gt;'files.content.read'&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  ]&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  &lt;SPAN&gt;'user'&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;  &lt;SPAN&gt;true&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;BR /&gt;&lt;/SPAN&gt;)&lt;BR /&gt;  .&lt;SPAN&gt;then&lt;/SPAN&gt;((&lt;SPAN&gt;authUrl&lt;/SPAN&gt;) &lt;SPAN&gt;=&amp;gt; &lt;/SPAN&gt;{&lt;BR /&gt;    &lt;SPAN&gt;window&lt;/SPAN&gt;.&lt;SPAN&gt;open&lt;/SPAN&gt;(&lt;SPAN&gt;authUrl&lt;/SPAN&gt;)&lt;SPAN&gt;;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;    &lt;SPAN&gt;// eslint-disable-next-line no-alert&lt;BR /&gt;&lt;/SPAN&gt;    &lt;SPAN&gt;const &lt;/SPAN&gt;&lt;SPAN&gt;code &lt;/SPAN&gt;&lt;SPAN&gt;= &lt;/SPAN&gt;&lt;SPAN&gt;window&lt;/SPAN&gt;.&lt;SPAN&gt;prompt&lt;/SPAN&gt;(&lt;SPAN&gt;'Enter your received code'&lt;/SPAN&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;SPAN&gt;''&lt;/SPAN&gt;)&lt;SPAN&gt;;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;    &lt;SPAN&gt;this&lt;/SPAN&gt;.dbx.auth.&lt;SPAN&gt;getAccessTokenFromCode&lt;/SPAN&gt;(&lt;SPAN&gt;null&lt;/SPAN&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;SPAN&gt;code&lt;/SPAN&gt;)&lt;BR /&gt;      .&lt;SPAN&gt;then&lt;/SPAN&gt;(({ &lt;SPAN&gt;result &lt;/SPAN&gt;}) &lt;SPAN&gt;=&amp;gt; &lt;/SPAN&gt;{&lt;BR /&gt;        // I'd expect to receive something to work with here&lt;BR /&gt;        &lt;SPAN&gt;console&lt;/SPAN&gt;.&lt;SPAN&gt;log&lt;/SPAN&gt;(&lt;SPAN&gt;result&lt;/SPAN&gt;)&lt;SPAN&gt;;&lt;BR /&gt;&lt;/SPAN&gt;      })&lt;SPAN&gt;;&lt;BR /&gt;&lt;/SPAN&gt;  })&lt;SPAN&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 14 Mar 2021 00:26:05 GMT</pubDate>
      <guid>https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/Is-there-a-PKCE-Example-for-a-quot-A-client-side-web-application/m-p/504550#M24961</guid>
      <dc:creator>Zatacke</dc:creator>
      <dc:date>2021-03-14T00:26:05Z</dc:date>
    </item>
    <item>
      <title>Re: Is there a PKCE Example for a "A client-side web application (pure Javascript)"?</title>
      <link>https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/Is-there-a-PKCE-Example-for-a-quot-A-client-side-web-application/m-p/504610#M24963</link>
      <description>&lt;P&gt;I just found there is &lt;A href="https://github.com/dropbox/dropbox-sdk-js/issues/527" target="_self"&gt;already a bugreport&lt;/A&gt; on this on GitHub since end of January.&lt;/P&gt;&lt;P&gt;I created a (not-working) standalone example and put it in that bugreport.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 14 Mar 2021 15:25:19 GMT</pubDate>
      <guid>https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/Is-there-a-PKCE-Example-for-a-quot-A-client-side-web-application/m-p/504610#M24963</guid>
      <dc:creator>Zatacke</dc:creator>
      <dc:date>2021-03-14T15:25:19Z</dc:date>
    </item>
    <item>
      <title>Re: Is there a PKCE Example for a "A client-side web application (pure Javascript)"?</title>
      <link>https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/Is-there-a-PKCE-Example-for-a-quot-A-client-side-web-application/m-p/504861#M24973</link>
      <description>&lt;P&gt;Thanks for writing this up! Yes, this is already open on GitHub so I'll follow up with you there.&lt;/P&gt;</description>
      <pubDate>Mon, 15 Mar 2021 15:30:11 GMT</pubDate>
      <guid>https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/Is-there-a-PKCE-Example-for-a-quot-A-client-side-web-application/m-p/504861#M24973</guid>
      <dc:creator>Greg-DB</dc:creator>
      <dc:date>2021-03-15T15:30:11Z</dc:date>
    </item>
  </channel>
</rss>

