Authorization header parsing is case sensitive and consumes non-Bearer schemes, so a valid __session cookie is ignored
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 78/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Tranquilla
- Stack tecnologico
- python
- Ambito
- authentication
Direzione di ricerca
Inizia in clerk_backend_api/security/authenticaterequest.py da _get_session_token e traccia come authenticate_request e authenticate_request_async utilizzano il relativo risultato. Aggiungi una copertura mirata per gli schemi Bearer senza distinzione tra maiuscole e minuscole, gli spazi aggiuntivi e gli header Authorization non-Bearer che ricadono su __session; il lavoro è completo quando entrambi i percorsi autenticano il token valido in questi casi.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
_get_session_token in clerk_backend_api/security/authenticaterequest.py pulls the token
out of the header with
bearer_token = request.headers.get('Authorization')
if bearer_token is not None:
return bearer_token.replace('Bearer ', '')
That is a substring delete and it is case sensitive, so two ordinary requests fail to
authenticate when they should not.
Reproduction
clerk-backend-api 6.0.1. I generate an RSA key locally, sign a session-shaped JWT with it and
pass the public PEM as jwt_key, so verification is real and needs no Clerk instance.
opts = AuthenticateRequestOptions(jwt_key=PUBLIC_PEM)
authenticate_request(Req({"Authorization": "bearer " + token}), opts)
Authorization: Bearer <token> -> signed-in
Authorization: bearer <token> -> signed-out token-invalid
Authorization: BEARER <token> -> signed-out token-invalid
Authorization: Bearer <token> (2 spaces) -> signed-out token-invalid-signature
cookie only, __session=<token> -> signed-in
Authorization: Basic ... plus a valid __session cookie -> signed-out token-invalid
Same run, as a control, so this is not a harness that fails everything: a matching
authorized_parties signs in and returns sub, a non-matching one gives
token-invalid-authorized-parties, an expired token gives token-expired, and a token signed
by a different key gives token-invalid-signature.
Two more details from the same line. 'Bearer aBearer b' extracts 'ab', and with a Basic
header present the extractor returns the literal string Basic dXNlcjpwYXNzd29yZA==, which
get_token_type then classifies as a SESSION_TOKEN.
authenticate_request_async shares the extractor, so both paths behave the same.
Why I think it is worth fixing
RFC 7235 section 2.1 makes the auth-scheme case insensitive, so bearer is a legal header that
this SDK rejects. The second case is the one I would worry about more. An app behind basic auth
(staging environments, some proxies) has its Authorization header set by something other than
Clerk, and the valid __session cookie is then never looked at, because the header is consumed
whatever it contains.
A prefix check would cover both:
value = request.headers.get('Authorization')
if value is not None:
scheme, _, rest = value.partition(' ')
if scheme.lower() == 'bearer' and rest.strip():
return rest.strip()
# fall through to the cookie instead of returning a non-token
Happy to send that as a PR with tests if you would rather review a diff.
How I found it, and what I am not claiming
I maintain a test harness that measures whether coding models can drive a given SDK, by running
the code they write and asserting on the HTTP that comes out. This finding did not come from
that. I read the token extraction path while looking at how the SDK handles credentials, and
these cases came from constructing them.
No model produced this, so it is latent rather than measured, and I would rather say so.
One limit on the repro: I sign the token myself and verify it networklessly with jwt_key, so
what I can show is which headers your extractor accepts. Whether your hosted instances ever see
a lowercase scheme in practice is your data, not mine.
toolshed is a small studio run by its owner, who directs the work, and AI does a lot of the
engineering.
Cal / toolshed / [email protected]
- Lingua principale
- Python
- Stelle
- 186
- Fork
- 47
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di clerk/clerk-sdk-python
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
clerk/clerk-sdk-python#241 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
clerk/clerk-sdk-python#227 ·
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 62/100
clerk/clerk-sdk-python#231 ·
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 38/100
clerk/clerk-sdk-python#230 ·
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 55/100
clerk/clerk-sdk-python#229 ·
Tutte le issue di clerk/clerk-sdk-python
Issue simili
-
feedback simulation workshop
Difficoltà 2/5 1-3 ore Idoneità per principianti 73/100
githubnext/gh-aw-workshop#4455 ·
I maintainer di solito rispondono entro 1 giorno
-
Triage 🩺
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
-
[BUG] Container scenario crashes without expected_recovery_time, kube DNS example uses retry_waitApertaneeds-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 77/100
krkn-chaos/krkn#1627 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
NousResearch/hermes-agent#136483 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
I maintainer di solito rispondono entro 1 giorno