Skip to content

Commit

Permalink
Enable token refresh for azure (#428)
Browse files Browse the repository at this point in the history
* Added ``offline`` option to ``make_azure_blueprint``. Added test. Added changelog entry.

* Run black

* Drop unnecessary ref

* Change syntax to avoid non-transparent modification of scope

* Fix test, update changelog

* Drop unused kwarg

* Extend scope docstring

* Update link (hopefully to the correct syntax)
  • Loading branch information
emilhe authored Jan 11, 2024
1 parent 92189b1 commit facc344
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 4 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ Changelog

`unreleased`_
-------------
nothing yet
* Set ``auto_refresh_url`` automatically in ``make_azure_blueprint`` when the ``offline_access``
scope is included, thereby enabling automatic token refresh

`7.0.1`_ (2024-01-05)
---------------------
Expand Down
14 changes: 11 additions & 3 deletions flask_dance/contrib/azure.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ def make_azure_blueprint(
Args:
client_id (str): The client ID for your application on Azure AD.
client_secret (str): The client secret for your application on Azure AD
scope (str, optional): comma-separated list of scopes for the OAuth token
scope (str, optional): comma-separated list of scopes for the OAuth token.
If the ``offline_access`` scope is included, automatic token refresh
will be enabled. `See the Azure documentation for more information.
<https://learn.microsoft.com/en-us/entra/identity-platform/scopes-oidc#the-offline_access-scope>`_
redirect_url (str): the URL to redirect to after the authentication
dance is complete
redirect_to (str): if ``redirect_url`` is not defined, the name of the
Expand Down Expand Up @@ -76,6 +79,10 @@ def make_azure_blueprint(
:returns: A :doc:`blueprint <flask:blueprints>` to attach to your Flask app.
"""
scope = scope or ["openid", "email", "profile", "User.Read"]
token_url = f"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token"
authorization_url = (
f"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize"
)
authorization_url_params = {}
if login_hint:
authorization_url_params["login_hint"] = login_hint
Expand All @@ -90,8 +97,9 @@ def make_azure_blueprint(
client_secret=client_secret,
scope=scope,
base_url="https://graph.microsoft.com",
authorization_url=f"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize",
token_url=f"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token",
authorization_url=authorization_url,
token_url=token_url,
auto_refresh_url=token_url if "offline_access" in scope else None,
redirect_url=redirect_url,
redirect_to=redirect_to,
login_url=login_url,
Expand Down
24 changes: 24 additions & 0 deletions tests/contrib/test_azure.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,30 @@ def test_blueprint_factory():
azure_bp.token_url
== "https://login.microsoftonline.com/common/oauth2/v2.0/token"
)
assert azure_bp.auto_refresh_url is None


def test_blueprint_factory_offline():
azure_bp = make_azure_blueprint(
client_id="foo",
client_secret="bar",
scope=["user.read", "offline_access"],
redirect_to="index",
)
assert isinstance(azure_bp, OAuth2ConsumerBlueprint)
assert azure_bp.session.scope == ["user.read", "offline_access"]
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"
)
assert azure_bp.auto_refresh_url is azure_bp.token_url


def test_blueprint_factory_with_domain_hint():
Expand Down

0 comments on commit facc344

Please sign in to comment.