forcedotcom / SalesforceMobileSDK-iOS

iOS SDK for Salesforce
Other
537 stars 421 forks source link

iOS 14 and 15, Logged Out suddenly #3477

Closed jeremym148 closed 3 weeks ago

jeremym148 commented 2 years ago

Please fill out the following details:

  1. Version of Mobile SDK Used: all
  2. Issue found in Native App or Hybrid App: native
  3. OS Version: 14,15
  4. Device: all
  5. Steps to reproduce: random, when getting push notification or when the phone or the app is not used after 30 minutes
  6. Actual behavior:
  7. Expected Behavior: get access token or refresh token from Keychain
  8. Error Log: nothing

After reading some documentation in the community: https://sourcediving.com/solving-mysterious-logout-issues-on-ios-15-8b818c089466

https://developer.apple.com/documentation/uikit/app_and_environment/responding_to_the_launch_of_your_app/about_the_app_launch_sequence

We can see that during the pre-warm app of iOS, the ProtectedData is not accessible so the access token and refresh token are not accessible and the login web view is pushed on top of the app. Maybe we can avoid it using isProtectedDataAvailable or kSecAttrAccessibleWhenUnlocked before processing any API calls to be sure that the app is able to access the Keychain

All our iOS apps are impacted

bbirman commented 2 years ago

