Problem with basicauth + handle_errors

1. Caddy version (caddy version):

v2.3.0 h1:fnrqJLa3G5vfxcxmOH/+kJOcunPLhSBnjgIvjXV/QTA=

2. How I run Caddy:

systemd

a. System environment:

Centos8 + systemd

b. Command:

N/A

c. Service/unit/compose file:

N/A

d. My complete Caddyfile or JSON config:

test.dreamwalkers.dk {

	     basicauth {
            foo JDJhJDE0JEI4TkVYZW5hcElKZEFMVzZtZ1p6TmV6RlFRaUY0NnRWZkUxbTB1MU5GcFBaRU91SEtkbEdD
         }


       reverse_proxy {
                        to 185.52.1.16:8080
                        to 81.4.109.218:8080
                        health_path /health
                        health_interval 1s
                        health_body "(OK)"
        }

        handle_errors {
                @maintenance expression {http.error.status_code} == 502
                rewrite @maintenance /images/502.html

                reverse_proxy https://statictest.dreamwalkers.dk {
                        header_up Host statictest.dreamwalkers.dk
                }
        }

        rewrite * /dreamwalkers/site{uri}

}

3. The problem I’m having:

When using “handle_errors”, i have difficulties also using basicauth. I belive the problem is that http 401 unauthorized is catched by the handle_errors, and never triggering the basicauth directive. Any suggestions to how i should be able to use both basicauth while also handle 502 errors ?

4. Error messages and/or full log output:

Login dialog never shown.

5. What I already tried:

I have tried to move the basicauth around, but that makes no difference

6. Links to relevant resources:

Well, it does trigger basicauth, but basicauth emits the 401 error which is then caught by handle_errors.

Right now, you’re passing all errors through a reverse_proxy. If you meant to only do that for 502s, then you should put all that inside a handle:

handle_errors {
	@maintenance expression {http.error.status_code} == 502
	handle @maintenance {
		rewrite * /images/502.html
		reverse_proxy https://statictest.dreamwalkers.dk {
			header_up Host statictest.dreamwalkers.dk
		}
	}
}

Yes, the handle_errors looks better with the handle, it is of course only the 502 i need to handle but the reverse_proxy, but it do not change that the basichauth is not working. I simply just get and blank page. If i remove the handle_errors, basicauth is working correctly

´´´
test.dreamwalkers.dk {

     basicauth {
        foo JDJhJDE0JEI4TkVYZW5hcElKZEFMVzZtZ1p6TmV6RlFRaUY0NnRWZkUxbTB1MU5GcFBaRU91SEtkbEdD
     }


   reverse_proxy {
                    to 185.52.1.16:8080
                    to 81.4.109.218:8080
                    health_path /health
                    health_interval 1s
                    health_body "(OK)"
    }

handle_errors {
	@maintenance expression {http.error.status_code} == 502
	handle @maintenance {
		rewrite * /images/502.html
		reverse_proxy https://statictest.dreamwalkers.dk {
			header_up Host statictest.dreamwalkers.dk
		}
	}
}

    rewrite * /dreamwalkers/site{uri}

}
´´´

I think you’ll also need to add this after the handle block so that the error HTTP status is preserved:

respond {http.error.status_text} {http.error.status_code}

Huraaa! that fixed it!!

Thank you so much!!

Thomas

Actually, now I’m really confused. The behaviour you’re seeing was fixed over a year ago, well before v2.0.0 stable:

I tried replicating locally and I can’t get it to happen. I’m using a config like this:

{
        admin off
        debug
}

:8883 {
        basicauth {
                foo JDJhJDE0JDd1Li5HMWR5bTBNdUV1ek1QdVlrb09JQUh4V243OVB5QXNkL0NESXdmUzBqYjV0UFZ6VHJT
        }

        handle_errors {
                @nope expression `{http.error.status_code} == 502`
                handle @nope {
                        respond {http.error.status_code}
                }
        }

        respond "Hello World"
}

Running this, I make a request to http://localhost:8883 in my browser. I get the basicauth prompt. If I give a bad user/pass (say bar/bar) the basicauth prompt clears and reloads (Caddy responds with a 401). If I then use the correct credentials foo/foo, then I get a HTTP 200 response with Hello World displayed.

So something funky must be going on. Can you try the above and confirm that it works for you?

1 Like

With your config, i get the same result as you describe, getting 401… BUT, now try to change :8883 to x.x.x.x:8883 or a domain name:8883 then it starts working differently, not giving back 401 but 200

´´´
{
admin off
debug
}

81.4.109.165:8883 {
basicauth {
foo JDJhJDE0JDd1Li5HMWR5bTBNdUV1ek1QdVlrb09JQUh4V243OVB5QXNkL0NESXdmUzBqYjV0UFZ6VHJT
}

    handle_errors {
            @nope expression `{http.error.status_code} == 502`
            handle @nope {
                    respond {http.error.status_code}
            }
    }

    respond "Hello World"

}
´´´

With the above i get 200, and not 401 … As soon as i change 81.4.109.165:8883 to :8883 i get the correct 401 … that is very funky :wink:

1 Like

Actually you can just change it to: 127.0.0.1:80 and then do a curl -vvv http://127.0.0.1/

´´´

  • Trying 127.0.0.1…
  • TCP_NODELAY set
  • Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)

GET / HTTP/1.1
Host: 127.0.0.1
User-Agent: curl/7.61.1
Accept: /

< HTTP/1.1 200 OK
< Server: Caddy
< Www-Authenticate: Basic realm=“restricted”
< Date: Sat, 24 Apr 2021 18:17:07 GMT
< Content-Length: 0
<

  • Connection #0 to host 127.0.0.1 left intact

´´´

1 Like

Oh wow, that’s fascinating. I see what’s going on now. Adapting the configs to JSON with caddy adapt --pretty makes it obvious. Thanks for noticing that.

So when you have a host matcher, the error routes also inherit the host matcher, on a subroute that wraps the other routes. This subroute has terminal marked on it which means that once matched, no handlers are executed past that point. The implicit error handler from the above PR isn’t actually run because it’s appended after the subroute, which is “too late”.

I’ll look to make a patch to fix this, I think we can append the implicit error handler at the end of top-level subroutes maybe. :thinking:

1 Like

Caddy is not only a pleasure to work with. The community behind it is what makes it really really great!! Thanks for your effort and kind help…

3 Likes

Wrote a PR to fix it. Seems to work fine but it’s pretty awkward.

I realized there’s a simpler solution than what I originally implemented, and I updated my PR. Feel free to try it out to confirm yourself.

You can grab the build from the CI artifacts here: caddyhttp: Fix via `routes.go` · caddyserver/caddy@a735af4 · GitHub

1 Like

This topic was automatically closed after 30 days. New replies are no longer allowed.