Reputation: 2939
I've built out an API via Flask views, which users access using some endpoints at /api/v1/....
. I'd like to authenticate users who make requests. What are ways to enforce authentication with my API? Is there a way to avoid building out a user model, and instead use Google or Github-based authentication?
Upvotes: 0
Views: 687
Reputation: 23078
I use flask-login which intercepts web requests with sessions and ones with a header. Requests from the web use Flask's session, requests from mobile apps send a header.
These methods return users for the given request. The API token is signed (tamperproofed) by itsdangerous, which powers Flask's cookies.
from itsdangerous import URLSafeSerializer, BadData
serializer = URLSafeSerializer(CONFIG['SECRET_KEY'])
def load_user_from_request(request):
token = request.headers.get('API-TOKEN')
if token:
try:
user_id = serializer.loads(token)["id"]
user = User.query.filter(User.active == True, User.id == int(user_id)).first()
if user:
return user
except BadData as e:
pass
return None
def load_user(id):
user = User.query.filter(User.active == True, User.id == int(id)).first()
if not user:
return None
return user
login_manager.user_loader(load_user)
login_manager.request_loader(load_user_from_request)
This endpoint takes in an authentication request, checks the username and password and issues a token. The itsdangerous serializer makes a tamperproof version of your object. The client submits the same as a header. As long as the app's secret key is safe, your servers can confirm that signed objects were issued by your servers.
@blueprint.route('/api_auth', methods=["post"])
def api_auth():
...check username and password
return response({
'API-TOKEN': serializer.dumps({'id': user.id})
})
Upvotes: 2