Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nginx password authentication keeps prompting for password

I want to upload a development branch of my website so that I can show it to clients and make tests in an environment as close to production as possible (with code that may not be ready for production). Thus I would like to password protect this site.

I'm developing a website using Django and use nginx for serving the website (with uWsgi). I manage to get prompted for password applying the following directives:

auth_basic "Restricted Content";  # also tried "Private Property"
auth_basic_user_file /etc/nginx/.htpasswd;

But the problem is that after entering the first password properly, it keeps prompting me for the user & password again; as if every API call would need to be authenticated.

I think the issue might be with my configuration file, so here's my site.conf file:

server {
    listen 80;
    server_name panel.mysite.dev;
    root /path/to/my/app/front/dist;

    ### I've also tried 'auth_basic' here

    location / {

        root /path/to/my/app/front/dist;
        index index.html;

        auth_basic "Private Property";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
    location /media {
        rewrite ^(.*)$ http://media.mysite.dev$1;
    }
    location /static {
        rewrite ^(.*)$ http://static.mysite.dev$1;
    }

}

server {
    listen 80;
    server_name api.mysite.dev;

    ### I've also tried 'auth_basic' here

    location /api {
        client_max_body_size 25m;
        uwsgi_pass unix:/tmp/api.mysite.dev.sock;
        include /path/to/my/app/back/uwsgi_params;
    }

}
server {
    listen 80;
    server_name media.mysite.dev;
    root /path/to/my/app/media;
    add_header 'Access-Control-Allow-Origin' '.*\.mysite\.[com|dev]';

    location / {
        root /path/to/my/app/media;
    }
}
server {
    listen 80;
    server_name static.mysite.dev;
    root /path/to/my/app/static;
    if ($http_origin ~* (https?://.*\.mysite\.[com|dev](:[0-9]+)?)) {
        set $cors "true";
    }
    location / {
        if ($cors = "true") {
            add_header 'Access-Control-Allow-Origin' "$http_origin";
        }
    }
}

My question: Is there any way to remember the password once entered and allow authenticated users to navigate easily? Or am I missing something trivial?

EDIT: In my django settings.py:

AUTHENTICATION_BACKENDS = (
    'oauth2_provider.backends.OAuth2Backend',
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
)
...
REST_FRAMEWORK = {
    ...
    DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'oauth2_provider.ext.rest_framework.OAuth2Authentication',
    ),

Thank you very much in advance. Any help would be much appreciated

like image 899
vabada Avatar asked Mar 17 '16 10:03

vabada


2 Answers

Basic authentication uses the Authorization header to transmit user and password. Django REST also uses this header in the TokenAuthentication authentication backend. Nginx does not support multiple Authorization headers, so if you try to login and use Token authentication simultaneously, things will break.

A solution requiring no changes to the Django app would be to use another means of authentication in nginx, e.g., client certificates, or, you can use the ngx_http_auth_request_module to check whether a signed session cookie is set/valid or if the request IP is in a (temporary) whitelist, and redirect the user to a page with a login form otherwise.

like image 199
Phillip Avatar answered Nov 15 '22 02:11

Phillip


There is an excellent, easy and more secured way for Basic Authentication with Nginx. It is, use oAuth2_proxy which has Basic Authentication support including a web form (excellent, browser will not keep connection alive) to input user/password credentials with option to include a password file like htpasswd. It also has support for many other identity providers. Here's my oAuth2_proxy config file for Basic Auth:

http_address = "0.0.0.0:5160" #use any port you want

upstreams = [
    "https://url-that-you-want-to-protect/"
]

request_logging = false
custom_sign_in_logo = "/etc/apache2/small-email-icon.png" #custom logo on form
authenticated_emails_file = "/etc/apache2/emails" #required option, file can be empty

htpasswd_file = "/etc/apache2/.htpasswd" #basic auth password file
display_htpasswd_form = true

client_id = "hfytr76r7686887"
client_secret = "ghgh6767ghgh7654fghj6543dfgh5432"
cookie_name = "_oauth2_proxy"
cookie_secret = "ghgh6gguujgh7654fghj6543dfgh5432"
cookie_expire = "2h15m0s"
# cookie_refresh = ""
cookie_secure = true
footer = "Unauthorized access prohibited."
like image 27
Atikul Haider Avatar answered Nov 15 '22 03:11

Atikul Haider