Repository: pypi/warehouse

Issue:
API tokens: Remove @token and pypi: cases
At some point in the future (perhaps at the end of the API token beta?), support for `@token` as a token username and `pypi:` as a token prefix should end in favor of `__token__` and `pypi-`, respectively.

See #6287, #6342.

cc @brainwane @di @ewdurbin @dstufft 




Discussion:
I'm in favor of doing this before the end of the beta, so that we can tell beta testers to try the new token usernames and prefixes, so we can find out during the beta whether the new ones cause any glitches.
would it be too much to just reserve the "token" username? Is it already in use? GitHub does that for things like "issues" etc.
Looks like the `token` username is unused: https://pypi.org/user/token/
@fschulze @hugovk you want something that other pypis eg devpi can use so you want something that was impossible to register previously
I’ve gone ahead and squatted that name.

Obviously, I’m cool with just removing that account or let PyPI admins do whatever they deem necessary with that name.
how about '🎟' as the username? eg "\N{ADMISSION TICKETS}"
@graingert what does the pypi.org username have to do with devpi? The ``devpi push`` command needs the pypi credentials anyway when used for pypi release.
@fschulze devpi would probably want to support this API token authentication scheme too. If an install has a user called "token" it would break that user for them. I'm thinking downstream "twine upload -r devpi" not upstream pypi
@graingert it would use separate credentials anyway as it already does now. I don't see any reason accounts on pypi would interfere with devpi or the other way around.
Yes but the "token" username is part of the API tokens Auth protocol
@graingert yes and it doesn't matter in devpi, because the API is specific to pypi.org. Otherwise all users in devpi would conflict with pypi.org already. If we implement upload tokens in devpi, then we would handle that on the devpi side. It is pretty easy to determine whether a token was used or not. Any ``token`` user in devpi would not interfere, because we can check whether we got a token or not by inspecting or validating it. So twine would work with devpi as soon as we would add token support and we wouldn't even have to block the ``token`` user name.
It's ultimately the maintainers' call, but I'm 👎 on plain `token` (or similar) for a few reasons:

1. Semantically, tokens are not passwords, so it doesn't make sense for them to have a valid username associated with them (apart from their relationship to the bearing user). The only reason we have a "username" at all in the scheme is backwards compatibility with `Authorization: basic` -- IIUC, the eventual plan is to update tools like `twine` and `setuptools` to use `Authorization: token <macaroon>` directly.
1. Similarly, it's _especially_ confusing to have a valid, _different_ username (e.g., the squatted `token`) built into the validation scheme for all users' tokens.
1. `^token` or similar is a lot easier to search for than `token`.
Is there a regex of currently valid PyPI usernames so we can be more informed when picking an intentionaly invalid one?
https://github.com/pypa/warehouse/blob/fe4b61d3e9f9bea4fa037de4aa17fac6599b63c2/warehouse/accounts/models.py#L60-L66
so some examples:

`_token`, `-token`, `.token`
`token_`, `token-`, `token.`

and my personal favorite:
`__token__`
`tokentokentokentokentokentokentokentokentokentokentoken` is also an invalid username because it is too long
`__token__` me likey.

Resolving patch:
diff --git a/warehouse/macaroons/auth_policy.py b/warehouse/macaroons/auth_policy.py
--- a/warehouse/macaroons/auth_policy.py
+++ b/warehouse/macaroons/auth_policy.py
@@ -38,8 +38,7 @@ def _extract_basic_macaroon(auth):
     except ValueError:
         return None
 
-    # TODO: Remove @token as an acceptable token username (GH-6345)
-    if auth_method != "@token" and auth_method != "__token__":
+    if auth_method != "__token__":
         return None
 
     return auth
diff --git a/warehouse/macaroons/services.py b/warehouse/macaroons/services.py
--- a/warehouse/macaroons/services.py
+++ b/warehouse/macaroons/services.py
@@ -43,12 +43,8 @@ def _extract_raw_macaroon(self, prefixed_macaroon):
         if prefixed_macaroon is None:
             return None
 
-        prefix, split, raw_macaroon = prefixed_macaroon.partition("-")
-        # TODO: Remove ':' as an acceptable delimiter for tokens (GH-6345)
-        if prefix != "pypi" or not split:
-            prefix, _, raw_macaroon = prefixed_macaroon.partition(":")
-
-        if prefix != "pypi":
+        prefix, _, raw_macaroon = prefixed_macaroon.partition("-")
+        if prefix != "pypi" or not raw_macaroon:
             return None
 
         return raw_macaroon


Test patch:
diff --git a/tests/unit/macaroons/test_auth_policy.py b/tests/unit/macaroons/test_auth_policy.py
--- a/tests/unit/macaroons/test_auth_policy.py
+++ b/tests/unit/macaroons/test_auth_policy.py
@@ -31,7 +31,6 @@
         ("notarealtoken", None),
         ("maybeafuturemethod foobar", None),
         ("token foobar", "foobar"),
-        ("basic QHRva2VuOmZvb2Jhcg==", "foobar"),  # "@token:foobar"
         ("basic X190b2tlbl9fOmZvb2Jhcg==", "foobar"),  # "__token__:foobar"
     ],
 )
@@ -49,7 +48,6 @@ def test_extract_http_macaroon(auth, result):
         ("notbase64", None),
         ("bm90YXJlYWx0b2tlbg==", None),  # "notarealtoken"
         ("QGJhZHVzZXI6Zm9vYmFy", None),  # "@baduser:foobar"
-        ("QHRva2VuOmZvb2Jhcg==", "foobar"),  # "@token:foobar"
         ("X190b2tlbl9fOmZvb2Jhcg==", "foobar"),  # "__token__:foobar"
     ],
 )
diff --git a/tests/unit/macaroons/test_services.py b/tests/unit/macaroons/test_services.py
--- a/tests/unit/macaroons/test_services.py
+++ b/tests/unit/macaroons/test_services.py
@@ -44,7 +44,6 @@ def test_creation(self):
             (None, None),
             ("noprefixhere", None),
             ("invalid:prefix", None),
-            ("pypi:validprefix", "validprefix"),
             ("pypi-validprefix", "validprefix"),
         ],
     )