Getting an Ebay OAuth Token
Asked Answered
S

3

6

I've been working on the ebaySDK for most of the week. I've managed to integrate the Trading and Shopping APIs into my project. For the trading API, I was using an Auth n Auth token which has a validity of upto 18 months. The OAuth Token which I need for the Sell APIs is valid only for a day, so I'll need to fetch it regularly before it expires. I followed the documentation on the site and even tried looking through python repos on github but I haven't been able to move forward as of yet. Here's a quick snippet of my request code, What am I doing wrong?

import requests, json, base64, xmltodict

AppSettings = {
    'app_id' : 'my_app_id',
    'app_secret' : 'my_app_secret',
    'dev_id': 'my_dev_id',
    'ruName': 'the_ruName_for_my_app'
}
authHeaderData =  AppSettings['app_id']+':'+AppSettings['app_secret']
encodedAuthHeader = base64.b64encode(authHeaderData)

session = requests.Session()

print encodedAuthHeader 
url = 'https://api.ebay.com/identity/v1/oauth2/token'

session.headers.update({
    'Content-Type':'application/x-www-form-urlencoded',
    'Authorization':'Basic '+encodedAuthHeader
    })

data = {
    'grant_type':'client_credentials',
    'redirect_uri': AppSettings['ruName'],
    'scope':'https://api.ebay.com/oauth/api_scope'
}

response = session.post(url, data=data).json()
print response

The response I'm getting is:

{u'error_description': u'client authentication failed', u'error': u'invalid_client'}

I checked all the keys. I even tried to get the token via the production signin provided by ebay but to no avail. The response I got from the url provided by ebay was html and js code (No JSON or any data).

Has anybody faced a similar issue? How can I work through this? Am I making the requests wrong? Any insight is greatly appreciated

Scalping answered 18/5, 2017 at 11:44 Comment(5)
Okay so after some more proper research and delving through the docs, I stumbled accross this answer on the eBay forum which basically breaks down the process. forums.developer.ebay.com/questions/18489/… So right now for the oauth user token, I'm going to the sign in link provided by eBay and filling out the login for the user. Lets see what happens next.Scalping
Were you able to get through? Do you need to go through sign in process every 2 hours?Radom
@mentorgashi No i dont need to do the sign in every couple hours because the response gives me a refresh token alongside the token. I can use the refresh token to generate a new token any time my token expiresScalping
Have you solved it?Ing
@Scalping could you please answer your question with your final solution?Gladygladys
S
13

Because this was such a nightmare to traverse eBays docs to find this answer, I figured i would post my function that solved this.

import requests, urllib, base64

def getAuthToken():
     AppSettings = {
          'client_id':'<client_id>',
          'client_secret':'<client_secret>',
          'ruName':'<ruName>'}

     authHeaderData = AppSettings['client_id'] + ':' + AppSettings['client_secret']
     encodedAuthHeader = base64.b64encode(str.encode(authHeaderData))

     headers = {
          "Content-Type" : "application/x-www-form-urlencoded", 
          "Authorization" : "Basic " + str(encodedAuthHeader)
          }

     body= {
          "grant_type" : "client_credentials",
          "redirect_uri" : AppSettings['ruName'],
          "scope" : "https://api.ebay.com/oauth/api_scope"
      }

     data = urllib.parse.urlencode(body)

     tokenURL = "https://api.ebay.com/identity/v1/oauth2/token"

     response = requests.post(tokenURL, headers=headers, data=data) 
     return response.json()


response = getAuthToken()
print(response)
response['access_token'] #access keys as required
response['error_description'] #if errors
Stokes answered 26/6, 2018 at 21:12 Comment(6)
FYI, requests will set the Content-Type header to application/x-www-form-urlencoded when you pass in a python dict. So you could shorten this to requests.post(..., data=body)Gardal
How can I get tokens for user, so, I can use with https://api.ebay.com/sell/fulfillment/v1/order?limit=10 ?Froh
You would need to use "Bearer <token>" in the Authorization headerDierolf
if you get any errors with this, check your encodedAuthHeader, it might have the b' and a trailing 'Merchant
@Stokes i'm using exact code with right production client id's and secrets but i keep getting " {'error': 'invalid_request', 'error_description': 'request is missing a required parameter or malformed.'}Rieth
encodedAuthHeader doesn’t work for me. I change to encodedAuthHeader = base64.b64encode(str.encode(authHeaderData)).decode("utf-8")Lactescent
C
2

