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

Token not working, always causing 403 #11217

Closed
novitae opened this issue Apr 20, 2022 · 26 comments · Fixed by #11260
Closed

Token not working, always causing 403 #11217

novitae opened this issue Apr 20, 2022 · 26 comments · Fixed by #11260
Labels

Comments

@novitae
Copy link

novitae commented Apr 20, 2022

Describe the bug

PyPI API Token not working for me

Expected behavior

GitHub action Upload Python Package authentication fails with the token I generates for it (403).

To Reproduce

Create a repo with some python things. Upload it to PyPI with twine from your terminal with username and password. It should work. Put this repo on github, change few things, update the version in setup.py. In actions, add the Upload Python Package action. Create an api token for it. Add it in the secrets under the name of PYPI_API_TOKEN. Create a new tag, it should start upload this tag to PyPI, but for me it fails.

Long story short, follow what's written here with the Upload Python Package GitHub action.

Also something weird, even if I deleted all my tokens, when I create new one, it tells me API token name already in use, but when I go back to my profile I see it registered ...

Additional context

I asked here pypi/support#1623 a 2FA recovery, now it is done. But could this be the source of the problem ? Right now I don't have 2FA activated, and since I saw we need a verified email to generate token (mine is verified), I'm asking myself if no having 2FA can influence this, like not generating valid tokens. Just supposition, I might be completely off-topic.

@di
Copy link
Member

di commented Apr 20, 2022

This is likely due to #11122. @woodruffw can you look into this?

@woodruffw
Copy link
Member

Yeah, taking a look now.

Just for clarification: the Upload Python Package action you're talking about is this one, right? https://github.com/pypa/gh-action-pypi-publish

@woodruffw
Copy link
Member

Hmm, I couldn't immediately reproduce this locally (on main = 7da6d17).

Here's what I did:

  • Created a fakepkg distribution and uploaded it using a normal username and password pair (succeeded)
  • Created an API token scoped to fakepkg via the web interface (succeeded)
  • Replaced the username and password with __token__ and the generated API token in my .pypirc
  • Uploaded a new release of fakepkg using the API token (succeeded)
  • Confirmed that it's present via the web interface
  • Removed the API token via the web interface (succeeded)
  • Confirmed that trying to upload via that token again failed (expected)

Am I missing any of your steps, @novitae? I'll try with some different 2FA configurations in a moment as well.

@woodruffw
Copy link
Member

I'm trying this with a public repository + package as well, with an API token associated with my 2FA-enabled PyPI account. Will report the results in a moment.

@woodruffw
Copy link
Member

woodruffw commented Apr 20, 2022

Publishing with the official GitHub Action works for me: https://github.com/trailofbits/blight/runs/6096536844?check_suite_focus=true

Here's the relevant GitHub Action step:

    - name: publish
      uses: pypa/gh-action-pypi-publish@master
      with:
        user: __token__
        password: ${{ secrets.PYPI_TOKEN }}

(where secrets.PYPI_TOKEN is my API token, including the pypy- prefix).

@woodruffw
Copy link
Member

I'm going to try cycling that API token as well. One moment.

@woodruffw
Copy link
Member

Okay, I think I was able to reproduce this:

