Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Consent-JWT / Consent-Id / PSD2-CERT header lookups are case-sensitive, so they silently fail over HTTP/2

Aperta Adatta ai principianti
#2,914 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

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à
Attiva
Stack tecnologico
scala

Direzione di ricerca

Inizia da obp-api/src/main/scala/code/api/util/APIUtil.scala leggendo getConsentJWT, getConsentIdRequestHeaderValue, getPSD2-CERT e le ricerche degli header vicine. Cerca nel file filter(_.name == RequestHeader...) e confronta il comportamento con getRequestHeader(). Il lavoro è completato quando i nomi degli header HTTP/2 in minuscolo risolvono gli stessi valori di consenso delle richieste HTTP/1.1 con maiuscole e minuscole miste.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Title: Consent-JWT / Consent-Id / PSD2-CERT header lookups are case-sensitive, so they silently fail over HTTP/2

Several request-header lookups in APIUtil.scala compare the header's
name field with == against a fixed-case literal, instead of doing a
case-insensitive comparison:

// obp-api/src/main/scala/code/api/util/APIUtil.scala
def getConsentJWT(requestHeaders: List[HTTPParam]): Option[String] = {
  requestHeaders.toSet.filter(_.name == RequestHeader.`Consent-JWT`).toList match {
    case x :: Nil => Some(x.values.mkString(", "))
    case _ => requestHeaders.toSet.filter(_.name == RequestHeader.`Consent-Id`).toList match {
      case x :: Nil => Some(x.values.mkString(", "))
      case _ => None
    }
  }
}

The same pattern appears for Consent-ID (a second, differently-cased
variant of the same header exists a few lines below Consent-Id),
PSD2-CERT, and TPP-Signature-Certificate.

Why this breaks under HTTP/2: RFC 7540 §8.1.2 requires HTTP/2 header
field names to be sent in lowercase on the wire. Any HTTP/2 client — which
is most modern HTTP clients by default when talking to a server that
advertises h2 via ALPN — sends consent-jwt, not Consent-JWT. The
== comparison against the mixed-case literal never matches, so
hasConsentJWT/getConsentJWT return false/None even though the
header is present with the correct name and value. The request then falls
through to whatever the next auth branch is, and — in our case — ends up
with a generic OBP-20001: User not logged in instead of ever reaching
Consent.checkConsent/applyConsentRulesCommon, which made this
confusing to diagnose: none of the consent-specific debug logging in
ConsentUtil.scala ever fired, because that code path was never entered.

Reproduction, against a real instance with consents.allowed=true, a
consent already created via POST /obp/v5.1.0/my/consents/IMPLICIT and
successfully answered via POST /obp/v3.1.0/banks/BANK_ID/consents/CONSENT_ID/challenge
(consent status ACCEPTED, verified independently):

# Over HTTP/2 (curl's and most clients' default for an ALPN-h2 server)
curl "https://<host>/obp/v5.1.0/users/current/user_id" \
  -H "Consent-JWT: <the accepted consent's jwt>" \
  -H "Consumer-Key: <consumer key>"
# -> HTTP 401 {"code":401,"message":"OBP-20001: User not logged in. Authentication is required!"}

# Identical request, forced to HTTP/1.1
curl --http1.1 "https://<host>/obp/v5.1.0/users/current/user_id" \
  -H "Consent-JWT: <the same jwt>" \
  -H "Consumer-Key: <consumer key>"
# -> HTTP 200 {"user_id":"..."}

Same consent, same JWT, same headers — the only difference is the wire
casing HTTP/1.1 vs HTTP/2 puts on the header name, and that alone flips
the result between "not logged in" and a correctly resolved user.

Suggested fix: compare header names case-insensitively, the way
getRequestHeader() a few lines below already does it correctly
(_.name.toLowerCase == name.toLowerCase). Applies to at least
getConsentJWT, getConsentIdRequestHeaderValue, `getPSD2-CERT`,
and the Consent-ID variant — worth a broader grep across APIUtil.scala
for the same filter(_.name == RequestHeader...) pattern to catch any
others.

Environment: reproduced against openbankproject/obp-api:latest,
commit b5a5765a185d173392c9d9c8fe36a4381097d954 (current develop HEAD
as of 2026-09-16), Kubernetes (k3s), behind an ingress-nginx TLS
termination that negotiates HTTP/2 with clients — but the bug is in the
header comparison itself and is not specific to this deployment; any
HTTP/2 client hitting these endpoints on any OBP-API instance should
reproduce it the same way.

Lingua principale
Scala
Stelle
1.7k
Fork
483
Merge medio
18h 35m
PR unite (30g)
17

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di OpenBankProject/OBP-API

Tutte le issue di OpenBankProject/OBP-API

Issue simili

Altre issue su Scala

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.