5

I am running a Flask web app and using Apache basic authentication(with .htaccess and .htpasswd files) to password protect it. I want to password protect only one webpage in the app. When I password protect the html file for the webpage there is no effect and the webpage is still not password protected. Could this be because it is my python file that is calling the html file using render_template? I'm not sure how to fix this issue.

accelke
  • 193
  • 1
  • 3
  • 11
  • What do you mean by "password protect the html file"? – dirn Apr 19 '15 at 03:17
  • What I mean is that I added .htaccess and .htpasswd files and in the .htaccess file I specified the html file. These files should ask for a username and password when the file is accessed. – accelke Apr 19 '15 at 03:42
  • That only works if you're serving the HTML file directly through Apache. You'll need to restrict access to the endpoint in Flask. – dirn Apr 19 '15 at 03:45
  • I see. How do I do that? – accelke Apr 19 '15 at 03:47

1 Answers1

22

You need to restrict access to your endpoint. This snippet should get you started down the right path.

from functools import wraps
from flask import request, Response


def check_auth(username, password):
    """This function is called to check if a username /
    password combination is valid.
    """
    return username == 'admin' and password == 'secret'

def authenticate():
    """Sends a 401 response that enables basic auth"""
    return Response(
    'Could not verify your access level for that URL.\n'
    'You have to login with proper credentials', 401,
    {'WWW-Authenticate': 'Basic realm="Login Required"'})

def requires_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if not auth or not check_auth(auth.username, auth.password):
            return authenticate()
        return f(*args, **kwargs)
    return decorated

With this, you could decorate any endpoint you want to restrict with @requires_auth.

@app.route('/secret-page')
@requires_auth
def secret_page():
    return render_template('secret_page.html')
dirn
  • 19,454
  • 5
  • 69
  • 74
  • I actually was using a method similar to this before. The problem I have with this method is that when I enter the username and password it just prompts for them again and it never validates. – accelke Apr 19 '15 at 04:04
  • 1
    From the snippet: If you are using basic auth with mod_wsgi you will have to enable auth forwarding, otherwise apache consumes the required headers and does not send it to your application: [WSGIPassAuthorization](https://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization). – dirn Apr 19 '15 at 04:06
  • Yes I did put "WSGIPassAuthorization On" in my /etc/apache2/sites-available/app.com.conf file but it did not make any difference. Is there a different file that I have to put it in? – accelke Apr 19 '15 at 04:10
  • Is there a way to add two possible username password combinations? I want managers to have access to certain pages that everyone else can't see, but I want them to be able to use their password for the pages everyone else can see. In production I will use full user authentication using proper methods, but this is for first draft testing. – bart cubrich Nov 10 '21 at 19:00