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
Exemple #2
0
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")
Exemple #3
0
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"
Exemple #4
0
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"
Exemple #5
0
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"
Exemple #6
0
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"
Exemple #7
0
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"
Exemple #8
0
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
Exemple #9
0
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"
Exemple #10
0
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
Exemple #13
0
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
Exemple #14
0
 def _make_app(*args, **kwargs):
     app = Flask(__name__)
     app.secret_key = "whatever"
     blueprint = make_azure_blueprint(*args, **kwargs)
     app.register_blueprint(blueprint)
     return app
 def _make_app(*args, **kwargs):
     app = Flask(__name__)
     app.secret_key = "whatever"
     blueprint = make_azure_blueprint(*args, **kwargs)
     app.register_blueprint(blueprint)
     return app
Exemple #16
0
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()

Exemple #17
0
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"],
Exemple #18
0
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'),