pythonflaskmarshmallowflask-marshmallowflask-smorest

Flask-smorest returning an empty json string


The JSON response of my endpoint returns {} even though I am logging the correct data.

from flask_smorest import Blueprint

bp = Blueprint("auth", __name__, url_prefix="/api/v1/auth/")


@bp.route("/login", methods=["POST"])
@bp.arguments(LoginRequest)
@bp.response(200, JwtTokenResponse)
@bp.response(404, ErrorResponse)
def login(args):
    current_app.logger.debug(args)
    username = args.get("username", None)
    password = args.get("password", None)
    current_app.logger.debug(f"Username: {username}")
    current_app.logger.debug(f"Password: {password}")

    user = User.query.filter_by(username=username).first()
    if user is None:
        return dict(message="User does not exists"), 404
    if not check_password_hash(user.password, password):
        return dict(message="Unable to Authenticate user."), 404

    access_token = create_access_token(identity=username)
    refresh_token = create_refresh_token(identity=username)
    response = dict(access_token=access_token, refresh_token=refresh_token)
    current_app.logger.debug(f"Response: {response}")
    return response, 200

My LoginTokenSchema and ErrorResponse schemas are defined as:

from marshmallow import Schema, fields

class JwtTokenResponse(Schema):
    access_token = fields.String()
    refresh_token = fields.String()

class ErrorResponse(Schema):
    message = fields.String()

When I test the API with a user not in the database or with the wrong password; it will product the correct response with ErrorRespose however with the correct creds it just will output {}, when I check the flask logs I can see access/refresh token dict, what am I doing wrong?


Solution

  • You don't need to call Blueprint.response twice, which is what I did in my question. You can call alt_response with a custom error message or just use abort and let flask-smorest take care of the rest.

    @bp.route("/login", methods=["POST"])
    @bp.arguments(LoginRequest)
    @bp.response(200, SmorestJWTTokenResponse)
    def login(args):
        current_app.logger.debug(args)
        username = args.get("username", None)
        password = args.get("password", None)
    
        user = User.query.filter_by(username=username).first()
        if user is None:
            abort(404, message="User does not exists.")
        if not check_password_hash(user.password, password):
            abort(404, message="Unable to Authenticate user.")
    
        access_token = create_access_token(identity=username)
        refresh_token = create_refresh_token(identity=username)
        return dict(access_token=access_token, refresh_token=refresh_token), 200