Flask-Admin authentication through oAuth

Flask-Admin provides the examples of authentication with Flask-Login and Flask-Security. Here is an example how to authenticate using Microsoft oAuth.

Create an application in Microsoft Application Registration Portal.

Add admin_auth.py.

import jwt
from flask import Blueprint, url_for, request, session, redirect
from flask_oauthlib.client import OAuth

APP_KEY = '...'
APP_SECRET = '...' 
ALLOWED_IDS = ['user@domain.com']

admin_auth_blueprint = Blueprint('admin_auth', __name__)

oauth = OAuth()
azure = oauth.remote_app(
    'azure',
    consumer_key=APP_KEY,
    consumer_secret=APP_SECRET,
    request_token_params={'scope': 'openid profile email'},
    base_url='https://graph.microsoft.com/v1.0/',
    request_token_url=None,
    access_token_method='POST',
    access_token_url='https://login.microsoftonline.com/common/oauth2/v2.0/token',
    authorize_url='https://login.microsoftonline.com/common/oauth2/v2.0/authorize')


def is_authenticated():
    return session.get('admin_authenticated', False)


@admin_auth_blueprint.route('/')
def login():
    if request.args.get('code'):
        response = azure.authorized_response()
        id_token = jwt.decode(response['id_token'], verify=False)
        id = id_token.get('email') or id_token.get('preferred_username')
        if id in ALLOWED_IDS:
            session['admin_authenticated'] = id
            return redirect(url_for('admin.index'))
        return 'No access', 403
    else:
        callback_url = url_for('admin_auth.login', _external=True)
        return azure.authorize(callback=callback_url)


@admin_auth_blueprint.route('/logout')
def logout():
    del session['admin_authenticated']
    return redirect('/')

For admin part create an AuthMixin with is_accessible and inaccesibble_callback methods and use it in admin views.

from flask_admin import Admin
from flask_admin.contrib.mongoengine import ModelView

class AuthMixin(object):

    def is_accessible(self):
        return is_authenticated()

    def inaccessible_callback(self, name, **kwargs):
        return redirect(url_for('admin_auth.login'))


class MyModelView(AuthMixin, ModelView):
    pass

adm = Admin(...)
adm.add_view(MyModelView(MyModel))
adm.add_link(MenuLink(name='Logout', endpoint='admin_auth.logout'))

Register the admin_auth_blueprint blueprint in the Flask app.

comments powered by Disqus