vouch-proxy icon indicating copy to clipboard operation
vouch-proxy copied to clipboard

`$auth_resp_x_vouch_user` is not set

Open freva opened this issue 1 year ago • 6 comments

Describe the problem I'm using Google IdP, the login seems to work: I am redirected to Google, I select my email, I get redirect back to my site and the private content is being served. The issue I'm having is that I want to limit showing the content to only certain emails, not anyone who logged in with Google. To do that I'm trying to write an expression in nginx on X-Vouch-User/$auth_resp_x_vouch_user: https://gist.github.com/freva/fe6c8058070e7ed477a9f2b52b1ee492

It seems like $auth_resp_x_vouch_user is not set, so the "default" behavior in the map is always invoked.

Additional context nginx version: 1.27.3

When I curl the vouch proxy, it does return X-Vouch-User:

$ curl http://192.168.0.24:9090/validate -H 'cookie: auth=xxx' -v 
*   Trying 192.168.0.24:9090...
* TCP_NODELAY set
* Connected to 192.168.0.24 (192.168.0.24) port 9090 (#0)
> GET /validate HTTP/1.1
> Host: 192.168.0.24:9090
> User-Agent: curl/7.68.0
> Accept: */*
> cookie: auth=xxx
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Vouch-Success: true
< X-Vouch-User: [email protected]
< Date: Tue, 31 Dec 2024 22:22:46 GMT
< Content-Length: 7
< Content-Type: text/plain; charset=utf-8
< 
200 OK
* Connection #0 to host 192.168.0.24 left intact

If I log in as another user, it doesn't work. I've tried debugging this quite a bit, including the X-Meta header in the gist, which returns x-meta: | | OK

freva avatar Dec 31 '24 23:12 freva

You could use 'vouch.whitelist'...

https://github.com/vouch/vouch-proxy/blob/012b2fdb6182f659735f1f43ecaadf5b4a3d038f/config/config.yml_example#L68

Happy New Year. I won't be looking at VP till next week but can offer better advice then

bnfinet avatar Jan 01 '25 00:01 bnfinet

Happy new year! Thanks for the tip, unfortunately that wont quite work for me since I'd like to allow different set of users for different sites, but using a single VP instance.

freva avatar Jan 01 '25 10:01 freva

Hello, I faced the same issue, and although I'm not exactly sure why, placing auth_request_set right above proxy_set_header made it work.

auth_request_set $auth_resp_x_vouch_user $upstream_http_x_vouch_user;
proxy_set_header X-Vouch-User $auth_resp_x_vouch_user;

nana4rider avatar Jan 31 '25 20:01 nana4rider

@nana4rider where did you put this? In my gist I have

auth_request_set $auth_resp_x_vouch_user $upstream_http_x_vouch_user;

under /validate, while

add_header X-Vouch-User $auth_resp_x_vouch_user;

is under /, so I cant really put them right after each other. For what it's worth, I tried adding both of those, in that order, under both /validate and /. Didn't help 😕

freva avatar Jan 31 '25 22:01 freva

@freva I removed it from /validate and added it to /, and it worked for me.

If this doesn't work for you, I'm not sure what the issue could be. 😢

location / {
    proxy_pass $backend;

    auth_request_set $auth_resp_x_vouch_user $upstream_http_x_vouch_user;
    proxy_set_header X-Vouch-User $auth_resp_x_vouch_user;
}

nana4rider avatar Jan 31 '25 22:01 nana4rider

If I remove it from /validate, nginx fails to start with

nginx: [emerg] unknown "auth_resp_x_vouch_user" variable

Full config:

map $auth_resp_x_vouch_user $is_authorized {
  [email protected]  "1";
  ~.+     "0";
  default "1";
}

server {
  listen        443 ssl;
  server_name   sub.mydomain.com;

  include	common.conf;
  include	ssl.conf;

  auth_request /validate;

  location = /validate {
    proxy_pass http://192.168.0.24:9090/validate;

    proxy_set_header Host $http_host;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";

    # these return values are used by the @error401 call
    auth_request_set $auth_resp_jwt $upstream_http_x_vouch_jwt; 
    auth_request_set $auth_resp_err $upstream_http_x_vouch_err; 
    auth_request_set $auth_resp_failcount $upstream_http_x_vouch_failcount; 
  }

  error_page 401 = @error401;

  location @error401 {
    return 302 https://login.mydomain.com/login?url=$scheme://$http_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error=$auth_resp_err;
  }

  location / {
    proxy_pass  http://192.168.0.22:32400;
    include     common_location.conf;
    add_header X-Vouch-User $auth_resp_x_vouch_user;
    proxy_set_header X-Vouch-User $auth_resp_x_vouch_user;
    add_header X-meta "$auth_resp_x_vouch_user | $upstream_http_x_vouch_user | OK";

    if ($is_authorized != "1") {
      return 403;
    }
  }
}

freva avatar Jan 31 '25 22:01 freva

@freva are you still having this issue?

Sorry for the delayed response. I'm going to close this but do let me know if you'd like to continue working it and we can reopen the issue and continue the discussion

bnfinet avatar Jul 23 '25 19:07 bnfinet

@bnfinet I did not figure out the original problem, but I've fixed it with your OpenResty example.

If anyone is curious, here's my setup:

init.lua (loaded once with init_by_lua_file)

function Set (list)
    local set = {}
    for _, l in ipairs(list) do set[l] = true end
    return set
end

function tableHasKey(table, key)
    return table[key] ~= nil
end

authorized_users_by_domain = {
    ["a.mysite.tld"] = Set { "[email protected]" },
    ["b.mysite.tld"] = Set { "[email protected]", "[email protected] }
}

auth.lua

local current_host = ngx.var.host
local authenticated_user = ngx.var.auth_resp_user

if current_host and authenticated_user then
    local authorized_for_domain = authorized_users_by_domain[current_host]
    if authorized_for_domain then
        if not tableHasKey(authorized_for_domain, authenticated_user) then
            ngx.log(ngx.ERR, "Unauthorized user '", authenticated_user, "' for domain '", current_host, "'")
            ngx.exit(ngx.HTTP_FORBIDDEN)
        end
    else
        ngx.log(ngx.INFO, "No authorization list defined for domain '", current_host, "'")
        ngx.exit(ngx.HTTP_FORBIDDEN)
    end
else
    ngx.log(ngx.INFO, "Missing ngx.var.host or ngx.var.auth_resp_user")
    ngx.exit(ngx.HTTP_FORBIDDEN)
end

a.conf (nginx config for a.mysite.tld)

server {
  listen        443 ssl;
  server_name   a.mysite.tld;
  include	auth.conf;

  location / {
    proxy_pass       http://10.0.1.101;
    auth_request_set $auth_resp_user $upstream_http_x_vouch_user;
  }
}

This lets me easily add auth to a subdomain by adding the users I want in init.lua and adding 2 lines to the site config (include auth.conf and auth_request_set $auth_resp_user ...). Short of https://github.com/vouch/vouch-proxy/issues/114, I think this is about as simple as it gets.

freva avatar Jul 24 '25 21:07 freva