Do you see this on Mobile SDK 9.2.1? In that version we changed the default accessibility from kSecAttrAccessibleWhenUnlockedThisDeviceOnly to kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly to address a similar sounding issue (https://github.com/forcedotcom/SalesforceMobileSDK-iOS/issues/3437).

BinyaminHalimi commented 2 years ago

Hello @bbirman , I tried the new SDK 9.2.1, but unfortunately the problem persist.

bbirman commented 2 years ago

Thanks for the update-- do you have any other information about when/how the failing key access is being attempted? Is the app setting a certain keychain access level instead of using the default?

BinyaminHalimi commented 2 years ago

Hello @bbirman. I can provide you the log that was printed.

Remote Access Consumer Key is missing from Plist file 2022-02-10 15:38:00.601491+0200 [24510:7524794] You've implemented -[ application:didReceiveRemoteNotification:fetchCompletionHandler:], but you still need to add "remote-notification" to the list of your supported UIBackgroundModes in your Info.plist. 2022-02-10 15:38:00.613083+0200 [24510:7524794] -canOpenURL: failed for URL: "cydia://package/com.example.package" - error: "This app is not allowed to query for scheme cydia" 2022-02-10 15:38:00.791301+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFPushNotificationManager Registering with Apple for remote push notifications 2022-02-10 15:38:01.002982+0200 [24510:7525114] 8.10.0 - [Firebase/Analytics][I-ACS023007] Analytics v.8.10.0 started 2022-02-10 15:38:01.003165+0200 [24510:7525114] 8.10.0 - [Firebase/Analytics][I-ACS023008] To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled (see http://goo.gl/RfcP7r) 2022-02-10 15:38:01.004910+0200 [24510:7525113] 8.10.0 - [Firebase/Messaging][I-FCM001000] FIRMessaging Remote Notifications proxy enabled, will swizzle remote notification receiver handlers. If you'd prefer to manually integrate Firebase Messaging, add "FirebaseAppDelegateProxyEnabled" to your Info.plist, and set it to NO. Follow the instructions at: https://firebase.google.com/docs/cloud-messaging/ios/client#method_swizzling_in_firebase_messaging to ensure proper integration. 2022-02-10 15:38:01.006210+0200 [24510:7524794] [Firebase/Crashlytics] Version 8.10.0 2022-02-10 15:38:01.416758+0200 [24510:7524794] [SFSDK] CLASS: _TtCC19SalesforceSDKCommon14KeychainHelper22KeychainUpgradeManager Attempting to upgrade keychain keys. 2022-02-10 15:38:01.455862+0200 [24510:7524794] [SFSDK] CLASS: _TtCC19SalesforceSDKCommon14KeychainHelper22KeychainUpgradeManager Attempting to upgrade keychain keys succeeded. 2022-02-10 15:38:01.456508+0200 [24510:7524794] [SFSDK] CLASS: _TtCC19SalesforceSDKCommon14KeychainHelper22KeychainUpgradeManager Base app identifer retrieved, upgrading dynamic keys. 2022-02-10 15:38:01.496963+0200 [24510:7524794] [SFSDK] CLASS: SFSDKSalesforceSDKUpgradeManager Attempt keychain attribute update 2022-02-10 15:38:01.510342+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFCrypto Base app identifier not configured. Creating a new value. 2022-02-10 15:38:01.510375+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFCrypto Saving the new base app identifier to the keychain. 2022-02-10 15:38:01.511110+0200 [24510:7525126] 8.10.0 - [Firebase/Analytics][I-ACS800023] No pending snapshot to activate. SDK name: app_measurement 2022-02-10 15:38:01.528070+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFCrypto Successfully created a new base app identifier and stored it in the keychain. 2022-02-10 15:38:01.563588+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFSecureEncryptionKey Creating secure key NOT using secure enclave 2022-02-10 15:38:01.564400+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFGeneratedKeyStore Unable to init unarchiver for key store data. Key store is invalid: Error Domain=NSCocoaErrorDomain Code=4864 " -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x4, 0x43, 0xffffffe4, 0xffffffe4, 0xffffffd9, 0x22, 0xffffffcc, 0xffffffd9)" UserInfo={NSDebugDescription= -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x4, 0x43, 0xffffffe4, 0xffffffe4, 0xffffffd9, 0x22, 0xffffffcc, 0xffffffd9)}. 2022-02-10 15:38:01.568534+0200 [24510:7525128] 8.10.0 - [Firebase/Analytics][I-ACS023012] Analytics collection enabled 2022-02-10 15:38:01.568659+0200 [24510:7525128] 8.10.0 - [Firebase/Analytics][I-ACS023220] Analytics screen reporting is enabled. Call +[FIRAnalytics logEventWithName:FIREventScreenView parameters:] to log a screen view event. To disable automatic screen reporting, set the flag FirebaseAutomaticScreenReportingEnabled to NO (boolean) in the Info.plist 2022-02-10 15:38:01.573954+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFSDKSalesforceSDKUpgradeManager Existing account or key is nil 2022-02-10 15:38:01.602761+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFSecurityLockout Resetting passcode. 2022-02-10 15:38:01.641414+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFDefaultUserAccountPersister There is no user account file in this user directory: /var/mobile/Containers/Data/Application/151CE105-BE32-44E3-A914-5158A8E62187/Library//00D7a0000005GRZEA2/0051t00000127weAAA 2022-02-10 15:38:01.647244+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFScreenLockManager Mobile policy stored for user. 2022-02-10 15:38:01.647916+0200 [24510:7524794] [SFSDK] CLASS: SFSDKSalesforceSDKUpgradeManager Upgraded to 9.2.1 Push notifications permission granted 2022-02-10 15:38:01.998214+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFOAuthCoordinator authenticate authenticating as 3MVG90**IaiEh5JBnm.tb without refresh token on 'https://--uat.my.salesforce.com' ... 2022-02-10 15:38:01.998392+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFSDKAuthConfigUtil getMyDomainAuthConfig:loginDomain: Advanced authentication configured. Retrieving auth configuration from https://--uat.my.salesforce.com/.well-known/auth-configuration 2022-02-10 15:38:02.023006+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFPushNotificationManager Registration with Apple for remote push notifications succeeded 2022-02-10 15:38:02.028920+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SalesforceSDKManager Scene 54525B44-6404-46CD-AE2D-C1E278FB139A is resuming active state. 2022-02-10 15:38:02.184355+0200 [24510:7525126] [assertion] Error acquiring assertion: <Error Domain=RBSServiceErrorDomain Code=1 "target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit" UserInfo={NSLocalizedFailureReason=target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit}> 2022-02-10 15:38:02.184583+0200 [24510:7525126] [ProcessSuspension] 0x1178f9a40 - ProcessAssertion: Failed to acquire RBS assertion 'ConnectionTerminationWatchdog' for process with PID=24513, error: Error Domain=RBSServiceErrorDomain Code=1 "target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit" UserInfo={NSLocalizedFailureReason=target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit} 2022-02-10 15:38:02.202471+0200 [24510:7525114] [assertion] Error acquiring assertion: <Error Domain=RBSServiceErrorDomain Code=1 "target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit" UserInfo={NSLocalizedFailureReason=target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit}> 2022-02-10 15:38:02.202547+0200 [24510:7525114] [ProcessSuspension] 0x1178f9b60 - ProcessAssertion: Failed to acquire RBS assertion 'ConnectionTerminationWatchdog' for process with PID=24512, error: Error Domain=RBSServiceErrorDomain Code=1 "target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit" UserInfo={NSLocalizedFailureReason=target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit} 2022-02-10 15:38:02.389976+0200 [24510:7525126] 8.10.0 - [Firebase/InAppMessaging][I-IAM130004] Failed restful api request to fetch in-app messages: seeing http status code as 403 with body as { "error": { "code": 403, "message": "Firebase In-App Messaging API has not been used in project 120111389992 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/firebaseinappmessaging.googleapis.com/overview?project=120111389992 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.", "status": "PERMISSION_DENIED", "details": [ { "@type": "type.googleapis.com/google.rpc.Help", "links": [ { "description": "Google developers console API activation", "url": "https://console.developers.google.com/apis/api/firebaseinappmessaging.googleapis.com/overview?project=120111389992" } ] }, { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "SERVICE_DISABLED", "domain": "googleapis.com", "metadata": { "service": "firebaseinappmessaging.googleapis.com", "consumer": "projects/120111389992" } } ] } } 2022-02-10 15:38:02.392742+0200 [24510:7525126] 8.10.0 - [Firebase/InAppMessaging][I-IAM700002] Error happened during message fetching Error Domain=NSURLErrorDomain Code=403 "(null)" 2022-02-10 15:38:02.431003+0200 [24510:7525114] [SalesforceSDKCore] CLASS: SFSDKAuthConfigUtil Successfully retrieved org auth config data from https://--uat.my.salesforce.com/.well-known/auth-configuration 2022-02-10 15:38:02.432148+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFOAuthCoordinator loadWebViewWithUrlString:cookie: Loading web view for 'SFOAuthTypeUserAgent' auth flow, with URL: https://--uat.my.salesforce.com/services/oauth2/authorize?client_id=3MVG90**IaiEh5JBnm.tb&redirect_uri=sfdc://success&display=touch&device_id=8E6892A4-EA60-4E36-85B0-5608216E7CF1&response_type=hybrid_token&scope=web%20api%20refresh_token 2022-02-10 15:38:02.432304+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFSDKWebViewStateManager [SFSDKWebViewStateManager sharedProcessPool]: No process pool exists. Creating new instance. 2022-02-10 15:38:02.510349+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFOAuthCoordinator webView:didStartProvisionalNavigation: host=--uat.my.salesforce.com : path=/services/oauth2/authorize 2022-02-10 15:38:02.545761+0200 [24510:7525126] [default] Failed to open URL ://google/link/?request_ip_version=IP%5FV4&match_message=No%20pre%2Dinstall%20link%20matched%20for%20this%20device%2E: Error Domain=NSOSStatusErrorDomain Code=-10814 "(null)" UserInfo={_LSLine=225, _LSFunction=-[_LSDOpenClient openURL:options:completionHandler:]} 2022-02-10 15:38:03.068433+0200 [24510:7524794] Unbalanced calls to begin/end appearance transitions for <SFSDKRootController: 0x10c551670>. 2022-02-10 15:38:03.069313+0200 [24510:7524794] [SalesforceSDKCore] CLASS: SFOAuthCoordinator webView:didStartProvisionalNavigation: host=--uat.my.salesforce.com : path=/ 2022-02-10 15:38:32.181405+0200 [24510:7524794] Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service 2022-02-10 15:38:32.199814+0200 [24510:7524794] Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service

AnuragTiwari1 commented 2 years ago

I also faced this, in my case the device was locked and then I got a notification. when I tried to open the notification my device asked for pin and when the app opened I was on login page, I am using hybrid app (react-native-sdk) and being able to reproduce the issue consistently.

I am using v9.2.0

Edit: I will try if upgrading to v9.2.1 fixes this

az-oolloow commented 2 years ago

So I think this might be related to the comment I made here: https://github.com/forcedotcom/SalesforceMobileSDK-iOS/pull/3447#issuecomment-982654888

Not sure if notification wake could do it, but basically if the app is launched in the background and not interactively, the migration in 9.2.1 doesn't have a chance to execute.

For us the solution to the protected data woes was to implement our own logic to safeguard against it, see here: https://github.com/forcedotcom/SalesforceMobileSDK-iOS/issues/3437#issuecomment-978363811

bbirman commented 2 years ago

@az-oolloow based on the comment you made before, we changed the upgrade step to only run if the keychain + protected data was available so that once the user launched the upgraded app the log outs would stop (there could potentially be one more log out after upgrading if it was launched in the background before the user launched it). Did you still see log outs after that which made you need to keep the other logic you mentioned?

iowlit commented 2 years ago

Version of Mobile SDK Used: 10.0 Issue found in Native App or Hybrid App: Native OS Version: 15.5 Device: all Steps to reproduce: random, when the phone or the app is not used after 30 minutes Actual behaviour: the app is getting logged out in background

Hi. Our users are also experiencing sudden logout while app is in background. Remote notifications are disabled in our app. We are accusing "pre-warming" functionality but it is almost imposible to prove. We have no idea how to fix the issue at the moment.

There are logs right before the app is getting logged out:

Screenshot 2022-05-31 at 13 58 42
bcriscuolo-sf commented 2 years ago

@iowlit we've recently addressed this in an app; it requires a bit of workaround to accomplish a clear path forward though.

I believe that technically your users are not logged out. Rather, MobileSDK entered a state (when the app was either pre-warmed or launched in the background) where it could not access the keychain to retrieve the authentication token. This is likely due to the device being locked, possibly after a reboot.

In our method of addressing this, we chose to interrupt our flow in application:didFinishLaunching:withOptions: if we determined that we did not have access to the keychain or protected data. The former was tested by attempting to write something to the keychain, the latter by uiApplication.isProtectedDataAvailable. If either fail, we consider the device not ready for our app.

For simplicity, we present an alert; the button action performs the balance of the setup needed (including initializing MobileSDK).

If the button was tapped, it must mean that the user has unlocked the device and both keychain and protected data area available.

Another option is to observe the protected data notifications. While these do not have a 1:1 mapping with keychain access, they are likely close enough to satisfy what MobileSDK needs.

Best of luck, Brian

iowlit commented 2 years ago

Hi @bcriscuolo-sf. Thanks for your advice. I am likely to add precondition on uiApplication.isProtectedDataAvailable at the very beginning of application:didFinishLaunching:withOptions: the app will simply crash in background with no additional user interaction required.

Zokor commented 1 year ago

We're also having this issue in the new 10.2 and it wasn't present in the 9.0.0.

Any idea when this can be fixed?

bbirman commented 1 year ago

@Zokor do you have logs you can share? do you know if it's happening when receiving a push notification?

Zokor commented 1 year ago

@bbirman we don't have logs. we don't have push notifications unfortunatly. We suspect it may be related with IOS pre-warming the app.

It looks like sdk trying to refresh token while iPad is in sleep mode, and while device is asleep sdk can't access Keychain. so when we open open an app again, it logout user because of no refresh token.

The thread urls seems interesting: https://sourcediving.com/solving-mysterious-logout-issues-on-ios-15-8b818c089466 https://developer.apple.com/documentation/uikit/app_and_environment/responding_to_the_launch_of_your_app/about_the_app_launch_sequence#3894431

These are the hints we have so far to solve this.

However for logs gonna ask if it's possible to have iOS system ones from the QA team.

bcriscuolo-sf commented 1 year ago

@Zokor I believe we've experienced a similar issue, and I think it is happening because of either app warming or background launch.

What you are seeing as a logout may not really be a logout - rather, MobileSDK doesn't have the ability to access the refresh token, and so gets itself into a login state - but in the meantime, you are still logged in.

To combat this, we introduced a check in our applicationDidFinishLaunching where we check both data protection and keychain permissions and access. If we can access both (as appropriate), continue the launch process and initialize MobileSDK (successfully!).

If we cannot access either, return false from applicationDidFinishLaunching and show an alert with a retry button.

If the user ends up seeing the retry button, it means that they've not only brought the app to the foreground, but also that the device is in a usable state (data protection and keychain).

Upon tapping retry, we "complete the launch" - initializing MobileSDK, etc.

While I can't share the code, the flow is pretty easy and has worked consistently for us. Please reach out with any questions - happy to help.

Zokor commented 1 year ago

@bcriscuolo-sf thank you :) you guys added that on this 10.2.0 version? or will be added in a future release?

bcriscuolo-sf commented 1 year ago

We're consuming 10.2.0, but all that is app-side - really just controlling for the app lifecycle better and ensuring MobileSDK is referenced only when in a state for which it can succeed in initializing.

Zokor commented 1 year ago

I see, problem is. We're using Ionic & Angular. We don't have anyone with knowledge of Objective C

wmathurin commented 3 weeks ago

Closing issue - there is a app-level workaround.