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')
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. Commented Sep 10, 2015 at 20:02
  • 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? Commented Sep 10, 2015 at 20:15

1 Answer 1

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)
Sign up to request clarification or add additional context in comments.

5 Comments

Do we just need these two elements or should there not be another function to verify user credentials against the database?
@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/latest
@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 :)
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!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.