[25](https://github.com/trailofbits/blight/runs/6096668206?check_suite_focus=true#step:8:25)l
  0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/41.7 kB • --:-- • ?
  0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/41.7 kB • --:-- • ?
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 41.7/41.7 kB • 00:00 • 74.8 MB/s
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 41.7/41.7 kB • 00:00 • 74.8 MB/s
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 41.7/41.7 kB • 00:00 • 74.8 MB/s
25hWARNING  Error during upload. Retry with the --verbose option for more details. 
ERROR    HTTPError: 403 Forbidden from https://upload.pypi.org/legacy/          
         Invalid or non-existent authentication information. See                
         https://pypi.org/help/#invalid-auth for more information.

Via: https://github.com/trailofbits/blight/runs/6096668206?check_suite_focus=true

That was with a brand new token, rather than a pre-existing one, on a 2FA-enabled account. Trying to repro locally now.

@woodruffw
Copy link
Member

Tried to reproduce this under the same conditions locally, with no luck:

  • Enabled 2FA (TOTP)
  • Created a new API token, scoped to fakepkg
  • Uploaded a new distribution successfully with the API token (expected failure)

@woodruffw
Copy link
Member

...okay. I tried creating the API token again, under the exact same conditions, and this time it succeeded: https://github.com/trailofbits/blight/runs/6096846818?check_suite_focus=true

The only thing I changed is how I entered the token into GitHub's secrets interface: this time, I noticed that there was a trailing newline and removed it. My best guess is that the PyPI GitHub Action isn't trimming the secret's trailing whitespace and is therefore passing a token that's slightly off. But I'm amazed that we haven't seen this before.

@woodruffw
Copy link
Member

@novitae Could you check your secret, and see whether it has a trailing newline? If so, could you remove it and retry publishing?

@woodruffw
Copy link
Member

This is how we yank the Macaroon from the HTTP headers:

def _extract_basic_macaroon(auth):
    """
    A helper function for extracting a macaroon from a
    HTTP Basic Authentication-style header.

    Returns None if the header doesn't contain a structurally
    valid macaroon, or the candidate (not yet verified) macaroon
    in a serialized form.
    """
    try:
        authorization = base64.b64decode(auth).decode()
        auth_method, _, auth = authorization.partition(":")
    except ValueError:
        return None

    if auth_method != "__token__":
        return None

    return auth

Note that we don't do any whitespace stripping, so this is looking like the culprit to me. So this is not a result of #11122, but just something that's been lurking and (somehow) hadn't been triggered yet.

@woodruffw
Copy link
Member

More root-causing: it looks like the GitHub Action for PyPI publishing also doesn't remove any trailing whitespace from the secret:

https://github.com/pypa/gh-action-pypi-publish/blob/717ba43cfbb0387f6ce311b169a825772f54d295/twine-upload.sh#L52

@novitae
Copy link
Author

novitae commented Apr 20, 2022

Sorry for the late answer @woodruffw

Just for clarification: the Upload Python Package action you're talking about is this one, right? https://github.com/pypa/gh-action-pypi-publish

Yep it's this one

Here's what I did:
...
Am I missing any of your steps, @novitae? I'll try with some different 2FA configurations in a moment as well.

Not really ... Here are the more detailed steps I did (sorry if I wasn't very clear):

  • Creating a new Github repo, cloning it, writing content, making a setup.py, and pushing it to pypi with
    python setup.py sdist
    python3 -m twine upload --repository-url https://upload.pypi.org/legacy/ dist/*
  • Changing few things of its content, changing the setup.py version, pushing to GitHub.
  • In the Github's page of the repo:
    • action -> new action -> Publish Python Package -> configure -> start commit -> commit new file
  • going to pypi.org, login, then account settings:
    • in API tokens -> add api token -> scope on the repo we are working on -> add token -> copy token -> add token
    • here I am getting back to the page I get by clicking "add api token" from the settings, with an error message API token name already in use, even if I remove every tokens of my profile.
    • On my setting page, in API tokens, I am seeing my new token (even if the upper error happened)
  • On my GitHub repo:
    • In settings -> secret -> actions -> new repository secret:
      • Name: PYPI_API_TOKEN
      • Value: paste the copied token (don't remove/add anything)
      • click on add secret
  • Add a new tag OR in actions -> Upload Python Package -> re-run jobs -> re-run all jobs
  • This should happen:

Capture d’écran 2022-04-20 à 23 53 45

  • My python-publish.yml is the absolute default one, but here it is if you want to check it anyway.
  • My PyPI account doesn't have 2FA, but my email is verified

Thanks for your help !

@woodruffw
Copy link
Member

No problem, thanks for following up.

Our current operating theory is that it's a whitespace problem -- could you try re-adding the API token, but making sure that there's no newline after?

@novitae
Copy link
Author

novitae commented Apr 21, 2022

Our current operating theory is that it's a whitespace problem -- could you try re-adding the API token, but making sure that there's no newline after?

So I retried, there's no whitespace for me, I checked many times. Still 403.

@woodruffw
Copy link
Member

Okay, thanks for checking. I'll continue trying to repro.

@di
Copy link
Member

di commented Apr 21, 2022

@novitae Could you try running your release workflow again without changing anything, to see if #11230 resolved this?

@novitae
Copy link
Author

novitae commented Apr 22, 2022

@novitae Could you try running your release workflow again without changing anything, to see if #11230 resolved this?

I generated a new api token, saved them in the repo's secrets, and tried to run, but it failed again. 403 ... very weird

@di
Copy link
Member

di commented Apr 22, 2022

Can you confirm your token starts with pypi-?

@novitae
Copy link
Author

novitae commented Apr 23, 2022

Can you confirm your token starts with pypi-?

yep

@novitae
Copy link
Author

novitae commented Apr 26, 2022

@di @woodruffw so, do you have more for me ? otherwise I could try to create a new pypi account and move all my repos there ...

@di
Copy link
Member

di commented Apr 26, 2022

Hi @novitae, can you send me the token you're trying to use via email to di@python.org?

@novitae
Copy link
Author

novitae commented Apr 26, 2022

Hi @novitae, can you send me the token you're trying to use via email to di@python.org?

@di
Well, this time it worked ! I think I found out the error:
When you're on the page to add token, you save the token, but then, as I was doing, I was going too fast, not reading and scrolling down to click on Add token in Add another token. (On safari, idk for other browsers) The token name field contains the name you filled in the previous initial page to generate the token.
So this was causing me this error API token name already in use, and was making the actual token I saved unusable. Very strange, so long story short, it seems (for me) that Add another token with the same name than the actual one disables the one of the page.

@di
Copy link
Member

di commented Apr 26, 2022

I agree, that is confusing. I made #11260 to resolve it.

@di di reopened this Apr 26, 2022
@di di closed this as completed in #11260 Apr 26, 2022
@JWock82
Copy link

JWock82 commented Dec 7, 2024

I'm having this issue. I tried removing whitespace from my token, creating a new token, and even setting up my github action as a trusted publisher. Still getting error 403. Incredibly frustrating.

@di
Copy link
Member

di commented Dec 7, 2024

@JWock82 Can you open a new issue with more details, like the name of your project, any example GitHub Actions runs, etc?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants