I'm trying to allow users to login to my Flask app using their accounts from a separate web service. I can contact the api of this web service and receive a security token. How do I use this token to authenticate users so that they have access to restricted views?
I don't need to save users into my own database. I only want to authenticate them for a session. I believe this can be done using Flask-Security and the @auth_token_required decorator but the documentation is not very detailed and I'm not sure how to implement this.
EDIT:
Here's a code example:
@main.route("/login", methods=["GET", "POST"])
def login():
payload = {"User": "john", "Password": "password123"}
url = "http://webserviceexample/api/login"
headers = {'content-type': 'application/json'})
#login to web service
r = requests.post(url, headers=headers, json=payload)
response = r.json()
if (r.status_code is 200):
token = response['user']['authentication_token']
# allow user into protected view
return render_template("login.html", form=form)
@main.route('/protected')
@auth_token_required
def protected():
return render_template('protected.html')
To install it, type sudo apt install python3-venv in your terminal and then you are good to go. If you are on windows then use something like virtualenv to make a virtual environment. This will create a folder named venv in the flask project which will contain the project specific libraries.
By default, Flask-Login uses sessions for authentication. This means you must set the secret key on your application, otherwise Flask will give you an error message telling you to do so.
Hey there Amedrikaner!
It looks like your use-case is simple enough that we can implement this ourselves. In the code below, I'll be storing your token in the users session and checking in a new wrapper. Let's get started by making our own wrapper, I usually just put these in a wrappers.py file but can you can place it where you like.
def require_api_token(func):
@wraps(func)
def check_token(*args, **kwargs):
# Check to see if it's in their session
if 'api_session_token' not in session:
# If it isn't return our access denied message (you can also return a redirect or render_template)
return Response("Access denied")
# Otherwise just send them where they wanted to go
return func(*args, **kwargs)
return check_token
Cool!
Now we've got our wrapper implemented we can just save their token to the session. Super simple. Let's modify your function...
@main.route("/login", methods=["GET", "POST"])
def login():
payload = {"User": "john", "Password": "password123"}
url = "http://webserviceexample/api/login"
headers = {'content-type': 'application/json'})
#login to web service
r = requests.post(url, headers=headers, json=payload)
response = r.json()
if (r.status_code is 200):
token = response['user']['authentication_token']
# Move the import to the top of your file!
from flask import session
# Put it in the session
session['api_session_token'] = token
# allow user into protected view
return render_template("login.html", form=form)
Now you can check the protected views using the @require_api_token wrapper, like this...
@main.route('/super_secret')
@require_api_token
def super_secret():
return "Sssshhh, this is a secret"
EDIT Woah! I forgot to mention you need to set your SECRET_KEY in your apps config.
Just a config.py file with SECRET_KEY="SOME_RANDOM_STRING" will do. Then load it with...
main.config.from_object(config)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With