Open LibertyDev18 opened 1 year ago
Hi @LibertyDev18, thanks for your inquiry. Do you mind sharing the error Domain, Code, and possibly any logs. From testing, i see we return NSURLErrorDomain Code=-1009 "The internet connection appears to be offline with other network error details.
Hi @antonioalwan, for sure. Just to be clear, this ONLY occurs when we are using the SSO Extension. We get a more appropriate system level network error when the SSO Extension is not in play.
When we restore network access the acquireTokenSilentWithParameters call succeeds as expected.
Error Domain=MSALErrorDomain Code=-50002 "(null)" UserInfo={MSALErrorDescriptionKey=No token matching arguments found in the cache, user interaction is required, MSALCorrelationIDKey=...}
I can provide more in depth MSAL logs via a different channel but here is a small snippet that might be helpful.
MSAL 1.2.15 iOS 16.6 [2023-09-01 18:20:59 - [MSAL] Didn't find family refresh token MSAL 1.2.15 iOS 16.6 [2023-09-01 18:20:59 - Creating Error with description: No token matching arguments found in the cache, user interaction is required MSAL 1.2.15 iOS 16.6 [2023-09-01 18:20:59 - [MSAL] Silent flow finished. Result (null), error: -51115 error domain: MSIDErrorDomain MSAL 1.2.15 iOS 16.6 [2023-09-01 18:20:59 - [MSAL] Silent broker extension flow finished. Result (null), error: -51115 error domain: MSIDErrorDomain, shouldFallBack: 1
To recreate the issue. We first successfully get an access token with MSAL leveraging the SSO Extension. We "disconnect" the device from any valid network. After the access token expires and we attempt to refresh silently we get the interaction required response instead of the actual network error.
Hi @antonioalwan, just checking in to see if you have been able to find anything and/or confirm behavior? Thanks!
Hi @LibertyDev18, Thanks for checking again. This is being validated and will update on the outcome soon
@antonioalwan, bumping this for an update.
@LibertyDev18 For silent flow, the logic works first by checking cached credentials before having any connection established. Once it is found that no cached credentials exist in cache for the user, the error is thrown to have an interactive request. Now, once interactive request is started, it detects the connection error and returns it. In most cases, there shouldn't be need to communicate with AAD if credentials are available in cache. So therefore, it makes sense not to check internet connection before checking the cache otherwise we would have an error for no reason.
Hi @antonioalwan, thank you for the additional information.
So, I guess my question here is more around the difference in behavior between a device with the SSO Extension enabled and one that does not. The behavior is NOT the same when attempting a silent auth flow.
Device with SSO Extension In this case MSAL works as you describe and the error to perform an interactive request is returned
Device without SSO Extension In this case MSAL returns the system level NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline."
My expectation would be that they should/would behave the same in both cases and looking to confirm if the difference is intentional?
Hi @antonioalwan, curious if you were able to provide any additional insight to the question in my last post?
Hi @LibertyDev18, Comparing silent flow for either SSO Extension and MSAL show same result as described above by checking the cache first and returning the interactive error when token. Were you able to compare that the error returned is different when no user has logged-in prior to acquireSilent using interactive flow for both cases?
Hi @antonioalwan, yes, these are identical A/B tests where all that is happening is a token is being refreshed silently after a previous successful acquisition of a token when a network connection is present.
Exact same scenario, exact same use case, the only difference is SSO Extension. The result is not the same. Two different response codes are returned. In the non-SSO Extension flow a network error is returned and not interaction required.
The network error is what the MSAL documentation indicates should/will be returned in this case.
Hi @LibertyDev18, There seems to be a difference between our setup as following the steps and applying identical A/B tests to refresh silently for both scenarios when we are using SSO extension and MSAL, the result was showing identical in both cases to 'No token matching arguments found in the cache, user interaction is required. Code= -50002'.
Note that the cache has to be cleared so that no tokens are found. If tokens are in the cache, they will be returned.
For interactive requests, it will always return Code 1009 for both SSO extension and MSAL when the internet connection is disconnected. Can I suggest writing down the steps in both scenarios and sharing the difference of the log?
Hi @antonioalwan, I'll spin up a very quick & simple sample project that might help with this so we're working off the exact same code. Do you have a location that I can supply that to you directly?
I'll also document the exact steps used to reproduce both scenarios and supply that with the project.
Hi @antonioalwan, I've created a sample project that I can send over to you to run and see the results. The project has full MSAL logging enabled. Project has a min target of iOS 16.4 and is using MSAL 1.2.16.
The difference between the two devices is that one is a fully managed device with the SSO Extension enabled while the other is using MSAL only (no device management, no Authenticator, just MSAL).
Attempting to refresh, a previously acquired token, silently when the NO SSO EXTENSION device has no network connection results in the following error: 2023-09-21 13:36:52.411236-0500 MSAL Behavior Tester[38088:2659419] Task <065E26F8-5443-4131-A522-8F7C68E3B391>.<1> HTTP load failed, 0/0 bytes (error code: -1009 [1:50]) 2023-09-21 13:36:52.416974-0500 MSAL Behavior Tester[38088:2659420] Task <065E26F8-5443-4131-A522-8F7C68E3B391>.<1> finished with error [-1009] Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={_kCFStreamErrorCodeKey=50, NSUnderlyingError=0x2804187e0 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_NSURLErrorNWPathKey=unsatisfied (No network route), _kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <065E26F8-5443-4131-A522-8F7C68E3B391>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask <065E26F8-5443-4131-A522-8F7C68E3B391>.<1>"
Attempting to refresh, a previously acquired token, silently when the SSO EXTENSION device has no network connection results in the following error: 2023-09-21 13:51:28.032677-0500 MSAL Behavior Tester[24471:1912172] MSAL Error: Error Domain=MSALErrorDomain Code=-50002 "(null)" UserInfo={MSALErrorDescriptionKey=No token matching arguments found in the cache, user interaction is required, MSALCorrelationIDKey=58E9EE30-5CE1-4E1B-9404-6B9F5F2BCFC8} ... 2023-09-21 13:51:28.052382-0500 MSAL Behavior Tester[24471:1912169] MSAL log: TID=1912172 MSAL 1.2.16 iOS 16.6.1 [2023-09-21 18:51:28 - 58E9EE30-5CE1-4E1B-9404-6B9F5F2BCFC8] [MSAL] acquireTokenSilent returning with error: (MSALErrorDomain, -50002) Masked(not-null)
@LibertyDev18 I see, thanks for detailing the errors and resubmitting the steps. The difference seems related to expired cached tokens vs. cleared cached tokens. I need to run this scenario and check the code path.
@LibertyDev18 You stated that you created a sample project. Do you mind sending it to antonioalwan@microsoft.com? Thanks!
Hi @antonioalwan, sent the sample project over to you. Thanks!
Hi @LibertyDev18, I validated this scenario and ran both cases where I saw the issue. However, in the SSO Extension case, the result shows a different error as interaction is required because no PRT exists in the cache. To achieve that, You need to log in using SSO extension with the same user prior to testing the second scenario. Once logged in, A Refresh token would be cached and then the error for interaction required won't be shown.
Hi @antonioalwan, thank you for looking into this further and the additional information. When we are testing the SSO extension path we are using the SSO extension to log the user in and secure the initial access token as the first app they install on the device directly through the test app. Are you saying we need to first log in directly to Authenticator first?
Hi @LibertyDev18, For the first time when setting up SSO Extension, a test user can log in with a network connection. Once logged in, a PRT would be cached. The test user can validate that SSO works by logging in through the browser where SSO is validated by allowing to log in without prompting for credentials. The next step in testing, disconnect from the network and log in. PRT should be available and it shouldn't return the interaction required.
Hi @antonioalwan, okay, so I'm not sure I'm following.
"For the first time when setting up SSO Extension, a test user can log in with a network connection. Once logged in, a PRT would be cached." This is exactly what step one of the test case is. We perform an interactive auth flow on the SSO Extension device via MSAL. Should this action not cache the PRT?
@LibertyDev18 It should, can we verify that login from the browser works without reentering credentials after completing that step?
Hi @antonioalwan, confirmed. I can navigate to a site in Safari that automatically logs the user in after step one in the test app. After thinking about it too, the PRT should be getting secured as part of the initial device enrollment and management.
For this test I:
@LibertyDev18 thanks again for providing the detailed steps. Even though it is invoking SSO Extension this is still MSAL based. There are checks made for AT at MSAL level. The next step flow invokes the broker (SSOExt) and when the broker returns an error there are more checks to try using MSAL RT from cache to update AT. While it may sound simple this is a complex process and a change in this flow could satisfy certain scenarios but break another dependency. The approach we prefer you to take if this is necessary for your app is to have an error handler to check network connectivity in the scenario.
In the SSO Extension context when a device has no internet connection and a call is made to acquireTokenSilentWithParameters when a token needs to be refreshed the API returns MSALErrorInteractionRequired instead of the expected NSURLErrorNotConnectedToInternet response code.
When the SSO Extension is not in play this same request returns the system level error.
Our understanding based on the documentation is that the system level error will be returned in this scenario and has an impact on what path we send users down within our apps. https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-error-handling-ios#error-handling-in-msal-for-iosmacos
We are seeing this behavior with MSAL 1.2.14 & 1.2.15 running on iOS 16 with 6.7.14 of Authenticator.
Thanks for your help in advance!