How do you implement token authentication in Flask?
Asked Answered
A

1

13

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')
Antione answered 10/9, 2015 at 19:37 Comment(2)
You need to store the users with the token; and confirm the validity of the token against the service. Otherwise you will have to authenticate visitors each time against the 3rd party service whenever they start.Sacchariferous
By each time do you mean for each session? If so, that's fine that they would have to authenticate again. Is there a reason this would be an issue?Antione
P
26

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)
Pare answered 11/9, 2015 at 1:35 Comment(5)
Do we just need these two elements or should there not be another function to verify user credentials against the database?Furriery
@EvanBurbidge Sorry for the late reply. This implementation was specifically for authenticating users against an external API elsewhere. Most like you want to follow a standard user login flow, check out this link for more flask-login.readthedocs.io/en/latestPare
@FBoucaut thanks for getting back in touch!! I actually started working with node and made a pretty nice user login / register / logout package using token based auth! Decided to keep all JS all the time :)Furriery
I'm interested in building an authentication similiar to this. Can anyone provide some information to how the authentication API has to look like to make this work. Or maby provide a link to a resource explaining how an API like this can be build. Thanks!Iseult
@MarcB. this could help you realpython.com/token-based-authentication-with-flaskGrose

© 2022 - 2024 — McMap. All rights reserved.