pythonoauthtiktoktiktok-api

TikTok oAuth API authorization code request always expired


I'm trying to use to oAuth of the TikTok API.

From what I got from their website, you first need to send the user to a particular link, with your client_key and redirect_uri, then the user need to log in.

After he's logged in, there will be a code in the return URL that you can use to get the access_token of the user. Problem is, I always got the error:

{'error': 'invalid_grant', 'error_description': 'Authorization code is expired.', 'log_id': 'XXXXXXXX'}

Here is the link that explains everything I did :

I already have an authorized application on their developer website with a client key, secret, and the Login kit that allows the user to log in.

Here is the Python code I did to test this :

import requests
import urllib
import secrets
import time

# Constants
CLIENT_KEY = "xxxxx"
CLIENT_SECRET = "yyyyy"
REDIRECT_URI = "https://oxyfoo.com/pierre/tiktok-automation/"
AUTHORIZE_URL = 'https://www.tiktok.com/v2/auth/authorize/'
TOKEN_URL = 'https://open.tiktokapis.com/v2/oauth/token/'

# Function to generate authorization URL
def generate_auth_url():
    csrf_state = secrets.token_hex(16)

    params = {
        'client_key': CLIENT_KEY,
        'scope': 'user.info.basic',
        'response_type': 'code',
        'redirect_uri': REDIRECT_URI,
        'state': csrf_state,
    }

    url = AUTHORIZE_URL + '?' + urllib.parse.urlencode(params)
    
    return url, csrf_state

# Function to get the access token
def get_access_token(authorization_code):
    data = {
        'client_key': CLIENT_KEY,
        'client_secret': CLIENT_SECRET,
        'code': authorization_code,
        'grant_type': 'authorization_code',
        'redirect_uri': REDIRECT_URI
    }
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }

    response = requests.post(TOKEN_URL, headers=headers, data=urllib.parse.urlencode(data))

    if response.status_code == 200:
        return response.json()
    else:
        print(f"Error: Received status code {response.status_code}")
        print(f"Response content: {response.content.decode()}")
        return None

# Testing
def manual_test():
    # Generate authorization URL
    print("Generating authorization URL...")
    url, state = generate_auth_url()
    print("URL:", url) # I go there and log in
    print("State:", state)
    
    # Prompt user for the redirect URL
    input_ = input("Paste the URL you were redirected to: ") # I put the url of the page that start with my redirect_uri with ?code, scopes, etc here
    
    # Extract authorization code from redirect URL
    code = input_.split("code=")[1].split("&")[0]
    print("Code:", code)
    
    # Fetch access token without delay
    print("Fetching access token...")
    token_info = get_access_token(code)
    print(token_info) # Here, I always have the error invalid grant authorization code is expired.

if __name__ == "__main__":
    manual_test()

I tried to really follow the documentation and I thought I did but I can't understand why I do have this error. I'm not familiar with using oAuth so maybe it's a basic error but I just can't seem to solve it.


Solution

  • As Michal pointed out, you need to decode the code you get before using it.

    Here is how you can do it (Edit of you manual_test() function) :

    def manual_test():
        # Generate authorization URL
        print("Generating authorization URL...")
        url, state = generate_auth_url()
        print("URL:", url)
        print("State:", state)
        
        # Prompt user for the redirect URL
        input_ = input("Paste the URL you were redirected to: ")
        
        # Extract authorization code from redirect URL
        code = input_.split("code=")[1].split("&")[0]
    
        # Decode the code (THAT'S THE EDITING PART)
        decoded_code = urllib.parse.unquote(code)
    
        print("Code:", code)
        print("Decoded Code:", decoded_code)
        
        # Fetch access token without delay
        print("Fetching access token...")
        token_info = get_access_token(decoded_code)
        print(token_info)