Basicauth does not work/prompt under certain circumstances

1. Caddy version (caddy version):

v2.1.1 h1:X9k1+ehZPYYrSqBvf/ocUgdLSRIuiNiMo7CvyGUQKeA=

2. How I run Caddy:

a. System environment:

Official Alpine Docker image/container from Docker Hub.

b. Service/unit/compose file:

  caddy:
    image: caddy:alpine
    container_name: caddy
    restart: unless-stopped
    labels:
      - com.centurylinklabs.watchtower.enable=true
    ports:
      - "4443:443"
      - "8080:80"
    networks:
      - redacted
    volumes:
      - ./caddy/data:/data
      - ./caddy/config:/config
      - ./caddy/Caddyfile:/etc/caddy/Caddyfile
      - /mnt/media/websites:/www/websites:ro
    env_file: ./envs/common.env

c. My complete Caddyfile or JSON config:

http:// {
  basicauth /* {
    username password
  }
  handle_errors {
    rewrite * /{http.error.status_code}
    reverse_proxy https://http.cat
  }
  handle {
    root / /www/websites/
    file_server
  }
}

3. The problem I’m having:

With the above Caddyfile, there is no prompt for basic auth. You’re immediately displayed the 401 status page (in this case that is https://http.cat/401). The handle_errors solution is from this github issue.

4. Error messages and/or full log output:

N/A

5. What I already tried:

Commenting or removing

  handle_errors {
    rewrite * /{http.error.status_code}
    reverse_proxy https://http.cat
  }

resolves the issue, so there seems to be an issue with order of operations preventing the auth prompt from ever appearing.

I’m open to either the order of operations being changed at the source or a different solution to error handling that would resolve this.

First thing, I’d make a few minor adjustments to your Caddyfile (no need for /* matcher on basicauth, it’s redundant; no need for the handle, and root / would only set root on requests to / but nothing else, should use * instead):

This is very strange though… I can replicate the issue like this:

:8884 {
  basicauth {
    foo JDJhJDE0JDBoOFVrd05IanNia3hFY2lSOEZvLnVZYm8uS0QxUGFFT2FtSHpMWmo4QUNsTW5jTm93UFVH
  }

  handle_errors {
    reverse_proxy https://google.com
  }

  respond "Foo"
}

Just the fact that there’s a reverse_proxy in handle_errors makes it fail.

The reason for this ultimately is that reverse_proxy will override the 401 status code that when combined with the Www-Authenticate Basic realm="restricted" header, actually triggers the basicauth prompt.

I’m not sure what the best solution to solve this would be. Maybe your backend will need to set the status to the same as the URL it serves for error pages?

@matt any ideas?

Just the fact that there’s a reverse_proxy in handle_errors makes it fail.

The reason for this ultimately is that reverse_proxy will override the 401 status code that when combined with the Www-Authenticate Basic realm="restricted" header, actually triggers the basicauth prompt.

Thanks for confirming I’m not insane, at least. :slight_smile:

First thing, I’d make a few minor adjustments to your Caddyfile (no need for /* matcher on basicauth, it’s redundant; no need for the handle , and root / would only set root on requests to / but nothing else, should use * instead):

I’ve made a ton of changes (and it’s in prod instead of internal testing!). Though it’s technically off-topic for this help thread, I’m always open to feedback for improvement.

As a general side note, it’s been completely random on which reverse proxied applications prefer a handle_path or a route. Not the fault of Caddy, really, just something strange I’ve noticed.


Edit: This is also outside of the scope of this thread, but my logs are filled with these:

caddy                | {"level":"error","ts":1599794626.0378284,"logger":"http.handlers.reverse_proxy","msg":"aborting with incomplete response","error":"context canceled"}
caddy                | {"level":"error","ts":1599794626.982335,"logger":"http.handlers.reverse_proxy","msg":"aborting with incomplete response","error":"context canceled"}
caddy                | {"level":"error","ts":1599794635.2733538,"logger":"http.handlers.reverse_proxy","msg":"aborting with incomplete response","error":"context canceled"}
caddy                | {"level":"error","ts":1599794646.3870308,"logger":"http.handlers.reverse_proxy","msg":"aborting with incomplete response","error":"context canceled"}

Everything seems to be working flawlessly…so it doesn’t hurt anything, just strange.

Re: the logs – I narrowed it down to Plex being proxied causing that. I’ll open a separate thread.