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
88 changes: 70 additions & 18 deletions flutter_appauth/ios/Classes/OIDExternalUserAgentIOSNoSSO.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#import <SafariServices/SafariServices.h>
#import <AuthenticationServices/AuthenticationServices.h>
#import <AppAuth/OIDAuthorizationRequest.h>
#import <AppAuth/OIDEndSessionRequest.h>


#if !TARGET_OS_MACCATALYST
Expand Down Expand Up @@ -74,26 +76,76 @@ - (BOOL)presentExternalUserAgentRequest:(id<OIDExternalUserAgentRequest>)request
if (!UIAccessibilityIsGuidedAccessEnabled()) {
__weak OIDExternalUserAgentIOSNoSSO *weakSelf = self;
NSString *redirectScheme = request.redirectScheme;
ASWebAuthenticationSession *authenticationVC =
[[ASWebAuthenticationSession alloc] initWithURL:requestURL
callbackURLScheme:redirectScheme
completionHandler:^(NSURL * _Nullable callbackURL,
NSError * _Nullable error) {
__strong OIDExternalUserAgentIOSNoSSO *strongSelf = weakSelf;
if (!strongSelf) {
return;
}
strongSelf->_webAuthenticationVC = nil;
if (callbackURL) {
[strongSelf->_session resumeExternalUserAgentFlowWithURL:callbackURL];

// Shared completion handler for both HTTPS and custom scheme code paths
void (^completionHandler)(NSURL * _Nullable, NSError * _Nullable) =
^(NSURL * _Nullable callbackURL, NSError * _Nullable error) {
__strong OIDExternalUserAgentIOSNoSSO *strongSelf = weakSelf;
if (!strongSelf) {
return;
}
strongSelf->_webAuthenticationVC = nil;
if (callbackURL) {
[strongSelf->_session resumeExternalUserAgentFlowWithURL:callbackURL];
} else {
NSError *safariError =
[OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
underlyingError:error
description:nil];
[strongSelf->_session failExternalUserAgentFlowWithError:safariError];
}
};

ASWebAuthenticationSession *authenticationVC;

// iOS 17.4+: Use claimed HTTPS URI callback when redirect scheme is "https".
// This uses ASWebAuthenticationSession.Callback.https(host:path:) which
// properly matches the full callback URL instead of just the scheme.
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 170400
if (@available(iOS 17.4, *)) {
if ([redirectScheme isEqualToString:@"https"]) {
// Extract the full redirect URL from the underlying request object.
// Cast based on concrete class since the protocol doesn't inherit from NSObject.
NSURL *redirectURL = nil;
if ([(NSObject *)request isKindOfClass:[OIDAuthorizationRequest class]]) {
redirectURL = [(OIDAuthorizationRequest *)request redirectURL];
} else if ([(NSObject *)request isKindOfClass:[OIDEndSessionRequest class]]) {
redirectURL = [(OIDEndSessionRequest *)request postLogoutRedirectURL];
}

if (redirectURL) {
ASWebAuthenticationSessionCallback *callback =
[ASWebAuthenticationSessionCallback
callbackWithHTTPSHost:redirectURL.host
path:redirectURL.path];
authenticationVC =
[[ASWebAuthenticationSession alloc] initWithURL:requestURL
callback:callback
completionHandler:completionHandler];
} else {
// Fallback if we couldn't extract the redirect URL
authenticationVC =
[[ASWebAuthenticationSession alloc] initWithURL:requestURL
callbackURLScheme:redirectScheme
completionHandler:completionHandler];
}
} else {
NSError *safariError =
[OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
underlyingError:error
description:nil];
[strongSelf->_session failExternalUserAgentFlowWithError:safariError];
// Non-HTTPS scheme (custom URL scheme)
authenticationVC =
[[ASWebAuthenticationSession alloc] initWithURL:requestURL
callbackURLScheme:redirectScheme
completionHandler:completionHandler];
}
}];
} else
#endif
{
// iOS < 17.4, or older SDKs that don't expose iOS 17.4 callback APIs.
authenticationVC =
[[ASWebAuthenticationSession alloc] initWithURL:requestURL
callbackURLScheme:redirectScheme
completionHandler:completionHandler];
}

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
authenticationVC.presentationContextProvider = self;
Expand Down
2 changes: 1 addition & 1 deletion flutter_appauth/ios/flutter_appauth.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ A new flutter plugin project.
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.dependency 'AppAuth', '1.7.4'
s.dependency 'AppAuth', '1.7.5'
s.ios.deployment_target = '9.0'
s.resource_bundles = {'flutter_appauth_privacy' => ['Resources/PrivacyInfo.xcprivacy']}
end
Expand Down