[ACCEPTED]-Nginx config: how to use auth_basic authentication if ssl_client_certificate none provided?-config

Accepted answer
Score: 29

You can set auth_basic configuration in the if clause 3 like this:

server {
    listen 443;
    auth_basic_user_file    .htpasswd;
    ssl_client_certificate  ca.cert;
    ssl_verify_client       optional;
    ...

    location / {
      ...

      if ($ssl_client_verify = SUCCESS) {
        set $auth_basic off;
      }
      if ($ssl_client_verify != SUCCESS) {
        set $auth_basic Restricted;
      }

      auth_basic $auth_basic;
    }
}

Now, authentication falls back 2 to HTTP Basic if no client certificate has 1 been provided (or if validation failed).

Score: 4

I'm unable to test this currently, but would 9 something like this work?

server {
    listen 80;
    server_name www.example.com example.com;
    rewrite ^ https://$server_name$request_uri? permanent;
}
server {
    listen 443;
    ...

    if ($ssl_client_verify != SUCCESS) {
        rewrite ^ http://auth.example.com/ permanent;
    } 
    location / {
        ...
    }

}
server {
    listen 80;
    server_name auth.example.com;
    location / {
        auth_basic "Please login";
        auth_basic_user_file .passfile;
    }
} 

So basically:
- Accept 8 all initial request (on port 80 for whatever 7 name you're using) and rewrite to ssl
- Check 6 if there's an the client is verified.
- If 5 not, rewrite to an alternate domain that 4 uses basic auth

Like I said, I can't test 3 it right now, but I'll try to get around 2 to it! Let me know if it helps, I'm interested 1 to see if it works.

Score: 3

Nginx provides no way to fall back to basic 5 authentication when client cert fails. As 4 an alternative you can use variables to 3 restrict access:

location / { 
  if ($ssl_client_verify = "SUCCESS") {
    set $authorized 1;
  }
  if ($authorized != 1) {
    error_page 401 @basicauth;
    return 401;
  }
}

location @basicauth {
  auth_basic "Please login";
  auth_basic_user_file .passfile;
  set $authorized 1;
  rewrite /(.*) /$1;
}

*keep in mind that IfIsEvil and 2 these rules may work incorrectly or interfere 1 with other parts of a larger configuration.

Score: 3

You may try using a map.

map $ssl_client_verify $var_auth_basic {
   default off;
   SUCCESS "Please login";
}

server {
   ....
   auth_basic $var_auth_basic;
   auth_basic_user_file .passfile;

that way the value 2 depends on $ssl_client_verify but is alsa always defined and 1 auth_basic and auth_basic_user_file is always inside server { block.

Score: 2

Forget about it, it won't work.

The reason why it fails 20 is because if is not part of the general configuration 19 module as one should believe. if is part of 18 the rewrite module and auth_basic is another module. You 17 just cannot have dynamic vhosts with basic 16 auth.

On the other hand...

You can have dynamic vhosts with their 15 own error pages. The following example is 14 designed for a custom 404 page but you can 13 implement it into your code.

server {
    listen 80;
    server_name _;

    set $site_root /data/www/$host;

    location / {
        root $site_root;
    }

    error_page 404 =404 /404.html;

    location /404.html {
        root $site_root/error_files;
        internal;

        error_page 404 =404 @fallback_404;
    }

    location @fallback_404 {
        root /var/www/;
        try_files /404.html =404;
        internal;
    }

    error_log  /var/log/nginx/error.log  info;
    access_log  /var/log/nginx/access.log;
}

What happens...

  • you are telling Nginx to use /404.html in case of HTTP_NOT_FOUND.
  • changing the location root to match the Web site error_pages directory.
  • internal redirection
  • returning a 404 http code
  • configure the fallback 404 page in location @fallback_404: In this location, the root is changed to /var/www/ so it will read files from that path instead of $site_root
  • at the last stage the code returns /var/www/404.html if it exists with a 404 http code.

NOTE: According to Nginx documentation :

Specifies that 12 a given location can only be used for internal requests. For 11 external requests, the client error 404 10 (Not Found) is returned. Internal requests 9 are the following:

  • requests redirected by the error_page, index, random_index, and try_files directives;
  • requests redirected by the “X-Accel-Redirect” response header field from an upstream server;
  • subrequests formed by the “include virtual” command of the ngx_http_ssi_module module and by the ngx_http_addition_module module directives;
  • requests changed by the rewrite directive.

Also:

There is a limit 8 of 10 internal redirects per request to 7 prevent request processing cycles that 6 can occur in incorrect configurations. If 5 this limit is reached, the error 500 (Internal 4 Server Error) is returned. In such cases, the 3 “rewrite or internal redirection cycle” message 2 can be seen in the error log.

Check this link for 1 more, hope that helps.

More Related questions