forcedotcom / SalesforceMobileSDK-iOS

iOS SDK for Salesforce
Other
537 stars 419 forks source link

Session is killed or reloaded when backgrounding/foregrounding the App to retrieve 2FA Code #3713

Closed sortinousn closed 3 months ago

sortinousn commented 4 months ago

Please fill out the following details:

  1. Version of Mobile SDK Used: 12
  2. Issue found in Native App or Hybrid App: Native
  3. OS Version: 16
  4. Device: iPhone 12 Pro
  5. Steps to reproduce: Open app, user logs in with username/password or FaceID and taps login. User then gets prompted for 2FA code. User opens email app to get code and input code, when the user opens the app the 2FA screen is gone and they are back at the login screen. User can't login because they are unable to enter the code.
  6. Actual behavior:
  7. Expected Behavior: User gets prompted for 2FA Code, if they background the app and them foreground it then the 2FA screen should still be showing and not reloaded or kicked back to the login screen.
bbirman commented 4 months ago

@sortinousn can you tell us more about your integration? Are you using AuthHelper.loginIfRequired? Where do you call it from if so?

sortinousn commented 4 months ago

@sortinousn can you tell us more about your integration? Are you using AuthHelper.loginIfRequired? Where do you call it from if so?

Yes, i am using one of the SDK iOS templates for Salesforce since we want to use biometrics to allow users log in to our member portal. Our authenticated site is served through a webview (Contentview.Swift) after successful authentication with Salesforce. This is working for the most part, its only when a user gets prompted for an MFA code that they can never enter the code since when the minimize the app/background the app to retrieve the code via email or message app the MFA screen to enter the code is lost and they are back at the login screen to enter their username/password

I am thinking the authview/initial view controller is always being recreated whenever the app is foregrounded rather than restoring the view? We don't seem to have any control of the app during authentication process as it seems the sdk handles this. Is there a way to restore the MFA screen on foregrounding/backgrounding of the app?

// SceneDelegate.swift
 ....

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
               options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        self.window = UIWindow(frame: windowScene.coordinateSpace.bounds)
        self.window?.windowScene = windowScene
        SalesforceManager.shared.biometricAuthenticationManager().biometricOptIn(optIn: true)
        // Define a response to user change events
        AuthHelper.registerBlock(forCurrentUserChangeNotifications: {
            self.resetViewState {
                self.setupRootViewController()
            }

        })
    }

    func setupRootViewController() {
        MobileSyncSDKManager.shared.setupUserStoreFromDefaultConfig()

       // We are authenticated and redirected to authenticated member portal
        self.window?.rootViewController = UIHostingController(rootView: ContentView())
    }

func sceneWillEnterForeground(_ scene: UIScene) {
        self.initializeAppViewState()
        AuthHelper.loginIfRequired {
            self.setupRootViewController()
        }
    }
}

...
ContentView.swift

...
struct ContentView: View {
    @State private var isLoading = true

    let accessToken = UserAccountManager.shared.currentUserAccount?.credentials.accessToken as? String ?? ""
    let clientID = UserAccountManager.shared.currentUserAccount?.credentials.clientId as? String ?? ""

    var body: some View {
        let url = String("\(Environment.sf)/secur/frontdoor.jsp?allp=1&apv=1&cshc=C00000000084sfhj3e&refURL=\(Environment.sf)%2Fsecur%2Ffrontdoor.jsp&retURL=%2Fphim%2Fapex%2FPHMPCommunitiesLanding&sid=\(accessToken)&untethered=")
        WebView(url: URL(string: url)!, isLoading: $isLoading)
            .overlay(ActivityIndicator(isAnimating: $isLoading))
    }
}
bbirman commented 3 months ago

Could you try moving AuthHelper.loginIfRequired from sceneWillEnterForeground... to scene(_ scene: UIScene, willConnectTo...? Here's a similar example: https://github.com/forcedotcom/SalesforceMobileSDK-iOS/blob/07d450509d7e60ee4a89ca39ece22776355555c0/native/SampleApps/RestAPIExplorer/RestAPIExplorer/SceneDelegate.swift#L41-L49