From 9637f5ad22f7ce7294c579cc6904ab8017b4e8bd Mon Sep 17 00:00:00 2001 From: gchq83514 <56722860+gchq83514@users.noreply.github.com> Date: Mon, 21 Oct 2019 09:50:55 +0100 Subject: [PATCH] Updated Azure to allow defining authorization_url_params (#288) Azure configuration: allow prompt, domain_hint, and login_hint --- CHANGELOG.rst | 1 + flask_dance/contrib/azure.py | 27 ++++++++++++++ tests/contrib/test_azure.py | 72 ++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f0aa20d0..0bc2526a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,6 +7,7 @@ Changelog to include the ``client_id`` in the OAuth token request. * Removed Okta pre-set configuration, since it doesn't add any value over using ``OAuth2ConsumerBlueprint`` directly. +* Updated Azure to allow defining ``authorization_url_params`` `2.2.0`_ (2019-06-04) --------------------- diff --git a/flask_dance/contrib/azure.py b/flask_dance/contrib/azure.py index 69d6760a..ef8453fc 100644 --- a/flask_dance/contrib/azure.py +++ b/flask_dance/contrib/azure.py @@ -24,6 +24,9 @@ def make_azure_blueprint( session_class=None, storage=None, tenant="common", + prompt=None, + domain_hint=None, + login_hint=None, ): """ Make a blueprint for authenticating with Azure AD using OAuth 2. This requires @@ -55,12 +58,35 @@ def make_azure_blueprint( `See the Azure documentation for more information about this parameter. `_ Defaults to ``common``. + prompt (str, optional): Indicate the type of user interaction that is required. + Valid values are ``login``, ``select_account``, ``consent``, ``admin_consent``. + Learn more about the options `here. + `_ + Defaults to ``None`` + domain_hint (str, optional): Provides a hint about the tenant or domain that + the user should use to sign in. The value of the domain_hint is a + registered domain for the tenant. If the tenant is federated to an + on-premises directory, AAD redirects to the specified tenant federation server. + Defaults to ``None`` + login_hint (str, optional): Can be used to pre-fill the username/email + address field of the sign-in page for the user, if you know their + username ahead of time. Often apps use this parameter during re-authentication, + having already extracted the username from a previous sign-in using the + preferred_username claim. + Defaults to ``None`` :rtype: :class:`~flask_dance.consumer.OAuth2ConsumerBlueprint` :returns: A :ref:`blueprint ` to attach to your Flask app. """ scope = scope or ["openid", "email", "profile", "User.Read"] + authorization_url_params = {} + if login_hint: + authorization_url_params["login_hint"] = login_hint + if domain_hint: + authorization_url_params["domain_hint"] = domain_hint + if prompt: + authorization_url_params["prompt"] = prompt azure_bp = OAuth2ConsumerBlueprint( "azure", __name__, @@ -78,6 +104,7 @@ def make_azure_blueprint( redirect_to=redirect_to, login_url=login_url, authorized_url=authorized_url, + authorization_url_params=authorization_url_params, session_class=session_class, storage=storage, ) diff --git a/tests/contrib/test_azure.py b/tests/contrib/test_azure.py index f0b4b188..810e7dae 100644 --- a/tests/contrib/test_azure.py +++ b/tests/contrib/test_azure.py @@ -43,6 +43,78 @@ def test_blueprint_factory(): ) +def test_blueprint_factory_with_domain_hint(): + azure_domain_bp = make_azure_blueprint( + client_id="foo", + client_secret="bar", + scope="user.read", + redirect_to="index", + domain_hint="Sample Hint", + ) + 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["domain_hint"] == "Sample Hint" + 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 test_blueprint_factory_with_login_hint(): + azure_domain_bp = make_azure_blueprint( + client_id="foo", + client_secret="bar", + scope="user.read", + redirect_to="index", + login_hint="Sample Login Hint", + ) + 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["login_hint"] == "Sample Login Hint" + 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 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 test_blueprint_factory_with_organization_tenant(): azure_orgs_bp = make_azure_blueprint( client_id="foo",