Skip to content

Conversation

@CristianoYL
Copy link
Contributor

Added Flask-JWT-Extended to replace Flask-JWT.

Introduced token refreshing, blacklisting, access control and other features.

"info": {
"_postman_id": "74a1833f-bc4e-4e85-a525-72d268ab9999",
"name": "Flask-JWT-Extended",
"description": "This collection contains requests associated witht the Flask-JWT-Extended section of the REST API course.",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exported the Postman collection used to test the code for this section.


- `POST: /login`
- Description: authenticate a user and ,if authenticated, respond with an access token and a refresh token.
- Description: authenticate a user and ,if authenticated, respond with a fresh access token and a refresh token.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the workflow slightly. We simply return a fresh access token when the user authenticates via credentials. We don't need a separate /fresh-login endpoint anymore.

from flask_jwt_extended import JWTManager

from resources.refresh_token import TokenRefresh
from resources.user import UserRegister, UserLogin, UserFreshLogin
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just put every resource related to user identity into resources.user

api.add_resource(ItemList, '/items')
api.add_resource(UserRegister, '/register')
api.add_resource(UserLogin, '/login')
api.add_resource(UserFreshLogin, '/fresh_login')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's get rid of fresh login.

'name': self.name,
'price': self.price,
'store_id': self.store_id
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I choose to return more info in the json() method so it's more convenient when testing.

@classmethod
def find_all(cls):
return cls.query.all()

Copy link
Contributor Author

@CristianoYL CristianoYL May 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to keep resources unaware of what's happening internally, so let's put this code in the model method instead.

items = [item.json() for item in ItemModel.find_all()]
if user_id:
return {'items': items}, 200
return {'items': [item['name'] for item in items]}, 401
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use list comprehension instead of list() and map()


if user and safe_str_cmp(user.password, data['password']):
access_token = create_access_token(identity=user.id)
access_token = create_access_token(identity=user.id, fresh=True)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always return fresh access token when the user authenticates via credentials.

required=True,
help="This field cannot be blank."
)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get rid of fresh login.

Copy link
Contributor Author

@CristianoYL CristianoYL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments

"""
app.config['JWT_SECRET_KEY'] = 'jose' # we can also use app.secret like before, Flask-JWT-Extended can recognize both
app.config['JWT_BLACKLIST_ENABLED'] = True # enable blacklist feature
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ['access', 'refresh'] # allow blacklisting for access and refresh tokens
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need refresh here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's true that we didn't blacklist any refresh token in the code. But I think we can keep it and talk about it, just to let the students know we can also blacklist a refresh token as well. In this way, we can freeze an account by all means.

def add_claims_to_jwt(identity):
if identity == 1: # instead of hard-coding, we can read from a config file to get a list of admins instead
return {'isAdmin': True}
return {'isAdmin': False}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we stick to snake_case for consistency? is_admin instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, will update it now.

def post(self):
current_user = get_jwt_identity()
new_token = create_access_token(identity=current_user, fresh=False)
return {'access_token': new_token}, 200
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we still doing token refreshes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I removed fresh login, but we still have refresh token. I'll add some more notes to explain these terms.

@CristianoYL
Copy link
Contributor Author

Some small improvements to the code.

I also added some more detailed explanation in README.md file in the section sub-directory. I exported the sample Postman request collection to the folder as well.

It should be finalized now. Let me know if there's anything wrong or any questions.

@CristianoYL
Copy link
Contributor Author

I renamed the folder for Flask-JWT-Extended to be section 11, since I suppose it would be the last section of the course now. (Move the Bonus Section from Section 11 to Section 12)

@jslvtr jslvtr merged commit f91f64e into master May 5, 2018
@jslvtr jslvtr deleted the sections/flask-jwt-extended branch August 11, 2021 10:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants