Closed salman90 closed 1 year ago
I think this is only relevant for OBO so I'll let @bgavrilMS address this
Thanks @tnorling . This is about exposing "Claims" field that comes with AAD errors. This is confidential client specific, it covers public client flows as well.
The flow is:
invalid_grant
+ claimsThere seems to be several issues related to handling claims and CAE in MSAL JS:
@Robbie-Microsoft - I think it makes sense to tackle claim handling next, as it blocks scenarios like CAE
Thanks @tnorling . This is about exposing "Claims" field that comes with AAD errors. This is confidential client specific, it covers public client flows as well.
@bgavrilMS Fixing this will likely address it for all flows anyway but I am curious, what is the public client scenario where AAD would throw claims back to the caller rather than just handling it on their own? My thought was that the absence of claims on the error object is only an issue for OBO because the caller in that scenario is not capable of invoking interaction on its own. I'm not sure I understand why a claims challenge from AAD (rather than a resource) would be necessary in public clients?
Thanks @tnorling . This is about exposing "Claims" field that comes with AAD errors. This is confidential client specific, it covers public client flows as well.
@bgavrilMS Fixing this will likely address it for all flows anyway but I am curious, what is the public client scenario where AAD would throw claims back to the caller rather than just handling it on their own? My thought was that the absence of claims on the error object is only an issue for OBO because the caller in that scenario is not capable of invoking interaction on its own. I'm not sure I understand why a claims challenge from AAD (rather than a resource) would be necessary in public clients?
Excellent question. Apart from OBO there are 2 more scenarios documented here: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-conditional-access-dev-guide#scenario-app-accessing-multiple-services - one is around SPAs and one is "accessing multiple services" - the docs mention a web app calling web apis, but this can very well be a mobile app accessing multiple web apis. CC @jmprieur to keep me honest on this.
@bgavrilMS Thanks for sharing that. After reading through it, it's still not clear to me why the claims are important to the caller in a web app scenario (I also don't see the claims called out explicitly like they are in the OBO section).
Let's ignore silent calls for a moment, if I make an interactive token request in a web app and AAD determines that claims are needed I would expect it to present any prompts it needs to and then return the token with the needed claims. In what scenario would it throw the claims back to the caller and expect the caller to make another interactive request with the claims it just threw?
Now if we agree that AAD should "do the right thing" in an interactive request regardless of whether or not claims are included, then the claims aren't really relevant in a web app at all, even if they are returned in a silent request error, since the "interaction_required" error is enough information for the caller to know what to do to resolve it.
I am not sure about this point @tnorling , hoping that @jmprieur or @salman90 can clarify. It may be a limitation of CA?
The docs and diagrams do show that AAD will reply with an error + claims and that there is an expectation for the app developer to include the claims in a new token request.
@salman90 This issue has been automatically marked as stale because it is marked as requiring author feedback but has not had any activity for 5 days. If your issue has been resolved please let us know by closing the issue. If your issue has not been resolved please leave a comment to keep this open. It will be closed automatically in 7 days if it remains stale.
Just to chime in, so far we didn't run into an issue with any of the CA scenarios we tried using a public client -since STS knows which claims are required, it knows how to get a token with those claims. So @tnorling is right on that account.
Coming back to the silent calls however, since msal.js caches/distinguishes tokens on the basis of claims in addition to scopes and claims are needed in silent requests (as of msal-common@v6), what happens if devs want to retrieve a token from the cache with claims as opposed to going to the network? (my memory is failing me here, as we tried most CA scenarios before this change -@salman90 would be good check this out)
On a more general note, I'm not sure if the SDKs should hide something that the platform itself choses to disclose. If the fact that the claims will be exposed to the app is shared knowledge, there might be features in future that rely on this (though perhaps this is a YAGNI case..)
@bgavrilMS @tnorling I tried both scenarios: SPA calling CA-protected web API using MSAL.js and a web app accessing multiple services (one service is CA protected). In both cases, an interaction_required is enough for the CA to work as expected; as @tnorling said, Azure AD does the right thing with or without a claim.
@derisen in the SPA case, we are not hiding anything because the claim is not sent with the interaction_required error from the auth server. I still need to confirm that the same behavior is happening in the web app scenario. I will debug the app further and confirm.
@bgavrilMS @tnorling I finish debugging the web app scenario; we do receive the claims in the error object:
{"error":"invalid_grant","error_description":"AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new location, you must use multi-factor authentication to access 'GUID'.\r\nTrace ID: 64ab9ad5-447a-432c-ba42-83784ad85800\r\nCorrelation ID: GUID\r\nTimestamp: 2023-01-04 19:44:18Z","error_codes":[50076],"timestamp":"2023-01-04 19:44:18Z","trace_id":"GUID","correlation_id":"GUID","error_uri":"https://login.microsoftonline.com/error?code=50076","suberror":"basic_action","claims":"{\"access_token\":{\"capolids\":{\"essential\":true,\"values\":[\"GUID\"]}}}"}
The scenario works fine with just an interaction, but I think @derisen is correct that we shouldn't hide something (claims) that the platform provides.
I agree, we need to expose the claims as part of the exception data. We have been doing this for years in ADAL and MSAL .NET
Agreed, if it's returned from the service we should return it as well. I started this discussion mostly for my own education so thanks for indulging me. To summarize my understanding of the above: we do not have a functional miss in PCAs today and addressing this bug would just serve to future-proof or add completeness to our interaction_required errors (and address a gap in OBO scenarios).
@Robbie-Microsoft - please pick this up next.
Core Library
MSAL Node (@azure/msal-node)
Core Library Version
1.14.5
Wrapper Library
N/A
Wrapper Library Version
0
Public or Confidential Client?
Confidential
Description
When trying to Implement conditional access (Require MFA) in a
ConfidentialClientApplication
using theacquireTokenOnBehalfOf
API, we are not receiving the claims in the error object to acquire a new access token with the required claims.When looking at the raw response on fiddler, we receive the claims from the token endpoint as shown below:
The issue is when instantiating the InteractionRequiredAuthError class, the claims are not passed to the class. Is there a way to receive the complete error response from msal?
Error Message
Msal Logs
[Tue, 20 Dec 2022 01:28:53 GMT] : @azure/msal-node@1.14.5 : Info - acquireTokenOnBehalfOf called [Tue, 20 Dec 2022 01:28:53 GMT] : [ed732fe7-13fd-4e60-a6e4-719fd554968f] : @azure/msal-common@9.0.1 : Info - SilentFlowClient:acquireCachedToken - No access token found in cache for the given properties.
MSAL Configuration
Relevant Code Snippets
Reproduction Steps
Expected Behavior
Receiving the claims with the InteractionRequiredAuthError to acquire an access token.
Identity Provider
Azure AD / MSA
Browsers Affected (Select all that apply)
Chrome
Regression
No response
Source
Internal (Microsoft)