Flask stateless authentication with secrets
Project description
Flask-Stateless-Auth
A lightweight no-batteries-included stateless authentication extension for Flask.
Features
-
Flask-Stateless-Auth assists with stateless authentication in case a Flask developer decides to:
- Authenticate statelessly without the use of sessions.
- Not to issue signed tokens e.g.(JWT), instead issue tokens that are to be validated against a db or a datastore of sorts.
-
Flask-Stateless-Auth stores a current_stateless_user variable in the request context upon authentication using the
token_requireddecorator -
Developer is free to implement their own authorization scheme, However:
- A typical
header_nameis 'Authorization' - A typical
auth_typeis 'Bearer' - A typical
tokenis a random b64 encoded string. - A typical
token_typeis: an access or refresh token
- A typical
-
2 Signals provided:
user-authorizeduser-unauthorized
Setup ⚙️
$ pip install flask-stateless-auth
Quick Start
# initializations
stateless_auth_manager = StatelessAuthManager()
app = Flask(__name__.split('.')[0])
# configs
class Config:
#TOKEN_TYPE = 'Bearer' # Default
#TOKEN_HEADER = 'Authorization'# Default
#ADD_CONTEXT_PROCESSOR = True # Default
#DEFAULT_TOKEN_TYPE = 'access' # Default
# models
class User(UserMixin):
def __init__(self, id, username):
self.id = id
self.username = username
class Token(TokenMixin):
def __init__(self, user_id, access_token, refresh_token):
self.user_id = user_id
self.access_token = access_token
self.refresh_token = refresh_token
# db
users = [
User(1, 'first_user'),
User(2, 'second_user')
]
tokens = [
Token(1, 'first_user_access_token', 'first_user_refresh_token'),
Token(2, 'second_user_access_token', 'second_user_refresh_token')
]
# First loader
@stateless_auth_manager.token_loader
def token_by(token, token_type, auth_type):
''' where `token` is the token loaded from the header '''
try:
for token in tokens:
if token_type == 'access'
if token.access_token == token:
return token
elif token_type == 'refresh':
if token.refresh_token == token:
return token
raise StatelessAuthError(msg='{} Invalid token'.format(token.type), code=401, type_='Token')
except StatelessAuthError:
raise
except Exception as e:
log.critical(e)
raise StatelessAuthError(msg='internal server error', code=500, type_='Server')
# Second loader
@stateless_auth_manager.user_loader
def user_by_token(token):
''' where `token` is the token model loaded from the token table '''
try:
for user in users:
if user.id == token.id: return user
except Exception as e:
log.critical(e)
raise StatelessAuthError(msg='internal server error', code=500, type_='Server')
log.critical('token: {} belongs to a user: {} but user wasn't found'.format(token.id, user.id))
raise StatelessAuthError(msg='internal server error', code=500, type_='Server')
# Error handler
@app.errorhandler(StatelessAuthError)
def handle_stateless_auth_error(error):
return jsonify({'error': error.full_msg}), error.code
@app.route('/secret', methods=['GET'])
@token_required(token_type='access', auth_type='Bearer') #access by default
def secret():
data = {'secret': 'Stateless auth is awesome :O'}
return jsonify(data), 200
@app.route('/whoami', methods=['GET'])
@token_required
def whoami():
data = {'my_username': current_stateless_user.username}
return jsonify(data), 200
if __name__ == '__main__':
app.config.from_object(Config())
stateless_auth_manager.init_app(app)
app.run()
- For a more practical example, check out:
tests/app_example.pyandtests/test_app.py.
Important Remarks:
-
Flask-Stateless-Auth enforces the use of the following authorization format:
{"header_name": "auth_type" + " " + "token"}
-
Flask-Stateless-Auth needs 2 callbacks in order to function properly:
token_loader: Should load a token from your models given, atoken,token_type, andauth_typeuser_loader: Should load a user from your models given token(token loaded fromtoken_loader)
-
Flask-Stateless-Auth also needs a StatlessAuthError error handler. The handler will receive an error with the following attributes:
error.code: suggested status codeerror.msg: messageerror.type: Error type ('token', 'request', 'scope')error.full_msg: Error msg + type- The developer can then decide how to handle each error seperately by controlling the info they would want to give out to the api client.
-
It is recommended that you raise a StatelessAuthError in case a token or a user cannot be loaded. However, you can still return
Noneand FlaskStatelessAuth will return a generic error message and code. -
Your token model must have an
is_expired()method that takes a request'sauth_type(e.g. 'bearer') andtoken_type(e.g. 'access' or 'refresh') and returns a boolean. -
Your user model must have an
is_activeproperty that returns a boolean. -
If you don't want to implement point
5.and6.then you can simply make your token and user models inherit from theTokenMixinandUserMixinmixins respecitvely.
Testing
$ tox
API
- StatelessAuthManager
- StatelessAuthError
- current_stateless_user
- token_required()
- TokenMixin
- UserMixin
Contact 📧
I currently work as a freelance software devloper. Like my work and got a gig for me?
Want to hire me fulltime? Send me an email @ omarryhan@gmail.com
Buy me a coffee ☕
Bitcoin: 3NmywNKr1Lzo8gyNXFUnzvboziACpEa31z
Ethereum: 0x1E1400C31Cd813685FE0f6D29E0F91c1Da4675aE
Bitcoin Cash: qqzn7rsav6hr3zqcp4829s48hvsvjat4zq7j42wkxd
Litecoin: MB5M3cE3jE4E8NwGCWoFjLvGqjDqPyyEJp
Paypal: https://paypal.me/omarryhan
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file flask-stateless-auth-0.0.17.tar.gz.
File metadata
- Download URL: flask-stateless-auth-0.0.17.tar.gz
- Upload date:
- Size: 9.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.6.3 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9be6aba83e3b0cc8ff50e2c51fb7e8174396f0903e1404e3145c704267f89b0
|
|
| MD5 |
9bd267c0f3c8ffa873bf12a810d47554
|
|
| BLAKE2b-256 |
d8f55e14780ec7bdb4398c46ec9c5f0e4a8774b748518bcba61198c727f1b659
|