title: TikTok oAuth API auth code is always expired
body: <p>I am trying to login using <a href="https://developers.tiktok.com/doc/login-kit-manage-user-access-tokens" rel="nofollow noreferrer">TikTok oAuth API</a></p>
  <p>I have a Firebase Cloud Function (Nodejs) set up to complete the oauth flow, based
  on the TikTok API Documentation, but when i reach the point (<a href="https://open-api.tiktok.com/oauth/access_token" rel="nofollow noreferrer">https://open-api.tiktok.com/oauth/access_token</a>) to get the actual user access token it fails and i get an error.</p>
  <p>The response i get is status 200 and</p>
  <pre><code>{
      &quot;data&quot;: {
          &quot;captcha&quot;: &quot;&quot;,
          &quot;desc_url&quot;: &quot;&quot;,
          &quot;description&quot;: &quot;Authorization code expired&quot;,
          &quot;error_code&quot;: 10007
      },
      &quot;message&quot;: &quot;error&quot;
  }
  </code></pre>
  <p>The TikTok API always gives me the same authorization code. So i am guessing something is wrong. Any suggestion is welcomed.</p>
  <p>Here is the code sample from the backend
  The <code>/linkTikTok/oauth</code> and point used to redirect the user to tikTok oauth and the <code>/linkTikTok/validate</code> is used to request the access token. The code runs fine but when it reaches <code>const URL = https://open-api.tiktok.com/oauth/access_token</code>; and actually requests the user access token i get response above.</p>
  <pre><code>import * as express from 'express';
  import * as cors from 'cors';
  import axios from 'axios';
  import * as cookieParser from 'cookie-parser';
  import { config } from 'firebase-functions';
  import { firestore } from 'firebase-admin';
  import { colRefs } from '../../constants/db-refs';
  
  const app = express();
  app.use(cors());
  app.use(cookieParser());
  app.listen();
  const { client_key, client_secret } = config().tikTokCredentials;
  const redirectURI = `https://xxxxx.firebaseapp.com/linkTikTok/validate`;
  
  
  app.get('/linkTikTok/oauth', async (req, res) =&gt; {
   // The user's id;
   const uid = 'a_user_id';
   if (!uid) {
    return res.status(401).send('This action requires user authentication');
   }
   // Random state
   const csrfState = Math.random().toString(36).substring(7);
   const state: any = {
    state: csrfState,
    timestamp: firestore.Timestamp.now(),
    uid,
   };
   // A state object kepts in firestore
   await colRefs.tikTokAuthState.doc(uid).set(state);
   res.cookie('__session', { state: csrfState });
   let url = 'https://open-api.tiktok.com/platform/oauth/connect/';
  
   url += `?client_key=${client_key}`;
   url += '&amp;scope=user.info.basic,video.list';
   url += '&amp;response_type=code';
   url += `&amp;redirect_uri=${redirectURI}`;
   url += '&amp;state=' + csrfState;
  
   return res.redirect(url);
  });
  
  
  app.get('/linkTikTok/validate', async (req, res) =&gt; {
   // Query state
   const state = req.query.state as string;
  
   if (!state) {
    return res.status(403).send('No state found');
   }
   const code = req.query.code as string;
   if (!code) {
    return res.status(403).send('No code found');
   }
   const sessionCookie = req.cookies['__session'] ?? {};
   const sessionState = sessionCookie.state;
  
   if (state !== sessionState) {
    return res.status(403).send('Wrong state');
   }
   // Retrieve the uid from firestore
   const uid = await (async () =&gt; {
    const states = (await colRefs.tikTokAuthState.where('state', '==', state).get()).docs.map(d =&gt; d.data());
    if (states.length !== 0 &amp;&amp; states.length &gt; 1) {
     console.warn('More than one state');
    }
    return states[0].uid;
   })();
  console.log({ uid });
  
  const URL = `https://open-api.tiktok.com/oauth/access_token`;
  
  const params = {
   client_key,
   client_secret,
   code,
   grant_type: 'authorization_code',
  };
  
  try {
   const result = await axios.post&lt;any&gt;(URL, '', {
     params,
   });
   const data = result.data.data;
   const {
     access_token: accessToken,
     refresh_token,
     refresh_expires_in,
     open_id: openId,
     expires_in,
   } = data;
  
   if (!accessToken) {
     throw new Error('No access token found');
   }
   // Application logic
   ...
  });
  </code></pre>