]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MINOR: sample: return the decoded JWT part when no path is given
authorWilly Tarreau <w@1wt.eu>
Tue, 22 Sep 2026 20:16:59 +0000 (20:16 +0000)
committerWilly Tarreau <w@1wt.eu>
Wed, 30 Sep 2026 14:11:24 +0000 (16:11 +0200)
jwt_header_query() and jwt_payload_query() are documented to return the
decoded header or payload of the token when they are called without any
argument. sample_conv_jwt_member_query() does fill the sample in that
case, but it jumps to its exit label while <retval> still holds the
zero it was initialized with, so the converter reports a failure and
the expression yields nothing at all.

Only the form taking a JSON path worked, which is the one the reg-test
used, hence the bug going unnoticed. The test now reads both parts of
the token without any argument as well.

The issue arrived in 2.5 with the original commit 0a72f5ee7c ("MINOR:
jwt: jwt_header_query and jwt_payload_query converters") so this fix
can be backported to all stable branches.

reg-tests/jwt/jws_verify.vtc
src/sample.c

index 724c60c893cbbab35f798522b6ae41d0f93c10d2..466109aa9eb450df8b4b88158bd9f12a2e53de71 100644 (file)
@@ -62,6 +62,15 @@ haproxy h1 -conf {
         http-response set-header x-jwt-token %[var(txn.bearer)]
         http-response set-header x-jwt-alg %[var(txn.jwt_alg)]
 
+        # both query converters return the decoded part they are named
+        # after when they are called without any argument, and perform a
+        # json_query on it otherwise
+        http-response set-header x-jwt-header %[var(txn.bearer),jwt_header_query]
+        http-response set-header x-jwt-payload %[var(txn.bearer),jwt_payload_query]
+        http-response set-header x-jwt-sub %[var(txn.bearer),jwt_payload_query('$.sub')]
+        http-response set-header x-jwt-iat %[var(txn.bearer),jwt_payload_query('$.iat',"int"),add(1)]
+        http-response set-header x-jwt-nokey %[var(txn.bearer),jwt_payload_query('$.nokey')]
+
         http-response set-header x-jwt-verify-HS256 %[var(txn.bearer),jwt_verify(txn.jwt_alg,"hmac key hs256")] if { var(txn.jwt_alg) -m str "HS256" }
         http-response set-header x-jwt-verify-HS384 %[var(txn.bearer),jwt_verify(txn.jwt_alg,"hmac key hs384")] if { var(txn.jwt_alg) -m str "HS384" }
         http-response set-header x-jwt-verify-HS512 %[var(txn.bearer),jwt_verify(txn.jwt_alg,"hmac key hs512")] if { var(txn.jwt_alg) -m str "HS512" }
@@ -165,6 +174,13 @@ client c1 -connect ${h1_mainfe_sock} {
     expect resp.status == 200
     expect resp.http.x-jwt-alg == "HS256"
     expect resp.http.x-jwt-verify-HS256 == "1"
+    # the two parts of that token are {"alg":"HS256","typ":"JWT"} and
+    # {"sub":"1234567890","name":"John Doe","iat":1516239022}
+    expect resp.http.x-jwt-header ~ "\"alg\":\"HS256\""
+    expect resp.http.x-jwt-payload ~ "\"name\":\"John Doe\""
+    expect resp.http.x-jwt-sub == "1234567890"
+    expect resp.http.x-jwt-iat == "1516239023"
+    expect resp.http.x-jwt-nokey == ""
 } -run
 
 client c2 -connect ${h1_mainfe_sock} {
index d110ff7b7b0ec77f13f6857d4aeea66b36475584..c34f143a8e0b102f03b1112a367bb188c7e88798 100644 (file)
@@ -5083,6 +5083,7 @@ static int sample_conv_jwt_member_query(const struct arg *args, struct sample *s
        if (args[0].type != ARGT_STR) {
                smp->data.u.str = *decoded_header;
                smp->data.type = SMP_T_STR;
+               retval = 1;
                goto end;
        }