Skip to content

Instantly share code, notes, and snippets.

@bitjockey42
Created February 17, 2021 04:42
Show Gist options
  • Save bitjockey42/4921deadd3f57ec248796b83495baf54 to your computer and use it in GitHub Desktop.
Save bitjockey42/4921deadd3f57ec248796b83495baf54 to your computer and use it in GitHub Desktop.
Breaking changes in flask-jwt-extended requires these changes in auth/views.py
from flask import request, jsonify, Blueprint, current_app as app
from flask_jwt_extended import (
create_access_token,
create_refresh_token,
jwt_required,
get_jwt_identity,
get_jwt,
)
from myapi.models import User
from myapi.extensions import pwd_context, jwt, apispec
from myapi.auth.helpers import revoke_token, is_token_revoked, add_token_to_database
blueprint = Blueprint("auth", __name__, url_prefix="/auth")
@blueprint.route("/login", methods=["POST"])
def login():
"""Authenticate user and return tokens
---
post:
tags:
- auth
requestBody:
content:
application/json:
schema:
type: object
properties:
username:
type: string
example: myuser
required: true
password:
type: string
example: P4$$w0rd!
required: true
responses:
200:
content:
application/json:
schema:
type: object
properties:
access_token:
type: string
example: myaccesstoken
refresh_token:
type: string
example: myrefreshtoken
400:
description: bad request
security: []
"""
if not request.is_json:
return jsonify({"msg": "Missing JSON in request"}), 400
username = request.json.get("username", None)
password = request.json.get("password", None)
if not username or not password:
return jsonify({"msg": "Missing username or password"}), 400
user = User.query.filter_by(username=username).first()
if user is None or not pwd_context.verify(password, user.password):
return jsonify({"msg": "Bad credentials"}), 400
access_token = create_access_token(identity=user.id)
refresh_token = create_refresh_token(identity=user.id)
add_token_to_database(access_token, app.config["JWT_IDENTITY_CLAIM"])
add_token_to_database(refresh_token, app.config["JWT_IDENTITY_CLAIM"])
ret = {"access_token": access_token, "refresh_token": refresh_token}
return jsonify(ret), 200
@blueprint.route("/refresh", methods=["POST"])
@jwt_required(refresh=True)
def refresh():
"""Get an access token from a refresh token
---
post:
tags:
- auth
parameters:
- in: header
name: Authorization
required: true
description: valid refresh token
responses:
200:
content:
application/json:
schema:
type: object
properties:
access_token:
type: string
example: myaccesstoken
400:
description: bad request
401:
description: unauthorized
"""
current_user = get_jwt_identity()
access_token = create_access_token(identity=current_user)
ret = {"access_token": access_token}
add_token_to_database(access_token, app.config["JWT_IDENTITY_CLAIM"])
return jsonify(ret), 200
@blueprint.route("/revoke_access", methods=["DELETE"])
@jwt_required
def revoke_access_token():
"""Revoke an access token
---
delete:
tags:
- auth
responses:
200:
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: token revoked
400:
description: bad request
401:
description: unauthorized
"""
jti = get_jwt()["jti"]
user_identity = get_jwt_identity()
revoke_token(jti, user_identity)
return jsonify({"message": "token revoked"}), 200
@blueprint.route("/revoke_refresh", methods=["DELETE"])
@jwt_required(refresh=True)
def revoke_refresh_token():
"""Revoke a refresh token, used mainly for logout
---
delete:
tags:
- auth
responses:
200:
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: token revoked
400:
description: bad request
401:
description: unauthorized
"""
jti = get_jwt()["jti"]
user_identity = get_jwt_identity()
revoke_token(jti, user_identity)
return jsonify({"message": "token revoked"}), 200
@jwt.user_lookup_loader
def user_loader_callback(identity):
return User.query.get(identity)
@jwt.token_in_blocklist_loader
def check_if_token_revoked(decoded_token):
return is_token_revoked(decoded_token)
@blueprint.before_app_first_request
def register_views():
apispec.spec.path(view=login, app=app)
apispec.spec.path(view=refresh, app=app)
apispec.spec.path(view=revoke_access_token, app=app)
apispec.spec.path(view=revoke_refresh_token, app=app)
@lesterBC
Copy link

lesterBC commented Jun 7, 2021

Hello :). Is this project open source? If yes can I have the repo link. I want to learn your flask folder structure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment