]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: http: Add http_auth_bearer sample fetch
authorRemi Tricot-Le Breton <rlebreton@haproxy.com>
Fri, 1 Oct 2021 13:36:53 +0000 (15:36 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Thu, 14 Oct 2021 14:38:07 +0000 (16:38 +0200)
This fetch can be used to retrieve the data contained in an HTTP
Authorization header when the Bearer scheme is used. This is used when
transmitting JSON Web Tokens for instance.

doc/configuration.txt
include/haproxy/http-t.h
src/http_fetch.c

index 621ca2fb145a2468eaa1c9438067b52c00ceee24..5466487ea6d69c5da9258e1abc03791b0d068ab8 100644 (file)
@@ -20038,6 +20038,13 @@ http_auth(<userlist>) : boolean
   fetch function is not really useful outside of ACLs. Currently only http
   basic auth is supported.
 
+http_auth_bearer([<header>]) : string
+  Returns the client-provided token found in the authorization data when the
+  Bearer scheme is used (to send JSON Web Tokens for instance). No check is
+  performed on the data sent by the client.
+  If a specific <header> is supplied, it will parse this header instead of the
+  Authorization one.
+
 http_auth_group(<userlist>) : string
   Returns a string corresponding to the user name found in the authentication
   data received from the client if both the user name and password are valid
index c6c50c95e1d3c5cb516cdfb608377632449858cd..3165082f9e5a616569d088a2e6d9f089ecc553a5 100644 (file)
@@ -77,6 +77,7 @@ enum ht_auth_m {
        HTTP_AUTH_UNKNOWN       = 0,
        HTTP_AUTH_BASIC,
        HTTP_AUTH_DIGEST,
+       HTTP_AUTH_BEARER,
 } __attribute__((packed));
 
 /* All implemented HTTP status codes */
index d3192aa6c47a3a4b165a5588715ca84803cb97c7..7b4e41d85f3eeda4f5be6a20ac0178b7ab70904d 100644 (file)
@@ -146,6 +146,9 @@ static int get_http_auth(struct sample *smp, struct htx *htx)
 
                txn->auth.method = HTTP_AUTH_BASIC;
                return 1;
+       } else if (!strncasecmp("Bearer", auth_method.area, auth_method.data)) {
+               txn->auth.method = HTTP_AUTH_BEARER;
+               return 1;
        }
 
        return 0;
@@ -1291,6 +1294,10 @@ static int smp_fetch_http_auth_type(const struct arg *args, struct sample *smp,
                        smp->data.u.str.area = "Digest";
                        smp->data.u.str.data = 6;
                        break;
+               case HTTP_AUTH_BEARER:
+                       smp->data.u.str.area = "Bearer";
+                       smp->data.u.str.data = 6;
+                       break;
                default:
                        return 0;
        }
@@ -1313,7 +1320,7 @@ static int smp_fetch_http_auth_user(const struct arg *args, struct sample *smp,
                return 0;
 
        txn = smp->strm->txn;
-       if (!get_http_auth(smp, htx))
+       if (!get_http_auth(smp, htx) || txn->auth.method != HTTP_AUTH_BASIC)
                return 0;
 
        smp->data.type = SMP_T_STR;
@@ -1336,7 +1343,7 @@ static int smp_fetch_http_auth_pass(const struct arg *args, struct sample *smp,
                return 0;
 
        txn = smp->strm->txn;
-       if (!get_http_auth(smp, htx))
+       if (!get_http_auth(smp, htx) || txn->auth.method != HTTP_AUTH_BASIC)
                return 0;
 
        smp->data.type = SMP_T_STR;
@@ -1346,6 +1353,43 @@ static int smp_fetch_http_auth_pass(const struct arg *args, struct sample *smp,
        return 1;
 }
 
+static int smp_fetch_http_auth_bearer(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+       struct channel *chn = SMP_REQ_CHN(smp);
+       struct htx *htx = smp_prefetch_htx(smp, chn, NULL, 1);
+       struct http_txn *txn;
+       struct buffer bearer_val = {};
+
+       if (!htx)
+               return 0;
+
+       if (args->type == ARGT_STR) {
+               struct http_hdr_ctx ctx;
+               struct ist hdr_name = ist2(args->data.str.area, args->data.str.data);
+
+               ctx.blk = NULL;
+               if (http_find_header(htx, hdr_name, &ctx, 0)) {
+                       char *space = NULL;
+                       space = memchr(ctx.value.ptr, ' ', ctx.value.len);
+                       if (space && strncasecmp("Bearer", ctx.value.ptr, ctx.value.len) == 0) {
+                               chunk_initlen(&bearer_val, space+1, 0, ctx.value.len - (space - ctx.value.ptr) - 1);
+                       }
+               }
+       }
+       else {
+               txn = smp->strm->txn;
+               if (!get_http_auth(smp, htx) || txn->auth.method != HTTP_AUTH_BEARER)
+                       return 0;
+
+               bearer_val = txn->auth.method_data;
+       }
+
+       smp->data.type = SMP_T_STR;
+       smp->data.u.str = bearer_val;
+       smp->flags = SMP_F_CONST;
+       return 1;
+}
+
 /* Accepts exactly 1 argument of type userlist */
 static int smp_fetch_http_auth(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
@@ -1357,7 +1401,7 @@ static int smp_fetch_http_auth(const struct arg *args, struct sample *smp, const
 
        if (!htx)
                return 0;
-       if (!get_http_auth(smp, htx))
+       if (!get_http_auth(smp, htx) || smp->strm->txn->auth.method != HTTP_AUTH_BASIC)
                return 0;
 
        smp->data.type = SMP_T_BOOL;
@@ -1377,7 +1421,7 @@ static int smp_fetch_http_auth_grp(const struct arg *args, struct sample *smp, c
 
        if (!htx)
                return 0;
-       if (!get_http_auth(smp, htx))
+       if (!get_http_auth(smp, htx) || smp->strm->txn->auth.method != HTTP_AUTH_BASIC)
                return 0;
 
        /* if the user does not belong to the userlist or has a wrong password,
@@ -2097,6 +2141,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
        { "http_auth_type",     smp_fetch_http_auth_type,     0,                NULL,    SMP_T_STR,  SMP_USE_HRQHV },
        { "http_auth_user",     smp_fetch_http_auth_user,     0,                NULL,    SMP_T_STR,  SMP_USE_HRQHV },
        { "http_auth_pass",     smp_fetch_http_auth_pass,     0,                NULL,    SMP_T_STR,  SMP_USE_HRQHV },
+       { "http_auth_bearer",   smp_fetch_http_auth_bearer,   ARG1(0,STR),      NULL,    SMP_T_STR,  SMP_USE_HRQHV },
        { "http_auth",          smp_fetch_http_auth,          ARG1(1,USR),      NULL,    SMP_T_BOOL, SMP_USE_HRQHV },
        { "http_auth_group",    smp_fetch_http_auth_grp,      ARG1(1,USR),      NULL,    SMP_T_STR,  SMP_USE_HRQHV },
        { "http_first_req",     smp_fetch_http_first_req,     0,                NULL,    SMP_T_BOOL, SMP_USE_HRQHP },