JWT Validation in HAProxy
Asked Answered
I

4

11

I have an HAProxy configured to accept requests to *.mysubdomain.com. The HAProxy will parse the subdomain (prod or dev from prod.mysubdomain.com or dev.mysubdomain.com) and forward to the correct backend. Two backends exist, one for prod and one for dev. Each backend contains two server entries pointing towards Marathon LB instances on each subdomain.

The subdomains require a JWT cookie for authentication on the backend. I have the public key to check the validity of the JWT, but would like to do so in the HAProxy. Is there a way to add my own code to perform the JWT validity check within the HAProxy configuration?

The HAProxy configuration file is as follows:

global
    maxconn 256

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend http-in
    bind *:80
    mode http

    # Returns true when one of the headers contains one of the strings either isolated or delimited by dots. This is used to perform domain name matching.
    acl host_dev hdr_dom(host) -i dev
    acl host_prod hdr_dom(host) -i prod

    acl jwtPresent req.cook(JWT) -m found

    use_backend prod_domain if jwtPresent host_prod
    use_backend dev_domain if jwtPresent host_dev

    default_backend prod_domain

backend prod_domain
    balance roundrobin
    server prodDomain1 "${MARATHON_LB_PROD_1}" maxconn 32 check
    server prodDomain2 "${MARATHON_LB_PROD_2}" maxconn 32 check

backend dev_domain
    balance roundrobin
    server devDomain1 "${MARATHON_LB_DEV_1}" maxconn 32 check
    server devDomain2 "${MARATHON_LB_DEV_2}" maxconn 32 check
Irrelevant answered 16/3, 2017 at 13:57 Comment(1)
Me too! It would be even better, if HAP could inject claims as Request Headers.Ursi
S
5

HAProxy can act as an API gateway and validate JWT tokens against a public key. They have written a blog post and provided sample code to show you how.

The post is here: https://www.haproxy.com/blog/using-haproxy-as-an-api-gateway-part-2-authentication/

The sample lua code is here: https://github.com/haproxytech/haproxy-lua-jwt

Streaming answered 9/2, 2019 at 14:35 Comment(0)
W
4

As the other answer pointed out, you have to use Lua script. You can use existing implementations from lua-resty-jwt or Kong.

Notes:

  • Those code-bases are not concise. A simple copy & paste won't work. So you have to extract the bare minimum you need.
  • You can't have dependencies in your Lua script. Only plain vanilla Lua. So you have to get rid of all require statements.
  • The tricky part is the HMAC implementation.
  • Avoid any I/O operation in your Lua script, e.g. file, database, network operations.

It's not an easy undertaking. Good luck! It's something worth sharing.

Weapon answered 9/3, 2018 at 0:30 Comment(0)
I
1

As of version 2.5 HAProxy now has an inbuilt function for validating JWTs, so you dont need to use lua script anymore.

https://www.haproxy.com/blog/verify-oauth-jwt-tokens-with-haproxy

https://docs.haproxy.org/2.8/configuration.html#7.3.1-jwt_verify

Impend answered 19/9, 2023 at 9:56 Comment(0)
I
0

As far as I could tell, HAProxy does not have the functionality to perform the logic for validating the JWT. Instead, I implemented a script in Lua for haproxy.cfg to call to perform the validation:

global
    maxconn 256
    lua-load /choose_backend.lua

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend http-in
    bind *:80

    http-request set-header X-SSL-Client-DN             %{+Q}[ssl_c_s_dn]


    http-request set-var(txn.backend_name) lua.backend_select()
    use_backend %[var(txn.backend_name)]

backend prod_domain
    balance roundrobin
    server prodDomain1 "${MARATHON_LB_PROD_1}" maxconn 32 check
    server prodDomain2 "${MARATHON_LB_PROD_2}" maxconn 32 check

backend dev_domain
    balance roundrobin
    server devDomain1 "${MARATHON_LB_DEV_1}" maxconn 32 check
    server devDomain2 "${MARATHON_LB_DEV_2}" maxconn 32 check
Irrelevant answered 28/6, 2017 at 20:34 Comment(1)
Could you share the lua script, too?Gnathonic

© 2022 - 2024 — McMap. All rights reserved.