2

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.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Madar
  • 196
  • 2
  • 15
  • 1
    There is this information in the doc about the received code: `The value should be URL decoded`. Maybe the code you get has some special characters (e.g. `/`) that need to be decoded before sending it back? – Michal Trojanowski Aug 08 '23 at 08:50
  • @MichalTrojanowski what do you mean by decoded ? Here is the example of what I get : https://my-website/?code=ibRvXepRgDe-vDqeaq3vRmAs9h8Qn0x6Wvv3sP064LbqX8euWxnCMP5UD9o6Qujk71K3S8KWcwJ_hXrlUFhpZzNq8A0dz_9cxKWT031Kzs_mhOr-a3pNFB07E0GQPW2hdJgq4JKHj91aspc7TDF9QLBvrO32UWz0VBNF-pKu0Uk03_1BT5HUuZxSA429ZkAD%2A3%214956&scopes=user.info.basic&state=2b003add51070b179b4f5a75f2d922b3 I only use the code that starts with ibR and end up with 4956 in the example above as an authorization code. I don't understand what you mean by saying "decoded". Can you give me an example please ? – Madar Aug 08 '23 at 11:27
  • 1
    You can read about "url-encoding" of characters. In short: some characters have reserved meaning in URLs and can't be used in values of query parameters. If you need to use such a character, you need to encode it, i.e. change it to some other characters that are not reserved (e.g. `/` is encoded to `%2F`). Once you need the original value again you have to decode it, i.e. change again the sequence to the reserved character. – Michal Trojanowski Aug 08 '23 at 12:35

1 Answers1

2

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)
Pierre Marsaa
  • 346
  • 2
  • 10