orange1
orange1

Reputation: 2939

Authentication for Flask-based API?

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

Answers (1)

Jesvin Jose
Jesvin Jose

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

Related Questions