@sunny babau I was having the same problem as you. It was indeed caused by the b' and a trailing '. After adding the following line to the code above, which removes these characters, it worked for me:

encodedAuthHeader = str(encodedAuthHeader)[2:len(str(encodedAuthHeader))-1]
Clippers answered 25/10, 2020 at 13:13 Comment(0)
W
0

I created a solution for this problem using a Python script that automates eBay OAuth user authentication, token retrieval, and decoding of the encoded authorization code.

Here is the Github repository:

https://github.com/johnchervanev/ebay_authentication_token

Here is the code:

import requests
from base64 import b64encode
from urllib.parse import urlparse, parse_qs
import webbrowser

# Prompt the user to enter their eBay production application credentials and redirect URI (known as RuName)
client_id = input("Enter your eBay client ID: ")
client_secret = input("Enter your eBay client secret: ")
redirect_uri = input("Enter your eBay redirect URI: ")

# Define all the scopes based on your requirements
scopes = (
    "https://api.ebay.com/oauth/api_scope "
    "https://api.ebay.com/oauth/api_scope/sell.marketing.readonly "
    "https://api.ebay.com/oauth/api_scope/sell.marketing "
    "https://api.ebay.com/oauth/api_scope/sell.inventory.readonly "
    "https://api.ebay.com/oauth/api_scope/sell.inventory "
    "https://api.ebay.com/oauth/api_scope/sell.account.readonly "
    "https://api.ebay.com/oauth/api_scope/sell.account "
    "https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly "
    "https://api.ebay.com/oauth/api_scope/sell.fulfillment "
    "https://api.ebay.com/oauth/api_scope/sell.analytics.readonly "
    "https://api.ebay.com/oauth/api_scope/sell.finances "
    "https://api.ebay.com/oauth/api_scope/sell.payment.dispute "
    "https://api.ebay.com/oauth/api_scope/commerce.identity.readonly "
    "https://api.ebay.com/oauth/api_scope/sell.reputation "
    "https://api.ebay.com/oauth/api_scope/sell.reputation.readonly "
    "https://api.ebay.com/oauth/api_scope/commerce.notification.subscription "
    "https://api.ebay.com/oauth/api_scope/commerce.notification.subscription.readonly "
    "https://api.ebay.com/oauth/api_scope/sell.stores "
    "https://api.ebay.com/oauth/api_scope/sell.stores.readonly"
)

# Set the target endpoint for the consent request in production
consent_endpoint_production = "https://auth.ebay.com/oauth2/authorize"
token_endpoint = "https://api.ebay.com/identity/v1/oauth2/token"

# Define the consent URL
consent_url = (
    f"{consent_endpoint_production}?"
    f"client_id={client_id}&"
    f"redirect_uri={redirect_uri}&"
    f"response_type=code&"
    f"scope={scopes}"
)

# Open the consent URL in the default web browser
webbrowser.open(consent_url)

print("Opening the browser. Please grant consent in the browser.")

# Retrieve the authorization code from the user after they grant consent
authorization_code_url = input("Enter the authorization code URL: ")

# Parse the URL to extract the authorization code
parsed_url = urlparse(authorization_code_url)
query_params = parse_qs(parsed_url.query)
authorization_code = query_params.get('code', [])[0]

# Make the authorization code grant request to obtain the token
payload = {
    "grant_type": "authorization_code",
    "code": authorization_code,
    "redirect_uri": redirect_uri
}

# Encode the client credentials for the Authorization header
credentials = f"{client_id}:{client_secret}"
encoded_credentials = b64encode(credentials.encode()).decode()

# Set the headers for the token request
token_headers = {
    "Content-Type": "application/x-www-form-urlencoded",
    "Authorization": f"Basic {encoded_credentials}"
}

# Make the POST request to the token endpoint
response = requests.post(token_endpoint, headers=token_headers, data=payload)

# Check the response
if response.status_code == 200:
    # Parse and print the response JSON
    response_json = response.json()
    print("Response containing the User access token:")
    print(response_json)
else:
    print(f"Error: {response.status_code}, {response.text}")
Westbrook answered 29/12, 2023 at 0:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.