miguelgrinberg / Flask-HTTPAuth

Simple extension that provides Basic, Digest and Token HTTP authentication for Flask routes
MIT License
1.27k stars 228 forks source link

Authentication Help #100

Closed marianakhoul closed 4 years ago

marianakhoul commented 4 years ago

Hello,

I am trying to authenticate my API.

some background information: I am using the HTTPBasicAuth() function (if you recommend anything else for this situation I do not mind changing the code)

Below is my app.py script

users={}
secrets = "./secrets.json" 
with open(secrets, 'r') as c:
    secrets_json = json.load(c)

user = secrets_json['API']['user']
password = secrets_json['API']['password']
users[user] = generate_password_hash(password)

app = Flask(__name__)
auth = HTTPBasicAuth()

@auth.verify_password
def verify_password(username, password):
    if username in users:
          return check_password_hash(users.get(username), password)
    return False

@app.route("/",methods=["GET"])
@auth.login_required
def main():
    return "Hello World"

@app.route("/annotate/",methods=["GET"])
@auth.login_required
def annotate():
#Annotate functions.....

if __name__ == "__main__":
    http_server = WSGIServer(('0.0.0.0',5000), app)
    http_server.serve_forever()

When I am using: curl -u Maria http://localhost:5000/ It asks for authentication, but if I call the annotate function using: curl -u Maria http://localhost:5000/annotate/gene=BRAF&protein_change=V600E&variant_type=MISSENSE

It doesn't ask for authentication.

I also want it to ask for authentication when using a web browser. When I ran it the first time, it asked through the browser but that was it. I was reading through your other issues and comments and you said it asks only once, but how can I make it ask every time?

Thank you very much for any help you can provide! Maria Nakhoul

miguelgrinberg commented 4 years ago

Can you copy the complete command and output for the example that does not ask authentication?

Your second question unfortunately cannot be done. The browser will ask for the username and password once and then remember it for the duration of the session.

marianakhoul commented 4 years ago

My whole app.py script:

from flask import Flask, render_template, request, jsonify, g,session, redirect,escape
from flask_httpauth import HTTPBasicAuth
from werkzeug.security import generate_password_hash, check_password_hash
from colemankb.annotations import ColemanKB
from gevent.pywsgi import WSGIServer
import json
import os

users={}

secrets = "./secrets.json" #os.environ.get('CRED', None) 

with open(secrets, 'r') as c:
    secrets_json = json.load(c)

user = secrets_json['API']['user']
password = secrets_json['API']['password']

users[user] = generate_password_hash(password.strip())

app = Flask(__name__)

auth = HTTPBasicAuth()
app.debug = True

#initiating ColemanKB object
s = ColemanKB()

@auth.verify_password
def verify_password(username, password):
    print(users)
    print(username)
    if username in users:
        print(username)
        print(check_password_hash(users.get(username), password))
        return check_password_hash(users.get(username), password)
    return False

@app.route("/",methods=["GET"])
@auth.login_required
def main():
    return "Hello World"

@app.route("/annotate/",methods=["GET"])
@auth.login_required
def annotate():

    s.get_annotation_df()
    s.gene = request.args.get('gene')
    s.protein_change = request.args.get('protein_change')
    s.variant_type = request.args.get('variant_type')

    try:
        s.exac = float(request.args.get('exac'))
    except TypeError:
        s.exac = ''

    tier = s.annotate_variant()

    data = {
        'gene': s.gene,
        'protein_change': s.protein_change,
        'variant_type': s.variant_type,
        'tier': tier,
        'exac': s.exac
    }
    return jsonify(data)

if __name__ == "__main__":
    http_server = WSGIServer(('0.0.0.0',5000), app)
    http_server.serve_forever()

For the example that doesn't ask authentication:

 (venv) (base) Marias-MacBook-Pro:coleman_kb marianakhoul$ curl -u Maria http://localhost:5000/annotate/?gene=BRAF&protein_change=V600E&variant_type=MISSENSE
[94] 90186
[95] 90187

[93]+  Stopped                 curl -u Maria http://localhost:5000/annotate/?gene=BRAF
[95]   Done                    protein_change=V600E
(venv) (base) Marias-MacBook-Pro:coleman_kb marianakhoul$ 

When you mean the duration of the session, you mean until I close the browser or until the API stops functioning? How would I be able to add an expiration for a user ?

Thank you, Maria Nakhoul

miguelgrinberg commented 4 years ago

The "&" character is used to send commands to run in the background. Try enclosing your URL in quotes:

curl -u Maria "http://localhost:5000/annotate/?gene=BRAF&protein_change=V600E&variant_type=MISSENSE"

See https://stackoverflow.com/questions/13339469/how-to-include-an-character-in-a-bash-curl-statement.

marianakhoul commented 4 years ago

Thank you! This fixed the curl issue thank you!

I ran it but it didn't ask for authentication from the browser even once. Do you recommend anything for the browser?

Thank you, Maria Nakhoul

miguelgrinberg commented 4 years ago

Close the browser completely (all the windows). The start a new browser window. Do you get the login prompt now?

marianakhoul commented 4 years ago

It works when I quit Safari completely each time. I think this is enough for now with the browser stuff.

Thank you so much for all your help!

miguelgrinberg commented 4 years ago

As I said before, the browser will remember the credentials and re-use them. That behavior cannot be changed.