nosduco / nforwardauth

Simple and minimalist forward auth service intended for use with reverse proxies (Traefik, Caddy, nginx, etc)
MIT License
116 stars 3 forks source link

Basic auth in URL not working with Caddy #15

Open damomato opened 1 year ago

damomato commented 1 year ago

Thanks for your work on this, everything is working great except I can't pass basic auth through the url to skip the login page.

For example, http://user:pass@service.example.xyz just takes me to the login page without signing in.

I'm guessing its due to something I need to add to my Caddy config? I've provided my docker and caddy set up below.

Docker compose

services:
  nforwardauth:
    image: nosduco/nforwardauth:v1
    container_name: auth
    environment:
      - PUID=1026
      - PGID=1000
      - TZ=Country/City
      - TOKEN_SECRET=examplesecret
      - AUTH_HOST=auth.example.xyz
      - COOKIE_DOMAIN=example.xyz
      - PORT=3000
    volumes:
      - ./passwd/passwd.txt:/passwd:ro
    ports:
      - 3000:3000
    restart: unless-stopped 

Caddyfile

auth.example.xyz {
    reverse_proxy http://127.0.0.1:3000
}

service.example.xyz {
    forward_auth http://127.0.0.1:3000 {
        uri /
    }
    reverse_proxy http://127.0.0.1:1111
}
nosduco commented 1 year ago

Hey! Glad it's working great for the most part :)

I did some quick research. ref: https://caddyserver.com/docs/caddyfile/directives/forward_auth#syntax

Looks like we can pass the "Authorization" header to nforwardauth by using the copy_headers directive inside the forward_auth block. HTTP basic auth works under the hood by sending a calculated Authorization header.

Could you try something like this and let me know if it works?

forward_auth http://127.0.0.1:3000 {
    uri /
        copy_headers Authorization
}

Thanks!

damomato commented 1 year ago

Unfortunately still not working. I forgot to mention that I was getting an error message when I tried the URL with user:pass in it. Still occuring even after that change. I'm using a private/incognito browser for testing.

"You are about to log in to the site “service.example.xyz” with the username “user”, but the web site does not require authentication. This may be an attempt to trick you.

Is “service.example.xyz” the site you want to visit?"

and clicking "Yes" takes me to the nforwardauth login page

otbutz commented 1 year ago

@nosduco copy-headers works the other way round:

copy_headers is a list of HTTP header fields to copy from the response to the original request, when the request has a success status code.

I think this might work:

forward_auth http://127.0.0.1:3000 {
    uri /
        header_up Authorization {header.Authorization}
}
damomato commented 1 year ago

Unfortunately I'm getting a HTTP ERROR 502 with that change.

otbutz commented 1 year ago

@damomato you might want to ask over at https://caddy.community/

damomato commented 1 year ago

Good idea. I'm not in a rush to get this resolved so I'll sit on it for a little bit and bring the question over there if no one has a solution here.

nosduco commented 1 year ago

Thanks, guys, I'm going to try and reproduce locally today and see where I can get with it. Caddy can be quirky sometimes.

nosduco commented 1 year ago

@damomato I believe this is a browser thing, which browser are you using?

The header is getting passed by default, and I can confirm through:

$ curl http://test:test@whoami.localhost.com
Hostname: bd5ad65a2fe0
IP: 127.0.0.1
IP: 172.18.0.2
RemoteAddr: 172.18.0.4:32814
GET / HTTP/1.1
Host: whoami.localhost.com
User-Agent: curl/8.1.2
Accept: */*
Accept-Encoding: gzip
Authorization: Basic dGVzdDp0ZXN0
X-Forwarded-For: 172.18.0.1
X-Forwarded-Host: whoami.localhost.com
X-Forwarded-Proto: http

when using my example in examples/caddy-v2/. It should be functional for things like nzb360 or other services that will hit the host directly instead of a browser. I will look into what we may be able to do to handle browser connections though.

damomato commented 1 year ago

I've been going between firefox and chrome private/incognito browsers.

I tested it this out on nzb360 instead of a browser and the logs show the following: When just using uri / or your solution nothing shows up. When using otbutz's solution of header_up Authorization {header.Authorization} I get the following error

thread 'tokio-runtime-worker' panicked at 'called Result::unwrap() on an Err value: InvalidAuthorizationHeader', src/main.rs:166:76

Also just checked with a browser and same thing happening with the logs.

Also my password doesn't contain any special characters, just letters and numbers

nosduco commented 1 year ago

You shouldn't have to do the header_up directive. It should be passing the header automatically with the forward_auth directive. My apologies for the misdirection there. My recommendation would be to just use the nforwardauth login page when using the browser, and use the basic auth when it's a service like nzb360 or others for accessing it. Are you having trouble even with nzb360?

damomato commented 1 year ago

Yeah having trouble with nzb360 as well. I run caddy by downloading the release on GitHub, not through docker, so maybe that's playing a part in this

Thanks for trying to get this working I appreciate that, shame we haven't found a solution. I'll sit on this for a bit longer and will ask on the caddy forum later.

bt90 commented 1 year ago

I think i found the issue.

Basic auth:

curl -vvv 'https://user:password@service.exmaple.com/'

The caddy example is fine as it is. The HTTP status code 302 is the problem in this case:

If the upstream responds with a 2xx status code, then access is granted and the header fields in copy_headers are copied to the original request, and handling continues

If nfordwardauth would simply return HTTP 200, things should work as expected.

bt90 commented 1 year ago

The basic auth response also lacks the set-cookie header.

damomato commented 1 year ago

Thanks for your reply @bt90, hopefully this resolves into a solution

bt90 commented 1 year ago

I'm dumb. I've checked the wrong backend service and the status code + response are perfectly valid for that.

The missing set-cookie header is IMHO still valid.

bt90 commented 1 year ago

@damomato are you trying this in a browser by any chance?

https://danq.me/2021/09/07/http-basic-auth-urls/

damomato commented 1 year ago

That's interesting. Even when using 'mandatory' I receive that pop-up. Not sure if I'm understanding correctly?

bt90 commented 1 year ago

Neither Firefox nor Chrome sent an Authorization header in my tests.

Firefox (in theory) will send it if the website ask for basic auth which nforwardauth doesn't.