Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to use multiple auth_request directives in nginx?

I would like to use multiple auth_request directives in order to try authentication with multiple servers - i.e. if the first auth server returns 403, try the second auth server. I tried a straightforward approach like this:

location /api {
    satisfy any;
    auth_request    /auth-1/;
    auth_request    /auth-2/;
    proxy_pass http://api_impl;
}

location /auth-1/ {
    internal;
    proxy_pass              http://auth_server_1;
    proxy_pass_request_body off;
    proxy_set_header        Content-Length "";
    proxy_set_header        X-Original-URI $request_uri;
}

location /auth-2/ {
    internal;
    proxy_pass              http://auth_server_2;
    proxy_pass_request_body off;
    proxy_set_header        Content-Length "";
    proxy_set_header        X-Original-URI $request_uri;
}

But nginx wouldn't parse the config file. I received the response

nginx: [emerg] "auth_request" directive is duplicate

Is there a way to achive such functionality in nginx?

like image 480
IztokK Avatar asked Aug 22 '17 16:08

IztokK


1 Answers

Here is my solution after finding this question in google looking for the same things:

  • Set an upstream server that will pass to loopback nginx servers
  • Make those upstream servers do what your /auth-1 and /auth-2 endpoints were doing, except they return 503 on authentication error (except the last in the chain that still returns 401 to signal to nginx that there are no more servers to try)
  • Tell nginx on /auth to just use this upstream, so it will try all authentication "servers" sequentially (thanks to the 503 return codes) until one of them succeeds OR the last one returns 401.
upstream auth {
    server 127.0.2.1:8000 max_fails=0;
    server 127.0.2.1:8001 max_fails=0;
    server 127.0.2.1:8002 max_fails=0;
}

# Method 1
server {
    listen 127.0.2.1:8000;

    location / {
        proxy_pass              http://auth_server_1; # Returns **503** on failure
        proxy_pass_request_body off;
        proxy_set_header        Content-Length "";
        proxy_set_header        X-Original-URI $request_uri;
    }
}

# Method 2
server {
    listen 127.0.2.1:8001;

    location / {
        proxy_pass              http://auth_server_2; # Returns **503** on failure
        proxy_pass_request_body off;
        proxy_set_header        Content-Length "";
        proxy_set_header        X-Original-URI $request_uri;
    }
}

# Method 3
server {
    listen 127.0.2.1:8002;

    location / {
        proxy_pass              http://auth_server_3; # Returns **401** on failure
        proxy_pass_request_body off;
        proxy_set_header        Content-Length "";
        proxy_set_header        X-Original-URI $request_uri;
    }
}

server {
    # ...
    location /api {
        auth_request    /auth;
        proxy_pass http://api_impl;
    }

    location /auth {
        proxy_pass http://auth/;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URL $request_uri;
        proxy_next_upstream error timeout http_503;
    }
    # ...
}
like image 84
Nathan Monfils Avatar answered Oct 11 '22 12:10

Nathan Monfils