Search code examples
haproxy

HAProxy set authorization header from cookie


I have a backend that I don't control that works using magic links. If I use the magic link, I don't have to log on. I want to share the magic link externally without exposing the actual key as the key changes from time to time and I was hoping to use haproxy as a reverse proxy. I don't want the link to be open to the entire internet and would like to use basic auth as well. The problem I am facing is that the backend overwrites the Authorization header (it's required for the magic link to work) and I get stuck in a loop and need to log on every time

My workaround:

  • On first request I request the basic auth (works)
  • Then I write it to a cookie (this part works)
  • On each subsequent request, if the cookie exists, I read the cookie and set the Authorization header to the cookie value (this part does not work)
  • Then I run http_auth which in my mind should now work since I have overwritten the header

But it does not work. Any suggestions?

userlist auth-list
  user myuser insecure-password mypass

frontend myfrontend
   bind *:80
   mode http
   acl is-path path -i -m beg /publiclink
   acl has_cookie req.hdr(X-MyAuth) -m found
   http-request set-header Authorization %[req.hdr(X-MyAuth)] if has_cookie
   http-request auth unless { http_auth(auth-list) }
   http-request set-var(txn.myhostheader) req.hdr(Authorization) if { http_auth(auth-list) !has_cookie }
   default_backend node

backend node
    mode http
    server dcnode1 192.168.0.1:8000 check
    http-response set-header set-cookie "X-MyAuth=%[var(txn.myhostheader)]; Path=/" if  { var(txn.myhostheader) -m found }
    http-request replace-path /publiclink1(.*) /magiclink\1
    http-request set-header Authorization "Key magiclink"

Solution

  • My answer is related to this point :

    • On each subsequent request, if the cookie exists, I read the cookie and set the Authorization header to the cookie value (this part does not work)

    In your backend, you set the Set-Cookie: X-MyAuth=... header :

    backend node
        http-response set-header set-cookie "X-MyAuth=%[var(txn.myhostheader)]; Path=/" if  { var(txn.myhostheader) -m found }
    
    

    So the next request contains a Cookie header like this one : Cookie: .* X-MyAuth=.*.

    But in your frontend, you use the X-MyAuth header (which probably does not exist) :

    frontend myfrontend
       acl has_cookie req.hdr(X-MyAuth) -m found
       http-request set-header Authorization %[req.hdr(X-MyAuth)] if has_cookie
    

    You may use the X-MyAuth cookie value like this :

    frontend myfrontend
       acl has_cookie cook(X-MyAuth) -m found
       http-request set-header Authorization %[cook(X-MyAuth)] if has_cookie