Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting User Token without Selenium automation? #56

Closed
albytterc opened this issue Aug 1, 2022 · 11 comments
Closed

Getting User Token without Selenium automation? #56

albytterc opened this issue Aug 1, 2022 · 11 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@albytterc
Copy link

albytterc commented Aug 1, 2022

Hi matecsaj,

Is there any way to avoid the Selenium automation when trying to get a user token? For example, instead of providing the user credentials in the ebay_rest.json file, to just go through the traditional OAuth flow where the login is provided by the end user?

Something like this would be useful in supporting multiple eBay users logging in.

Thanks,
Albert

@matecsaj matecsaj added the help wanted Extra attention is needed label Aug 2, 2022
@matecsaj
Copy link
Owner

matecsaj commented Aug 2, 2022

Albert,

When the following are blank, Selenium is used to get refresh tokens.

    "refresh_token": "",
    "refresh_token_expiry": ""

Instead, do something like this, with, of course, your token info.

    "refresh_token": "production_refresh_token",
    "refresh_token_expiry": "production_token_expiry"

Use of an ebay_rest.json file is optional; the Class initializer accepts relevant keyword parameters.

        :param application (str or dict, optional) :
        Supply the name of the desired application record in ebay_rest.json or a dict with application credentials.

        Can omit when ebay_rest.json contains only one application record.
        :param user (str or dict, optional) :
        Supply the name of the desired user record in ebay_rest.json or a dict with user credentials.
        Can omit when ebay_rest.json contains only one user record.

        :param header (str or dict, optional) :
        Supply the name of the desired header record in ebay_rest.json or a dict with header credentials.
        Can omit when ebay_rest.json contains only one header record.

Sample code.

from ebay_rest import API, Error

application = {
    "app_id": "placeholder-placeholder-PRD-placeholder-placeholder",
    "cert_id": "PRD-placeholder-placeholder-placeholder-placeholder-placeholder",
    "dev_id": "placeholder-placeholder-placeholder-placeholder-placeholder",
    "redirect_uri": "placeholder-placeholder-placeholder-placeholder"
}

user = {
    "email_or_username": "<production-username>",
    "password": "<production-user-password>",
    "scopes": [
        "https://api.ebay.com/oauth/api_scope",
        "https://api.ebay.com/oauth/api_scope/sell.inventory",
        "https://api.ebay.com/oauth/api_scope/sell.marketing",
        "https://api.ebay.com/oauth/api_scope/sell.account",
        "https://api.ebay.com/oauth/api_scope/sell.fulfillment"
    ],
    "refresh_token": "production-refresh_token",
    "refresh_token_expiry": "production-token_expiry"
}

header = {
    "accept_language": "en-US",
    "affiliate_campaign_id": "",
    "affiliate_reference_id": "",
    "content_language": "en-CA",
    "country": "CA",
    "currency": "CAD",
    "device_id": "",
    "marketplace_id": "EBAY_ENCA",
    "zip": ""
}

try:
    api = API(application=application, user=user, header=header)
except Error as error:
    print(f'Error {error.number} is {error.reason}  {error.detail}.\n')
else:
    try:
        print("The five least expensive iPhone things now for sale on-eBay:")        
        for record in api.buy_browse_search(q='iPhone', sort='price', limit=5):
            if 'record' not in record:
                pass    # TODO Refer to non-records, they contain optimization information.
            else:
                item = record['record']
                print(f"item id: {item['item_id']} {item['item_web_url']}")
    except Error as error:
        print(f'Error {error.number} is {error.reason} {error.detail}.\n')
    else:
        pass

When using eBay's sandbox:

  1. Omit "scopes."
  2. Your credentials will contain 'SBX' instead of 'PRD.'

Output.

