Skip to content

Commit

Permalink
[api] New, optional refresh token and configurable JWT user load
Browse files Browse the repository at this point in the history
  • Loading branch information
dpgaspar committed Mar 25, 2019
1 parent dee6d81 commit 8aeb40b
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 7 deletions.
17 changes: 16 additions & 1 deletion docs/rest_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,11 @@ For this we POST request with a JSON payload using::
}

Notice the *provider* argument, FAB currently supports DB and LDAP
authentication backends for the Api.
authentication backends for the Api. The login endpoint returns a fresh **access token** and optionally
a **refresh token**. You can renew the **access token** using the **refresh token** but this time
the returned token will not be fresh. To obtain a new non fresh access token
use ``refresh`` endpoint with the **refresh token**. To obtain a **refresh token** on the login endpoint
send the optional parameter **"refresh": true** on the JSON PUT payload.

Let's request our Token then::

Expand Down Expand Up @@ -336,6 +340,17 @@ methods::
base_permissions = ['can_private']


You can create an alternate JWT user loader, this can be useful if you want
to use an external Authentication provider and map the JWT identity to your
user Model::

@appbuilder.sm.jwt_manager.user_loader_callback_loader
def alternate_user_loader(identity):
# find the user by it's identity
...
return user


Model REST Api
--------------

Expand Down
34 changes: 28 additions & 6 deletions flask_appbuilder/security/api.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
from flask import request
from flask_jwt_extended import create_access_token
from flask_jwt_extended import create_access_token, create_refresh_token, \
jwt_refresh_token_required, get_jwt_identity
from flask_babel import lazy_gettext
from ..views import expose
from ..api import BaseApi, ModelRestApi
from ..api import BaseApi, ModelRestApi, safe


class SecurityApi(BaseApi):

route_base = '/api/v1/security'

@expose('/login', methods=['POST'])
@safe
def login(self):
"""
Login endpoint for the API returns a JWT
:return:
Login endpoint for the API returns a JWT and possibly a refresh token
:return: Flask response with JSON payload containing an
access_token and refresh_token
"""
if not request.is_json:
return self.response_400(message="Request payload is not JSON")
username = request.json.get('username', None)
password = request.json.get('password', None)
provider = request.json.get('provider', None)
refresh = request.json.get('refresh', False)
if not username or not password or not provider:
return self.response_400(message="Missing required parameter")
# AUTH
Expand All @@ -41,8 +45,26 @@ def login(self):
return self.response_401()

# Identity can be any data that is json serializable
access_token = create_access_token(identity=user.id)
return self.response(200, access_token=access_token)
resp = dict()
resp['access_token'] = create_access_token(identity=user.id, fresh=True)
if refresh:
resp['refresh_token'] = create_refresh_token(identity=user.id)
return self.response(200, **resp)

@expose('/refresh', methods=['POST'])
@jwt_refresh_token_required
@safe
def refresh(self):
"""
Security endpoint for the refresh token, so we can obtain a new
token without forcing the user to login again
:return: Flask Response with JSON payload containing
a new access_token
"""
return self.response(
200,
access_token=create_access_token(identity=get_jwt_identity(), fresh=False)
)


class UserApi(ModelRestApi):
Expand Down

0 comments on commit 8aeb40b

Please sign in to comment.