Alex Daltsis
Alex Daltsis

Reputation: 71

TikTok oAuth API auth code is always expired

I am trying to login using TikTok oAuth API

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 (https://open-api.tiktok.com/oauth/access_token) to get the actual user access token it fails and i get an error.

The response i get is status 200 and

{
    "data": {
        "captcha": "",
        "desc_url": "",
        "description": "Authorization code expired",
        "error_code": 10007
    },
    "message": "error"
}

The TikTok API always gives me the same authorization code. So i am guessing something is wrong. Any suggestion is welcomed.

Here is the code sample from the backend The /linkTikTok/oauth and point used to redirect the user to tikTok oauth and the /linkTikTok/validate is used to request the access token. The code runs fine but when it reaches const URL = https://open-api.tiktok.com/oauth/access_token; and actually requests the user access token i get response above.

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) => {
 // 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 += '&scope=user.info.basic,video.list';
 url += '&response_type=code';
 url += `&redirect_uri=${redirectURI}`;
 url += '&state=' + csrfState;

 return res.redirect(url);
});


app.get('/linkTikTok/validate', async (req, res) => {
 // 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 () => {
  const states = (await colRefs.tikTokAuthState.where('state', '==', state).get()).docs.map(d => d.data());
  if (states.length !== 0 && states.length > 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<any>(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
 ...
});

Upvotes: 2

Views: 5200

Answers (3)

Alex Daltsis
Alex Daltsis

Reputation: 71

I was using Google's CDN passed from firebase hosting to call the Cloud Function, that was causing the issue.

Upvotes: 0

CodeRevolution
CodeRevolution

Reputation: 117

I got the same error in my code, however, in my case, I was doing duplicate authentication with the TikTok API, because I forgot the "code" GET parameter in my URL and when I was saving settings in my app again, the GET parameter fired again the authentication sequence and I got always the "Authorization code expired" error - but only the second time I was making requests.

You should check if you don't also have duplicate authentication requests in your app.

Upvotes: 4

Junaid Shad
Junaid Shad

Reputation: 71

would you share the piece of code you've written so that we could find the spot.

Upvotes: 0

Related Questions