Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions msal/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@


# The __init__.py will import this. Not the other way around.
__version__ = "1.5.0"
__version__ = "1.5.1"

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -193,6 +193,18 @@ def __init__(
Default value is None, means it will not be passed to Microsoft.
:param list[str] client_capabilities: (optional)
Allows configuration of one or more client capabilities, e.g. ["CP1"].

Client capability is meant to inform the Microsoft identity platform
(STS) what this client is capable for,
so STS can decide to turn on certain features.
For example, if client is capable to handle *claims challenge*,
STS can then issue CAE access tokens to resources
knowing when the resource emits *claims challenge*
the client will be capable to handle.

Implementation details:
Client capability is implemented using "claims" parameter on the wire,
for now.
MSAL will combine them into
`claims parameter <https://openid.net/specs/openid-connect-core-1_0-final.html#ClaimsParameter`_
which you will later provide via one of the acquire-token request.
Expand Down Expand Up @@ -264,7 +276,8 @@ def _build_client(self, client_credential, authority):
default_body=default_body,
client_assertion=client_assertion,
client_assertion_type=client_assertion_type,
on_obtaining_tokens=self.token_cache.add,
on_obtaining_tokens=lambda event: self.token_cache.add(dict(
event, environment=authority.instance)),
on_removing_rt=self.token_cache.remove_rt,
on_updating_rt=self.token_cache.update_rt)

Expand All @@ -275,7 +288,7 @@ def get_authorization_request_url(
login_hint=None, # type: Optional[str]
state=None, # Recommended by OAuth2 for CSRF protection
redirect_uri=None,
response_type="code", # Can be "token" if you use Implicit Grant
response_type="code", # Could be "token" if you use Implicit Grant
prompt=None,
nonce=None,
domain_hint=None, # type: Optional[str]
Expand All @@ -292,7 +305,11 @@ def get_authorization_request_url(
Address to return to upon receiving a response from the authority.
:param str response_type:
Default value is "code" for an OAuth2 Authorization Code grant.
You can use other content such as "id_token".

You could use other content such as "id_token" or "token",
which would trigger an Implicit Grant, but that is
`not recommended <https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-implicit-grant-flow#is-the-implicit-grant-suitable-for-my-app>`_.

:param str prompt:
By default, no prompt value will be sent, not even "none".
You will have to specify a value explicitly.
Expand Down Expand Up @@ -735,6 +752,11 @@ def _acquire_token_silent_by_finding_specific_refresh_token(
response = client.obtain_token_by_refresh_token(
entry, rt_getter=lambda token_item: token_item["secret"],
on_removing_rt=rt_remover or self.token_cache.remove_rt,
on_obtaining_tokens=lambda event: self.token_cache.add(dict(
event,
environment=authority.instance,
skip_account_creation=True, # To honor a concurrent remove_account()
)),
scope=scopes,
headers={
CLIENT_REQUEST_ID: correlation_id or _get_new_correlation_id(),
Expand Down Expand Up @@ -936,7 +958,8 @@ def _acquire_token_by_username_password_federated(
"https://github.com/AzureAD/microsoft-authentication-library-for-python/wiki/Username-Password-Authentication")
logger.debug("wstrust_endpoint = %s", wstrust_endpoint)
wstrust_result = wst_send_request(
username, password, user_realm_result.get("cloud_audience_urn"),
username, password,
user_realm_result.get("cloud_audience_urn", "urn:federation:MicrosoftOnline"),
wstrust_endpoint.get("address",
# Fallback to an AAD supplied endpoint
user_realm_result.get("federation_active_auth_url")),
Expand Down
4 changes: 3 additions & 1 deletion msal/oauth2cli/oauth2.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ def __init__(self,
def _obtain_token(
self, grant_type, params=None, data=None,
also_save_rt=False,
on_obtaining_tokens=None,
*args, **kwargs):
_data = data.copy() # to prevent side effect
resp = super(Client, self)._obtain_token(
Expand All @@ -481,7 +482,7 @@ def _obtain_token(
# but our obtain_token_by_authorization_code(...) encourages
# app developer to still explicitly provide a scope here.
scope = _data.get("scope")
self.on_obtaining_tokens({
(on_obtaining_tokens or self.on_obtaining_tokens)({
"client_id": self.client_id,
"scope": scope,
"token_endpoint": self.configuration["token_endpoint"],
Expand All @@ -495,6 +496,7 @@ def obtain_token_by_refresh_token(self, token_item, scope=None,
rt_getter=lambda token_item: token_item["refresh_token"],
on_removing_rt=None,
on_updating_rt=None,
on_obtaining_tokens=None,
**kwargs):
# type: (Union[str, dict], Union[str, list, set, tuple], Callable) -> dict
"""This is an overload which will trigger token storage callbacks.
Expand Down
4 changes: 3 additions & 1 deletion msal/token_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ def __add(self, event, now=None):
environment = realm = None
if "token_endpoint" in event:
_, environment, realm = canonicalize(event["token_endpoint"])
if "environment" in event: # Always available unless in legacy test cases
environment = event["environment"] # Set by application.py
response = event.get("response", {})
data = event.get("data", {})
access_token = response.get("access_token")
Expand Down Expand Up @@ -170,7 +172,7 @@ def __add(self, event, now=None):
at["key_id"] = data.get("key_id")
self.modify(self.CredentialType.ACCESS_TOKEN, at, at)

if client_info:
if client_info and not event.get("skip_account_creation"):
account = {
"home_account_id": home_account_id,
"environment": environment,
Expand Down