def __init__(self, app, client_id, client_secret, expected_issuer, expected_audience, jwks_url, tenant, session_secret, scopes=None, e2e_expected_audience=None, e2e_client_id=None): super(AzureOAuth, self).__init__(app) azure_bp = make_azure_blueprint( client_id=client_id, client_secret=client_secret, scope=scopes, tenant=tenant, ) app.server.register_blueprint(azure_bp, url_prefix="/login") app.server.secret_key = session_secret self._jwkaas = JWKaas(expected_audience, expected_issuer, jwks_url=jwks_url) self._e2e_jwkaas = JWKaas(e2e_expected_audience, expected_issuer, jwks_url=jwks_url) self.client_id = client_id self.e2e_client_id = e2e_client_id self.logout_url = None self.user = None
def register_oauthhandlers(app): blueprint = None if not app.config["OAUTH_TYPE"]: return if app.config["OAUTH_TYPE"] == 'slack': blueprint = slack.make_slack_blueprint( client_id=app.config["OAUTH_ID"], client_secret=app.config["OAUTH_SECRET"], scope="identity.basic,identity.email", redirect_to="auth.slack_login", login_url="/login", # authorized_url=None, # session_class=None, # storage=None, subdomain=app.config["OAUTH_DOMAIN"], ) elif app.config["OAUTH_TYPE"] == 'azure': blueprint = azure.make_azure_blueprint( client_id=app.config["OAUTH_ID"], client_secret=app.config["OAUTH_SECRET"], tenant=app.config["OAUTH_DOMAIN"], scope="profile email User.ReadBasic.All openid", redirect_to="auth.azure_login", login_url="/login", ) elif app.config["OAUTH_TYPE"] == 'github': blueprint = github.make_github_blueprint( client_id=app.config["OAUTH_ID"], client_secret=app.config["OAUTH_SECRET"], # scope="user,read:user", redirect_to="auth.github_login", login_url="/login", ) if blueprint is not None: app.register_blueprint(blueprint, url_prefix="/oauth")
def test_load_from_config(): app = Flask(__name__) app.secret_key = "anything" app.config["AZURE_OAUTH_CLIENT_ID"] = "foo" app.config["AZURE_OAUTH_CLIENT_SECRET"] = "bar" azure_bp = make_azure_blueprint(redirect_to="index") app.register_blueprint(azure_bp) resp = app.test_client().get("/azure") url = resp.headers["Location"] client_id = URLObject(url).query.dict.get("client_id") assert client_id == "foo"
def test_context_local(): responses.add(responses.GET, "https://google.com") # set up two apps with two different set of auth tokens app1 = Flask(__name__) ghbp1 = make_azure_blueprint( "foo1", "bar1", redirect_to="url1", backend=MemoryBackend({"access_token": "app1"}), ) app1.register_blueprint(ghbp1) app2 = Flask(__name__) ghbp2 = make_azure_blueprint( "foo2", "bar2", redirect_to="url2", backend=MemoryBackend({"access_token": "app2"}), ) app2.register_blueprint(ghbp2) # outside of a request context, referencing functions on the `azure` object # will raise an exception with pytest.raises(RuntimeError): azure.get("https://google.com") # inside of a request context, `azure` should be a proxy to the correct # blueprint session with app1.test_request_context("/"): app1.preprocess_request() azure.get("https://google.com") request = responses.calls[0].request assert request.headers["Authorization"] == "Bearer app1" with app2.test_request_context("/"): app2.preprocess_request() azure.get("https://google.com") request = responses.calls[1].request assert request.headers["Authorization"] == "Bearer app2"
def test_blueprint_factory_with_organization_tenant(): azure_orgs_bp = make_azure_blueprint(client_id="foo", client_secret="bar", scope="user.read", redirect_to="index", tenant='organizations') assert isinstance(azure_orgs_bp, OAuth2ConsumerBlueprint) assert azure_orgs_bp.session.scope == "user.read" assert azure_orgs_bp.session.base_url == "https://graph.microsoft.com" assert azure_orgs_bp.session.client_id == "foo" assert azure_orgs_bp.client_secret == "bar" assert azure_orgs_bp.authorization_url == "https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize" assert azure_orgs_bp.token_url == "https://login.microsoftonline.com/organizations/oauth2/v2.0/token"
def test_blueprint_factory(): azure_bp = make_azure_blueprint( client_id="foo", client_secret="bar", scope="user.read", redirect_to="index", ) assert isinstance(azure_bp, OAuth2ConsumerBlueprint) assert azure_bp.session.scope == "user.read" assert azure_bp.session.base_url == "https://graph.microsoft.com" assert azure_bp.session.client_id == "foo" assert azure_bp.client_secret == "bar" assert azure_bp.authorization_url == "https://login.microsoftonline.com/common/oauth2/v2.0/authorize" assert azure_bp.token_url == "https://login.microsoftonline.com/common/oauth2/v2.0/token"
def create_app() -> Flask: """ Creates a flask application and registers the api blueprint. """ if settings.sentry_dsn: log.debug("Initialising Sentry SDK.") sentry_sdk.init( # pylint: disable=abstract-class-instantiated dsn=settings.sentry_dsn, integrations=[FlaskIntegration(), SqlalchemyIntegration()], ) log.debug("Initializing app.") app = Flask(__name__) CORS(app) app.wsgi_app = ProxyFix( # type: ignore app.wsgi_app, x_proto=int(settings.use_x_forwarded_proto), x_host=int(settings.use_x_forwarded_host), ) app.config.update( SECRET_KEY=settings.secret_key, SQLALCHEMY_DATABASE_URI=settings.postgres_dsn, SQLALCHEMY_TRACK_MODIFICATIONS=False, FLASK_ADMIN_SWATCH="darkly", ) if settings.azure_auth_enabled: azure_blueprint = make_azure_blueprint( client_id=settings.azure_client_id, client_secret=settings.azure_client_secret, tenant=settings.azure_tenant, redirect_url="/", ) app.register_blueprint(azure_blueprint) db.sqla.init_app(app) admin.init_app(app) app.register_blueprint(api) log.debug("Migrating database.") run_migrations.main() log.debug("App initialisation complete.") return app
def test_blueprint_factory_with_prompt(): azure_domain_bp = make_azure_blueprint( client_id="foo", client_secret="bar", scope="user.read", redirect_to="index", prompt="select_account", ) assert isinstance(azure_domain_bp, OAuth2ConsumerBlueprint) assert azure_domain_bp.session.scope == "user.read" assert azure_domain_bp.session.base_url == "https://graph.microsoft.com" assert azure_domain_bp.session.client_id == "foo" assert azure_domain_bp.client_secret == "bar" assert azure_domain_bp.authorization_url_params[ "prompt"] == "select_account" assert (azure_domain_bp.authorization_url == "https://login.microsoftonline.com/common/oauth2/v2.0/authorize") assert (azure_domain_bp.token_url == "https://login.microsoftonline.com/common/oauth2/v2.0/token")
def make_azure_blueprint(): """ Following the instructions at https://flask-dance.readthedocs.io/en/latest/providers.html#module-flask_dance.contrib.azure """ arg_name2config_key = { "client_id": "AZURE_OAUTH_CLIENT_ID", "client_secret": "AZURE_OAUTH_CLIENT_SECRET", } config_kwargs = populate_config_kwargs(arg_name2config_key, app.config) kwargs = { "scope": ["https://graph.microsoft.com/.default"], "redirect_to": "oauth_status", } blueprint = azure_dance.make_azure_blueprint(**config_kwargs, **kwargs) blueprint.storage = flask_dance.consumer.storage.sqla.SQLAlchemyStorage(fra_back.models.OAuth, master_session) return blueprint
def init_login(server: Flask) -> Flask: """Add login to server""" # Azure server.secret_key = os.environ["SECRET_KEY"] blueprint = make_azure_blueprint( client_id=os.environ["AZURE_CLIENT_ID"], client_secret=os.environ["AZURE_CLIENT_SECRET"], redirect_url="/login?provider=azure" ) server.register_blueprint(blueprint, url_prefix="/login") # Flask Login login_manager = LoginManager() login_manager.init_app(server) login_manager.login_view = "login" @login_manager.user_loader def load_user(user_id: str) -> Any: """Load User""" return User.query.filter_by(email=user_id).first() @server.route("/logout") @login_required def logout() -> Any: """Logout user""" logout_user() return redirect(url_for("index")) server.route("/login")(login) @login_manager.unauthorized_handler def unauthorized() -> Any: """Redict to login""" return redirect(url_for("login")) return server
from datetime import datetime from flask_migrate import Migrate from flask_login import (LoginManager, UserMixin, current_user, login_required, login_user, logout_user) import json app = Flask(__name__) app.wsgi_app = ProxyFix(app.wsgi_app) app.secret_key = "supersekritit_now" blueprint = make_azure_blueprint( client_id="e9bf7a9a-13bc-4db8-af9d-f6626ec9705f", client_secret="ekbvXCNU187!golTCD36[#|", scope=["User.Read", "profile", "openid", "email"], ) app.register_blueprint(blueprint, url_prefix="/login") import os DATABASE_URL = os.environ.get('DATABASE_URL') test_sql_url = 'sqlite:///../test_ct_db1.db' if DATABASE_URL: app.config['SQLALCHEMY_DATABASE_URI'] = DATABASE_URL else: app.config['SQLALCHEMY_DATABASE_URI'] = test_sql_url app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
def _make_app(*args, **kwargs): app = Flask(__name__) app.secret_key = "whatever" blueprint = make_azure_blueprint(*args, **kwargs) app.register_blueprint(blueprint) return app
login_manager = LoginManager() login_manager.init_app(app) login_manager.login_view = "login" # disable oauth2 https check os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' app.secret_key = "supersekrit" github_bp = make_github_blueprint( client_id="ff51fa522d0edcaa86c7", client_secret="01961dc18f0134f912bda65e6dd98f6ae5b07ef4", redirect_to="authorized_github") app.register_blueprint(github_bp, url_prefix="/login") azure_bp = make_azure_blueprint( client_id="0cd36578-7d2d-46ac-897a-d5edde683a7d", client_secret="wzTOHZ8391(ihinkJCI3~)^", redirect_to="authorized_azure") app.register_blueprint(azure_bp, url_prefix="/login") @login_manager.user_loader def get_user_by_id(user_id): session = DBSession() return session.query(User).filter_by(id=int(user_id)).one_or_none() def get_user_by_email(email): session = DBSession() return session.query(User).filter_by(email=email).one_or_none()
from flask import redirect, url_for, request, current_app, session, flash from flask_dance.contrib.azure import make_azure_blueprint, azure from oauthlib.oauth2.rfc6749.errors import TokenExpiredError, InvalidGrantError from flask_login import login_user from app.user import User azure_app_id = current_app.config['AZURE_APP_ID'] azure_app_pwd = current_app.config['AZURE_APP_PWD'] bp = make_azure_blueprint(client_id=azure_app_id, client_secret=azure_app_pwd, redirect_to='default.logged') @bp.route("/auth_azure", methods=['GET', 'POST']) def authenticate_azure(): if not azure.authorized: return redirect(url_for("azure.login")) try: resp = azure.get("/v1.0/me") assert resp.ok except (InvalidGrantError, TokenExpiredError): return redirect(url_for("azure.login")) # Todo: Investigate more on https://github.com/singingwolfboy/flask-dance/issues/35 resp_json = resp.json() # print(f'Logged User Response:\n{resp_json}') user = { 'id': resp_json["id"], 'name': resp_json["displayName"], 'email': resp_json["mail"], 'given_name': resp_json["givenName"], 'surname': resp_json["surname"], 'job_title': resp_json["jobTitle"],
from wtforms.validators import InputRequired, Email, Length, NumberRange import json from werkzeug.utils import secure_filename import os from oauthlib.oauth2.rfc6749.errors import InvalidClientIdError from oauthlib.oauth2.rfc6749.errors import TokenExpiredError app = Flask(__name__) app.config[ 'SECRET_KEY'] = 'asdfaioasdfkjhasdfkljh349856@#$^@#&@$%UDFHSDFH@#$589234y6oiapdfhgna9088q34258' UPLOAD_FOLDER = 'static/temp/' ALLOWED_EXTENSIONS = set(['csv']) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER blueprint = make_azure_blueprint( client_id="A Thing", client_secret="A Secret", tenant='A Tentant', ) app.register_blueprint(blueprint, url_prefix="/login") def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS class Interaction(FlaskForm): interaction = SelectField('Interaction', choices=[('Voicemail', 'Voicemail'), ('Talked', 'Talked'),