okta / okta-mobile-swift

okta-mobile-swift
https://github.com/okta/okta-mobile-swift
Apache License 2.0
44 stars 19 forks source link

Cannot Sign In Immediately After Signing Out #140

Closed aetherealtech closed 1 year ago

aetherealtech commented 1 year ago

Describe the bug?

Calling await webInterface.signOut, and after it succeeds, calling await webInterface.signIn, never shows the sign in web view (because the sign out view is not fully dismissed yet) and does not report any errors indicating that the presentation failed. Instead it blocks forever on the await.

What is expected to happen?

Ideally await webInterface.signOut should block until the transient web view is fully dismissed, at which point it would be safe to call await webInterface.signIn.

If this is not possible, await webInterface.signIn should at least throw an exception if it fails to present, so that we can catch it and try presenting again.

What is the actual behavior?

await webInterface.signOut does not wait until the dismissal animation for the sign-out web view is completed (it appears to finish when the dismissal animation starts). When await webInterface.signIn fails to present because another presentation is still active, it reports no errors and results in the awaiting task effectively leaking (it will never resume).

Reproduction Steps?

Task {
  try await signOut(from: nil)
  try await signIn(from: nil)
}

Additional Information?

I opened an issue about this a while ago, here: https://github.com/okta/okta-mobile-swift/issues/87

No resolution or suggested workaround was given except to enable ephemeral sessions and just remove the token instead of calling signOut. We were using ephemeral sessions at the time so I accepted this as the solution. Since we now need to use non-ephemeral sessions (we want our users' credentials saved to their phones), this is no longer an option.

SDK Version(s)

1.3.1 (we are stuck on this version until this bug is resolved)

Build Information

No response

mikenachbaur-okta commented 1 year ago

Hi @aetherealtech, this is a known issue with Apple's ASWebAuthenticationSession class. Since it doesn't expose the underlying view controller presented during the sign-in process, there's no way to orchestrate new controller presentations to coincide with the dismissal. The most straightforward approach is to set an arbitrary delay, such as is used here in the sample application when presenting an error alert.

You could potentially observe the view hierarchy, and detect when the presentedViewController changes, and add a block to the view controller's transition coordinator, but that is often overkill for this use-case.

I looked into adding out-of-the-box support for something like this, but that would cause unnecessary delays to everyone's application when it might not be necessary.