Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# UNRELEASED
- Improved the state validation error messages to distinguish a missing `state` parameter from a mismatched one. The end session message now notes that a provider's `end_session_endpoint` may point at a legacy or SAML single-logout endpoint, which does not echo `state`. Addresses issue #956.
- Fixed `OIDExternalUserAgentIOSCustomBrowser` failing the flow with "Unable to open Safari." when `canOpenURL:` returns `NO` for a URL that the system can open, for example an https URL when Safari is restricted and another browser is the default. The flow now fails only if the URL really cannot be opened. Addresses issue #980.
- Fixed a crash when the user cancels sign-in on iOS, caused by `ASWebAuthenticationSession` being deallocated during its completion handler or dismiss animation. Based on [#917](https://github.com/openid/AppAuth-iOS/pull/917) by @Prash88.

# 3.0.0
- BREAKING: Updates made to support Xcode 27. ([#972](https://github.com/openid/AppAuth-iOS/pull/972), [#973](https://github.com/openid/AppAuth-iOS/pull/973))
Expand Down
27 changes: 27 additions & 0 deletions Sources/AppAuth/iOS/OIDExternalUserAgentIOS.m
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,31 @@ @interface OIDExternalUserAgentIOS ()<SFSafariViewControllerDelegate>
@end
#endif

/*! @brief How long a finished session is kept alive once the main queue is next free.
@discussion This is a heuristic. It needs to outlast the session's dismiss transition, which
hasn't started yet when the completion handler runs.
*/
static const NSTimeInterval kOIDSessionRetentionDelay = 2.0;

/*! @brief Keeps @c session alive for a while after the caller lets go of it.
@discussion If the session is deallocated before its dismiss transition ends, it crashes
when the transition completes (FB12132525). The delay starts once the main queue is
free, so a slow completion callback doesn't eat into it.
@param session The session to keep alive, or nil.
*/
static void OIDRetainSessionBriefly(ASWebAuthenticationSession *_Nullable session) {
if (!session) {
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_after(
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kOIDSessionRetentionDelay * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
(void)session;
});
});
}

@implementation OIDExternalUserAgentIOS {
UIViewController *_presentingViewController;
BOOL _prefersEphemeralSession;
Expand Down Expand Up @@ -132,6 +157,7 @@ - (BOOL)presentExternalUserAgentRequest:(id<OIDExternalUserAgentRequest>)request
if (!strongSelf) {
return;
}
OIDRetainSessionBriefly(strongSelf->_webAuthenticationVC);
strongSelf->_webAuthenticationVC = nil;
if (callbackURL) {
// The session matches callback URLs more loosely than the flow checks the redirect URL (a
Expand Down Expand Up @@ -203,6 +229,7 @@ - (void)dismissExternalUserAgentAnimated:(BOOL)animated completion:(void (^)(voi
if (webAuthenticationVC) {
// dismiss the ASWebAuthenticationSession
[webAuthenticationVC cancel];
OIDRetainSessionBriefly(webAuthenticationVC);
if (completion) completion();
} else if (safariVC) {
// dismiss the SFSafariViewController
Expand Down
Loading