flask-HTTPTokenAuth Fails to Verify Token

Question:

I’m working my way through Miguel Grinberg’s book Flask Web Development, and I’ve run into a snag in Chapter 14 (Application Programming Interfaces) with the authentication routine. I’m attempting to update the code to use the current version of flask-HTTPAuth according to the example code in the github repo. I can authenticate to HTTPBasicAuth with email/password, but when I try to pass a token I still get a password prompt.

Here is my app/api/authentication.py file:

from flask import g, jsonify
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth, MultiAuth

from ..models import User
from . import api
from .errors import forbidden, unauthorized


basic_auth = HTTPBasicAuth()
token_auth = HTTPTokenAuth(scheme='Bearer')
multi_auth = MultiAuth(basic_auth, token_auth)


@basic_auth.verify_password
def verify_password(email, password):
    if email == '':
        return False
    user = User.query.filter_by(email=email).first()
    if not user:
        return False
    g.current_user = user
    g.token_used = False
    if user.verify_password(password):
        return user
    else:
        return False

@token_auth.verify_token
def verify_token(token):
    user = User.verify_auth_token(token)
    if user:
        g.current_user = user
        g.token_used = True
        return user
    else:
        return False

@basic_auth.error_handler
def auth_error():
    return unauthorized('Invalid credentials')

@token_auth.error_handler
def auth_error():
    return unauthorized('Invalid credentials')

@api.before_request
@multi_auth.login_required
def before_request():
    if not g.current_user.is_anonymous and not g.current_user.confirmed:
        return forbidden('Unconfirmed account')

@api.route('/tokens/', methods=['POST'])
@multi_auth.login_required
def get_token():
    if g.current_user.is_anonymous or g.token_used:
        return unauthorized('Invalid credentials')
    return jsonify({'token': g.current_user.generate_auth_token(), 'expiration': 3600})

I’m using Python 3.10.6, Flask 2.2.2 and HTTPie 3.2.1. What am I doing wrong?

Asked By: Darwin von Corax

||

Answers:

I’ve figured it out. The current version of HTTPie (3.2.1) needs to know whether you’re sending a token or a userid:password pair. To do this, you use the command

http --auth <username>:<password> ...

for basic authentication or

http --auth-type bearer --auth <token> ...

for token authentication.

Answered By: Darwin von Corax