The five least expensive iPhone things now for sale on eBay:
item id: v1|110551100598|410108380484 http://www.sandbox.ebay.com/itm/Retro-Magnetic-Wallet-Leather-Case-For-Apple-iPhone-13-Pro-Max-12-11-XR-8-Cover-/110551100598?hash=item19bd5becb6:g:aXsAAOSwaiFiyAV9
item id: v1|110551164737|410108400925 http://www.sandbox.ebay.com/itm/For-iPhone-6-6-7-8-Plus-LCD-Display-Touch-Screen-Replacement-Home-Button-Camera-/110551164737?hash=item19bd5ce741:g:6hcAAOSwE3Ni45Qu
item id: v1|110551164738|410108400957 http://www.sandbox.ebay.com/itm/For-iPhone-6-6-7-8-Plus-LCD-Display-Touch-Screen-Replacement-Home-Button-Camera-/110551164738?hash=item19bd5ce742:g:4BcAAOSwG8Ni45Ra
item id: v1|110551164739|410108400989 http://www.sandbox.ebay.com/itm/For-iPhone-6-6-7-8-Plus-LCD-Display-Touch-Screen-Replacement-Home-Button-Camera-/110551164739?hash=item19bd5ce743:g:4CEAAOSwG8Ni45SQ

Did I understand your question, and is my response satisfactory?

@albytterc
Copy link
Author

Thank you for this detailed and quick response. But I was more wondering if there was a way to not have to provide the user's credentials in the API object constructor directly, so the user could log in themselves. It seems to me the user's credentials must be provided in some way to the API before logging in (either through the keywords or the json file). For example, my application is trying to create listings on the user's sandbox account through this library,.so it would require them to login manually.

@matecsaj
Copy link
Owner

matecsaj commented Aug 3, 2022

Re. It seems to me.

eBay is rigid and only provides one or two ways of doing things. My understanding of what eBay expects and prefers is baked into the eBay-rest library. If you want to modify ebay-rest to make it more flexible, a PR would be warmly received.

Re. My application is trying to create listings on the user's sandbox account.

You are fortunate; dozens and maybe even hundreds of applications and websites already do that; they give you viable examples. Have you found one that handles eBay credentials in a way your end-users will like and tried to mimic it?

@matecsaj
Copy link
Owner

An easy option is to switch ebay_rest from Selenium to Playwright and, while doing so, make it headless. This would also eliminate a chrome driver dependency.

Requests is already a dependency, so utilizing it would be even better; more labour to implement.

@matecsaj matecsaj added enhancement New feature or request good first issue Good for newcomers labels Aug 11, 2022
@matecsaj
Copy link
Owner

Upon further consideration, urllib is already baked into the Swagger-generated code, so using urllib would be better than Requests because it makes progress towards reducing dependencies.

@matecsaj
Copy link
Owner

In answer to a user's question.

Note that the “production_refresh_token” and “refresh_token_expiry” are dumped to the log file.

That happens in this file https://github.com/matecsaj/ebay_rest/blob/main/src/ebay_rest/token.py, where the following line is located.
message = f'Edit to your ebay_rest.json file to avoid the browser pop-up.\n'

If your project uses log-level info or higher, the info will appear in your log. Alternately, put a breakpoint after the line of code, and cut-paste the values.

@matecsaj
Copy link
Owner

matecsaj commented Oct 8, 2022

I determined that urlib or requests can't fully substitute for Selenium or Playwright because some pages rely on javascript.

I also discovered that we don't need to switch to Playwrite to run headless; let us give this change e611789
a try with the next release.

@matecsaj
Copy link
Owner

The headless change was commented out until captcha automation is added. d1ad19c

@matecsaj
Copy link
Owner

matecsaj commented Nov 8, 2022

Perhaps some things have changed in a helpful way, give eBay's documentation a careful read.
https://developer.ebay.com/api-docs/static/get_auth_n_auth_tokens.html

@gbm001
Copy link
Contributor

gbm001 commented Jan 11, 2023

I use ebay_rest for a web server application and don't use Selenium to get refresh tokens. I use JS to push people to the right eBay web page when they click an 'authorize' button; they then fill in their login on the eBay site and I pick up the consent token on our 'live' server (the one specified on the eBay token details). The live server then builds a redirect which goes to the machine that actually requested the token originally (all this happens in the browser, including the original eBay redirect, so it all works fine with localhost addresses).

(that said, I haven't tried updating to a new version of ebay_rest in a while and that would probably break everything as selenium seems to have become a required dependency again...)

@matecsaj matecsaj removed the good first issue Good for newcomers label Jan 12, 2023
@matecsaj
Copy link
Owner

We don't need to keep this issue open.

  1. A compilation of the fruitful parts of the discussion is now found in README.md.
  2. A separate issue will track the only possible code change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants