diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 000000000..919434a62
--- /dev/null
+++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/Package.swift b/Package.swift
index ae72258ac..c62ca8a5b 100644
--- a/Package.swift
+++ b/Package.swift
@@ -50,11 +50,12 @@ let package = Package(
name: "AppAuth",
dependencies: ["AppAuthCore"],
path: "Source/AppAuth",
- sources: ["iOS", "macOS"],
+ sources: ["iOS", "macOS", "visionOS"],
publicHeadersPath: "",
cSettings: [
.headerSearchPath("iOS"),
.headerSearchPath("macOS"),
+ .headerSearchPath("visionOS"),
.headerSearchPath("macOS/LoopbackHTTPServer"),
]
),
diff --git a/Source/AppAuth.h b/Source/AppAuth.h
index 19abc55e1..924b21b17 100644
--- a/Source/AppAuth.h
+++ b/Source/AppAuth.h
@@ -56,6 +56,11 @@
#import "OIDAuthorizationService+Mac.h"
#import "OIDExternalUserAgentMac.h"
#import "OIDRedirectHTTPHandler.h"
+#elif TARGET_OS_VISION
+#import "OIDAuthState+Vision.h"
+#import "OIDAuthorizationService+Vision.h"
+#import "OIDExternalUserAgentVision.h"
+#import "OIDExternalUserAgentVisionCustomBrowser.h"
#else
#error "Platform Undefined"
#endif
diff --git a/Source/AppAuth/iOS/OIDAuthState+IOS.h b/Source/AppAuth/iOS/OIDAuthState+IOS.h
index 1a1ee63a0..82f09e77f 100644
--- a/Source/AppAuth/iOS/OIDAuthState+IOS.h
+++ b/Source/AppAuth/iOS/OIDAuthState+IOS.h
@@ -46,7 +46,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (id)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
presentingViewController:(UIViewController *)presentingViewController
- callback:(OIDAuthStateAuthorizationCallback)callback;
+ completion:(OIDAuthStateAuthorizationCallback)callback;
/*! @brief Convenience method to create a @c OIDAuthState by presenting an authorization request
(optionally using an emphemeral browser session that shares no cookies or data with the
@@ -68,12 +68,12 @@ NS_ASSUME_NONNULL_BEGIN
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
presentingViewController:(UIViewController *)presentingViewController
prefersEphemeralSession:(BOOL)prefersEphemeralSession
- callback:(OIDAuthStateAuthorizationCallback)callback
+ completion:(OIDAuthStateAuthorizationCallback)callback
API_AVAILABLE(ios(13));
+ (id)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
- callback:(OIDAuthStateAuthorizationCallback)callback API_AVAILABLE(ios(11)) API_UNAVAILABLE(macCatalyst)
+ completion:(OIDAuthStateAuthorizationCallback)callback API_AVAILABLE(ios(11)) API_UNAVAILABLE(macCatalyst)
__deprecated_msg("This method will not work on iOS 13. Use "
"authStateByPresentingAuthorizationRequest:presentingViewController:callback:");
diff --git a/Source/AppAuth/iOS/OIDAuthState+IOS.m b/Source/AppAuth/iOS/OIDAuthState+IOS.m
index c474a77d1..1f644bfb6 100644
--- a/Source/AppAuth/iOS/OIDAuthState+IOS.m
+++ b/Source/AppAuth/iOS/OIDAuthState+IOS.m
@@ -29,7 +29,7 @@ @implementation OIDAuthState (IOS)
+ (id)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
presentingViewController:(UIViewController *)presentingViewController
- callback:(OIDAuthStateAuthorizationCallback)callback {
+ completion:(OIDAuthStateAuthorizationCallback)callback {
id externalUserAgent;
#if TARGET_OS_MACCATALYST
externalUserAgent = [[OIDExternalUserAgentCatalyst alloc]
@@ -39,14 +39,14 @@ @implementation OIDAuthState (IOS)
#endif // TARGET_OS_MACCATALYST
return [self authStateByPresentingAuthorizationRequest:authorizationRequest
externalUserAgent:externalUserAgent
- callback:callback];
+ completion:callback];
}
+ (id)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
presentingViewController:(UIViewController *)presentingViewController
prefersEphemeralSession:(BOOL)prefersEphemeralSession
- callback:(OIDAuthStateAuthorizationCallback)callback {
+ completion:(OIDAuthStateAuthorizationCallback)callback {
id externalUserAgent;
#if TARGET_OS_MACCATALYST
externalUserAgent = [[OIDExternalUserAgentCatalyst alloc]
@@ -59,17 +59,17 @@ @implementation OIDAuthState (IOS)
#endif // TARGET_OS_MACCATALYST
return [self authStateByPresentingAuthorizationRequest:authorizationRequest
externalUserAgent:externalUserAgent
- callback:callback];
+ completion:callback];
}
#if !TARGET_OS_MACCATALYST
+ (id)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
- callback:(OIDAuthStateAuthorizationCallback)callback {
+ completion:(OIDAuthStateAuthorizationCallback)callback {
OIDExternalUserAgentIOS *externalUserAgent = [[OIDExternalUserAgentIOS alloc] init];
return [self authStateByPresentingAuthorizationRequest:authorizationRequest
externalUserAgent:externalUserAgent
- callback:callback];
+ completion:callback];
}
#endif // !TARGET_OS_MACCATALYST
diff --git a/Source/AppAuth/iOS/OIDExternalUserAgentIOS.m b/Source/AppAuth/iOS/OIDExternalUserAgentIOS.m
index 4a8cda0a3..62d5574c2 100644
--- a/Source/AppAuth/iOS/OIDExternalUserAgentIOS.m
+++ b/Source/AppAuth/iOS/OIDExternalUserAgentIOS.m
@@ -104,26 +104,51 @@ - (BOOL)presentExternalUserAgentRequest:(id)request
if (!UIAccessibilityIsGuidedAccessEnabled()) {
__weak OIDExternalUserAgentIOS *weakSelf = self;
NSString *redirectScheme = request.redirectScheme;
- ASWebAuthenticationSession *authenticationVC =
- [[ASWebAuthenticationSession alloc] initWithURL:requestURL
- callbackURLScheme:redirectScheme
- completionHandler:^(NSURL * _Nullable callbackURL,
- NSError * _Nullable error) {
- __strong OIDExternalUserAgentIOS *strongSelf = weakSelf;
- if (!strongSelf) {
+ ASWebAuthenticationSession *authenticationVC;
+ if (@available(iOS 17.4, *)) {
+ authenticationVC =
+ [[ASWebAuthenticationSession alloc] initWithURL:requestURL
+ callback: [ASWebAuthenticationSessionCallback callbackWithCustomScheme: redirectScheme]
+ completionHandler:^(NSURL * _Nullable callbackURL,
+ NSError * _Nullable error) {
+ __strong OIDExternalUserAgentIOS *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];
- }
- }];
+ }
+ strongSelf->_webAuthenticationVC = nil;
+ if (callbackURL) {
+ [strongSelf->_session resumeExternalUserAgentFlowWithURL:callbackURL];
+ } else {
+ NSError *safariError =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
+ underlyingError:error
+ description:nil];
+ [strongSelf->_session failExternalUserAgentFlowWithError:safariError];
+ }
+ }];
+
+ } else {
+ authenticationVC = [[ASWebAuthenticationSession alloc] initWithURL:requestURL
+ callbackURLScheme:redirectScheme
+ completionHandler:^(NSURL * _Nullable callbackURL,
+ NSError * _Nullable error) {
+ __strong OIDExternalUserAgentIOS *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];
+ }
+ }];
+ }
+
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
authenticationVC.presentationContextProvider = self;
diff --git a/Source/AppAuth/macOS/OIDAuthState+Mac.h b/Source/AppAuth/macOS/OIDAuthState+Mac.h
index 71e56f22a..315aac709 100644
--- a/Source/AppAuth/macOS/OIDAuthState+Mac.h
+++ b/Source/AppAuth/macOS/OIDAuthState+Mac.h
@@ -47,7 +47,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (id)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
presentingWindow:(NSWindow *)presentingWindow
- callback:(OIDAuthStateAuthorizationCallback)callback;
+ completion:(OIDAuthStateAuthorizationCallback)callback;
/*! @brief Convenience method to create a @c OIDAuthState by presenting an authorization request
(optionally using an emphemeral browser session that shares no cookies or data with the
@@ -69,7 +69,7 @@ NS_ASSUME_NONNULL_BEGIN
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
presentingWindow:(NSWindow *)presentingWindow
prefersEphemeralSession:(BOOL)prefersEphemeralSession
- callback:(OIDAuthStateAuthorizationCallback)callback
+ completion:(OIDAuthStateAuthorizationCallback)callback
API_AVAILABLE(macos(10.15));
/*! @param authorizationRequest The authorization request to present.
@@ -81,7 +81,7 @@ NS_ASSUME_NONNULL_BEGIN
*/
+ (id)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
- callback:(OIDAuthStateAuthorizationCallback)callback
+ completion:(OIDAuthStateAuthorizationCallback)callback
__deprecated_msg("For macOS 10.15 and above please use "
"authStateByPresentingAuthorizationRequest:presentingWindow:callback:");
diff --git a/Source/AppAuth/macOS/OIDAuthState+Mac.m b/Source/AppAuth/macOS/OIDAuthState+Mac.m
index f2894daaf..2fb6f39fe 100644
--- a/Source/AppAuth/macOS/OIDAuthState+Mac.m
+++ b/Source/AppAuth/macOS/OIDAuthState+Mac.m
@@ -29,32 +29,32 @@ @implementation OIDAuthState (Mac)
+ (id)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
presentingWindow:(NSWindow *)presentingWindow
- callback:(OIDAuthStateAuthorizationCallback)callback {
+ completion:(OIDAuthStateAuthorizationCallback)callback {
OIDExternalUserAgentMac *externalUserAgent = [[OIDExternalUserAgentMac alloc] initWithPresentingWindow:presentingWindow];
return [self authStateByPresentingAuthorizationRequest:authorizationRequest
externalUserAgent:externalUserAgent
- callback:callback];
+ completion:callback];
}
+ (id)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
presentingWindow:(NSWindow *)presentingWindow
prefersEphemeralSession:(BOOL)prefersEphemeralSession
- callback:(OIDAuthStateAuthorizationCallback)callback {
+ completion:(OIDAuthStateAuthorizationCallback)callback {
OIDExternalUserAgentMac *externalUserAgent =
[[OIDExternalUserAgentMac alloc] initWithPresentingWindow:presentingWindow
prefersEphemeralSession:prefersEphemeralSession];
return [self authStateByPresentingAuthorizationRequest:authorizationRequest
externalUserAgent:externalUserAgent
- callback:callback];
+ completion:callback];
}
+ (id)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
- callback:(OIDAuthStateAuthorizationCallback)callback {
+ completion:(OIDAuthStateAuthorizationCallback)callback {
OIDExternalUserAgentMac *externalUserAgent = [[OIDExternalUserAgentMac alloc] init];
return [self authStateByPresentingAuthorizationRequest:authorizationRequest
externalUserAgent:externalUserAgent
- callback:callback];
+ completion:callback];
}
@end
diff --git a/Source/AppAuth/visionOS/OIDAuthState+Vision.h b/Source/AppAuth/visionOS/OIDAuthState+Vision.h
new file mode 100644
index 000000000..d0e310286
--- /dev/null
+++ b/Source/AppAuth/visionOS/OIDAuthState+Vision.h
@@ -0,0 +1,90 @@
+/*! @file OIDAuthState+Vision.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 Google Inc. All Rights Reserved.
+ @copydetails
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import
+
+#if TARGET_OS_VISION
+
+#import
+
+#import "OIDAuthState.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief visionOS specific convenience methods for @c OIDAuthState.
+ */
+@interface OIDAuthState (Vision)
+
+/*! @brief Convenience method to create a @c OIDAuthState by presenting an authorization request
+ and performing the authorization code exchange in the case of code flow requests. For
+ the hybrid flow, the caller should validate the id_token and c_hash, then perform the token
+ request (@c OIDAuthorizationService.performTokenRequest:callback:)
+ and update the OIDAuthState with the results (@c
+ OIDAuthState.updateWithTokenResponse:error:).
+ @param authorizationRequest The authorization request to present.
+ @param presentingWindow The window to present the authentication flow.
+ @param callback The method called when the request has completed or failed.
+ @return A @c OIDExternalUserAgentSession instance which will terminate when it
+ receives a @c OIDExternalUserAgentSession.cancel message, or after processing a
+ @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message.
+ */
++ (id)
+ authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
+ presentingWindow:(UIWindow *)presentingWindow
+ completion:(OIDAuthStateAuthorizationCallback)callback;
+
+/*! @brief Convenience method to create a @c OIDAuthState by presenting an authorization request
+ (optionally using an emphemeral browser session that shares no cookies or data with the
+ normal browser session) and performing the authorization code exchange in the case of code
+ flow requests. For the hybrid flow, the caller should validate the id_token and c_hash, then
+ perform the token request (@c OIDAuthorizationService.performTokenRequest:callback:)
+ and update the OIDAuthState with the results using
+ @c OIDAuthState.updateWithTokenResponse:error:.
+ @param authorizationRequest The authorization request to present.
+ @param presentingWindow The window to present the @c ASWebAuthenticationSession UI.
+ @param prefersEphemeralSession Whether the caller prefers to use a private authentication
+ session. See @c ASWebAuthenticationSession.prefersEphemeralWebBrowserSession for more.
+ @param callback The method called when the request has completed or failed.
+ @return A @c OIDExternalUserAgentSession instance which will terminate when it
+ receives a @c OIDExternalUserAgentSession.cancel message, or after processing a
+ @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message.
+ */
++ (id)
+ authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
+ presentingWindow:(UIWindow *)presentingWindow
+ prefersEphemeralSession:(BOOL)prefersEphemeralSession
+ completion:(OIDAuthStateAuthorizationCallback)callback;
+
+/*! @param authorizationRequest The authorization request to present.
+ @param callback The method called when the request has completed or failed.
+ @return A @c OIDExternalUserAgentSession instance which will terminate when it
+ receives a @c OIDExternalUserAgentSession.cancel message, or after processing a
+ @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message.
+ @discussion This method uses the default browser to present the authentication flow.
+ */
++ (id)
+ authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
+ completion:(OIDAuthStateAuthorizationCallback)callback
+ __deprecated_msg("For visionOS 1.0 and above please use "
+ "authStateByPresentingAuthorizationRequest:presentingWindow:callback:");
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // TARGET_OS_OSX
diff --git a/Source/AppAuth/visionOS/OIDAuthState+Vision.m b/Source/AppAuth/visionOS/OIDAuthState+Vision.m
new file mode 100644
index 000000000..ec7ecf1cd
--- /dev/null
+++ b/Source/AppAuth/visionOS/OIDAuthState+Vision.m
@@ -0,0 +1,61 @@
+/*! @file OIDAuthState+Vision.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 Google Inc. All Rights Reserved.
+ @copydetails
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import
+
+#if TARGET_OS_VISION
+
+#import "OIDAuthState+Vision.h"
+#import "OIDExternalUserAgentVision.h"
+
+@implementation OIDAuthState (Vision)
+
++ (id)
+ authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
+ presentingWindow:(UIWindow *)presentingWindow
+ completion:(OIDAuthStateAuthorizationCallback)callback {
+ OIDExternalUserAgentVision *externalUserAgent = [[OIDExternalUserAgentVision alloc] initWithPresentingWindow:presentingWindow];
+ return [self authStateByPresentingAuthorizationRequest:authorizationRequest
+ externalUserAgent:externalUserAgent
+ completion:callback];
+}
++ (id)
+ authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
+ presentingWindow:(UIWindow *)presentingWindow
+ prefersEphemeralSession:(BOOL)prefersEphemeralSession
+ completion:(OIDAuthStateAuthorizationCallback)callback {
+ OIDExternalUserAgentVision *externalUserAgent =
+ [[OIDExternalUserAgentVision alloc] initWithPresentingWindow:presentingWindow
+ prefersEphemeralSession:prefersEphemeralSession];
+ return [self authStateByPresentingAuthorizationRequest:authorizationRequest
+ externalUserAgent:externalUserAgent
+ completion:callback];
+}
+
++ (id)
+ authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
+ completion:(OIDAuthStateAuthorizationCallback)callback {
+ OIDExternalUserAgentVision *externalUserAgent = [[OIDExternalUserAgentVision alloc] init];
+ return [self authStateByPresentingAuthorizationRequest:authorizationRequest
+ externalUserAgent:externalUserAgent
+ completion:callback];
+}
+
+@end
+
+#endif // TARGET_OS_OSX
diff --git a/Source/AppAuth/visionOS/OIDAuthorizationService+Vision.h b/Source/AppAuth/visionOS/OIDAuthorizationService+Vision.h
new file mode 100644
index 000000000..4f404f9b1
--- /dev/null
+++ b/Source/AppAuth/visionOS/OIDAuthorizationService+Vision.h
@@ -0,0 +1,78 @@
+/*! @file OIDAuthorizationService+Vision.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 Google Inc. All Rights Reserved.
+ @copydetails
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import
+
+#if TARGET_OS_VISION
+
+#import
+
+#import "OIDAuthorizationService.h"
+#import "OIDExternalUserAgentSession.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Provides visionOS specific authorization request handling.
+ */
+@interface OIDAuthorizationService (Vision)
+
+/*! @brief Perform an authorization flow, presenting an appropriate browser for the user to
+ authenticate.
+ @param request The authorization request.
+ @param presentingWindow The window to present the authentication flow.
+ @param callback The method called when the request has completed or failed.
+ @return A @c OIDExternalUserAgentSession instance which will terminate when it
+ receives a @c OIDExternalUserAgentSession.cancel message, or after processing a
+ @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message.
+ */
++ (id) presentAuthorizationRequest:(OIDAuthorizationRequest *)request
+ presentingWindow:(UIWindow *)presentingWindow
+ callback:(OIDAuthorizationCallback)callback;
+
+/*! @brief Perform an authorization flow using the @c ASWebAuthenticationSession optionally using an
+ emphemeral browser session that shares no cookies or data with the normal browser session.
+ @param request The authorization request.
+ @param presentingWindow The window to present the authentication flow.
+ @param prefersEphemeralSession Whether the caller prefers to use a private authentication
+ session. See @c ASWebAuthenticationSession.prefersEphemeralWebBrowserSession for more.
+ @param callback The method called when the request has completed or failed.
+ @return A @c OIDExternalUserAgentSession instance which will terminate when it
+ receives a @c OIDExternalUserAgentSession.cancel message, or after processing a
+ @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message.
+ */
++ (id) presentAuthorizationRequest:(OIDAuthorizationRequest *)request
+ presentingWindow:(UIWindow *)presentingWindow
+ prefersEphemeralSession:(BOOL)prefersEphemeralSession
+ callback:(OIDAuthorizationCallback)callback;
+
+/*! @brief Perform an authorization flow using the default browser.
+ @param request The authorization request.
+ @param callback The method called when the request has completed or failed.
+ @return A @c OIDExternalUserAgentSession instance which will terminate when it
+ receives a @c OIDExternalUserAgentSession.cancel message, or after processing a
+ @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message.
+ */
++ (id)presentAuthorizationRequest:(OIDAuthorizationRequest *)request
+ callback:(OIDAuthorizationCallback)callback
+ __deprecated_msg("For visionOS 1.15 and above please use presentAuthorizationRequest:presentingWindow:callback:");
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // TARGET_OS_VISION
diff --git a/Source/AppAuth/visionOS/OIDAuthorizationService+Vision.m b/Source/AppAuth/visionOS/OIDAuthorizationService+Vision.m
new file mode 100644
index 000000000..ead07edc6
--- /dev/null
+++ b/Source/AppAuth/visionOS/OIDAuthorizationService+Vision.m
@@ -0,0 +1,58 @@
+/*! @file OIDAuthorizationService+Vision.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 Google Inc. All Rights Reserved.
+ @copydetails
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import
+
+#if TARGET_OS_VISION
+
+#import "OIDAuthorizationService+Vision.h"
+#import "OIDExternalUserAgentVision.h"
+
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation OIDAuthorizationService (Vision)
+
++ (id) presentAuthorizationRequest:(OIDAuthorizationRequest *)request
+ presentingWindow:(UIWindow *)presentingWindow
+ callback:(OIDAuthorizationCallback)callback {
+ OIDExternalUserAgentVision *externalUserAgent = [[OIDExternalUserAgentVision alloc] initWithPresentingWindow:presentingWindow];
+ return [self presentAuthorizationRequest:request externalUserAgent:externalUserAgent callback:callback];
+}
+
++ (id) presentAuthorizationRequest:(OIDAuthorizationRequest *)request
+ presentingWindow:(UIWindow *)presentingWindow
+ prefersEphemeralSession:(BOOL)prefersEphemeralSession
+ callback:(OIDAuthorizationCallback)callback {
+ OIDExternalUserAgentVision *externalUserAgent =
+ [[OIDExternalUserAgentVision alloc] initWithPresentingWindow:presentingWindow
+ prefersEphemeralSession:prefersEphemeralSession];
+ return [self presentAuthorizationRequest:request externalUserAgent:externalUserAgent callback:callback];
+}
+
++ (id) presentAuthorizationRequest:(OIDAuthorizationRequest *)request
+ callback:(OIDAuthorizationCallback)callback {
+ OIDExternalUserAgentVision *externalUserAgent = [[OIDExternalUserAgentVision alloc] init];
+ return [self presentAuthorizationRequest:request externalUserAgent:externalUserAgent callback:callback];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // TARGET_OS_OSX
diff --git a/Source/AppAuth/visionOS/OIDExternalUserAgentVision.h b/Source/AppAuth/visionOS/OIDExternalUserAgentVision.h
new file mode 100644
index 000000000..945edf6db
--- /dev/null
+++ b/Source/AppAuth/visionOS/OIDExternalUserAgentVision.h
@@ -0,0 +1,54 @@
+/*! @file OIDExternalUserAgentVision.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 Google Inc. All Rights Reserved.
+ @copydetails
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import
+
+#if TARGET_OS_VISION
+
+#import
+
+#import "OIDExternalUserAgent.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief An Apple-Vision-specific external user-agent UI Coordinator that uses the default browser to
+ present an external user-agent request.
+ */
+@interface OIDExternalUserAgentVision : NSObject
+
+/*! @brief The designated initializer.
+ @param presentingWindow The window from which to present the @c ASWebAuthenticationSession on
+ macOS 10.15 and above. Older macOS versions use the system browser.
+ */
+- (instancetype)initWithPresentingWindow:(UIWindow *)presentingWindow NS_DESIGNATED_INITIALIZER;
+
+/*! @brief Create an external user-agent which optionally uses a private authentication session.
+ @param presentingWindow The window from which to present the @c ASWebAuthenticationSession.
+ @param prefersEphemeralSession Whether the caller prefers to use a private authentication
+ session. See @c ASWebAuthenticationSession.prefersEphemeralWebBrowserSession for more.
+ */
+- (nullable instancetype)initWithPresentingWindow:(UIWindow *)presentingWindow
+ prefersEphemeralSession:(BOOL)prefersEphemeralSession;
+
+- (instancetype)init __deprecated_msg("Use initWithPresentingWindow for visionOS 1.0 and above.");
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // TARGET_OS_OSX
diff --git a/Source/AppAuth/visionOS/OIDExternalUserAgentVision.m b/Source/AppAuth/visionOS/OIDExternalUserAgentVision.m
new file mode 100644
index 000000000..f43385725
--- /dev/null
+++ b/Source/AppAuth/visionOS/OIDExternalUserAgentVision.m
@@ -0,0 +1,194 @@
+/*! @file OIDExternalUserAgentVision.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 Google Inc. All Rights Reserved.
+ @copydetails
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import
+
+#if TARGET_OS_VISION
+
+#import "OIDExternalUserAgentVision.h"
+
+#import
+
+#import "OIDErrorUtilities.h"
+#import "OIDExternalUserAgentSession.h"
+#import "OIDExternalUserAgentRequest.h"
+
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OIDExternalUserAgentVision ()
+@end
+
+@implementation OIDExternalUserAgentVision {
+ BOOL _externalUserAgentFlowInProgress;
+ __weak id _session;
+ BOOL _prefersEphemeralSession;
+
+ UIWindow *_presentingWindow;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpartial-availability"
+ ASWebAuthenticationSession *_webAuthenticationSession;
+#pragma clang diagnostic pop
+}
+
+- (instancetype)initWithPresentingWindow:(UIWindow *)presentingWindow {
+ self = [super init];
+ if (self) {
+ _presentingWindow = presentingWindow;
+ }
+ return self;
+}
+
+- (nullable instancetype)initWithPresentingWindow:(UIWindow *)presentingWindow
+ prefersEphemeralSession:(BOOL)prefersEphemeralSession {
+ self = [self initWithPresentingWindow:presentingWindow];
+ if (self) {
+ _prefersEphemeralSession = prefersEphemeralSession;
+ }
+ return self;
+}
+
+- (instancetype)init {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnonnull"
+ return [self initWithPresentingWindow:nil];
+#pragma clang diagnostic pop
+}
+
+- (BOOL)presentExternalUserAgentRequest:(id)request
+ session:(id)session {
+ if (_externalUserAgentFlowInProgress) {
+ // TODO: Handle errors as authorization is already in progress.
+ return NO;
+ }
+
+ _externalUserAgentFlowInProgress = YES;
+ _session = session;
+ NSURL *requestURL = [request externalUserAgentRequestURL];
+
+ if (_presentingWindow) {
+ __weak OIDExternalUserAgentVision *weakSelf = self;
+ NSString *redirectScheme = request.redirectScheme;
+ ASWebAuthenticationSession *authenticationSession;
+ if (@available(visionOS 1.1, *)) {
+ authenticationSession = [[ASWebAuthenticationSession alloc] initWithURL:requestURL
+ callback: [ASWebAuthenticationSessionCallback callbackWithCustomScheme: redirectScheme]
+ completionHandler:^(NSURL * _Nullable callbackURL,
+ NSError * _Nullable error) {
+ __strong OIDExternalUserAgentVision *strongSelf = weakSelf;
+ if (!strongSelf) {
+ return;
+ }
+ strongSelf->_webAuthenticationSession = nil;
+ if (callbackURL) {
+ [strongSelf->_session resumeExternalUserAgentFlowWithURL:callbackURL];
+ } else {
+ NSError *safariError =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
+ underlyingError:error
+ description:nil];
+ [strongSelf->_session failExternalUserAgentFlowWithError:safariError];
+ }
+ }];
+
+ } else {
+ authenticationSession = [[ASWebAuthenticationSession alloc] initWithURL:requestURL
+ callbackURLScheme:redirectScheme
+ completionHandler:^(NSURL * _Nullable callbackURL,
+ NSError * _Nullable error) {
+ __strong OIDExternalUserAgentVision *strongSelf = weakSelf;
+ if (!strongSelf) {
+ return;
+ }
+ strongSelf->_webAuthenticationSession = nil;
+ if (callbackURL) {
+ [strongSelf->_session resumeExternalUserAgentFlowWithURL:callbackURL];
+ } else {
+ NSError *safariError =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
+ underlyingError:error
+ description:nil];
+ [strongSelf->_session failExternalUserAgentFlowWithError:safariError];
+ }
+ }];
+ }
+
+ authenticationSession.presentationContextProvider = self;
+
+ _webAuthenticationSession = authenticationSession;
+ _webAuthenticationSession.prefersEphemeralWebBrowserSession = _prefersEphemeralSession;
+ if (authenticationSession.canStart) {
+ return [authenticationSession start];
+ } else {
+ return NO;
+ }
+ }
+
+
+ [[UIApplication sharedApplication] openURL:requestURL options: [NSDictionary new] completionHandler:nil];
+ /*if (!openedBrowser) {
+ [self cleanUp];
+ NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeBrowserOpenError
+ underlyingError:nil
+ description:@"Unable to open the browser."];
+ [session failExternalUserAgentFlowWithError:safariError];
+ }*/
+ return true;
+}
+
+- (void)dismissExternalUserAgentAnimated:(BOOL)animated completion:(void (^)(void))completion {
+ if (!_externalUserAgentFlowInProgress) {
+ // Ignore this call if there is no authorization flow in progress.
+ if (completion) completion();
+ return;
+ }
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpartial-availability"
+ ASWebAuthenticationSession *webAuthenticationSession = _webAuthenticationSession;
+#pragma clang diagnostic pop
+
+ // Ideally the browser tab with the URL should be closed here, but the AppAuth library does not
+ // control the browser.
+ [self cleanUp];
+ if (webAuthenticationSession) {
+ // dismiss the ASWebAuthenticationSession
+ [webAuthenticationSession cancel];
+ if (completion) completion();
+ } else if (completion) {
+ completion();
+ }
+}
+
+- (void)cleanUp {
+ _session = nil;
+ _externalUserAgentFlowInProgress = NO;
+ _webAuthenticationSession = nil;
+}
+
+#pragma mark - ASWebAuthenticationPresentationContextProviding
+
+- (ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:(ASWebAuthenticationSession *)session {
+ return _presentingWindow;
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // TARGET_OS_OSX
diff --git a/Source/AppAuth/visionOS/OIDExternalUserAgentVisionCustomBrowser.h b/Source/AppAuth/visionOS/OIDExternalUserAgentVisionCustomBrowser.h
new file mode 100644
index 000000000..793f78f00
--- /dev/null
+++ b/Source/AppAuth/visionOS/OIDExternalUserAgentVisionCustomBrowser.h
@@ -0,0 +1,113 @@
+/*! @file OIDExternalUserAgentVisionCustomBrowser.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2018 Google LLC
+ @copydetails
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import
+
+#if TARGET_OS_VISION
+
+#import
+
+#import "OIDExternalUserAgent.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief A block that transforms a regular http/https URL into one that will open in an
+ alternative browser.
+ @param requestURL the http/https request URL to be transformed.
+ @return transformed URL.
+ */
+typedef NSURL *_Nullable (^OIDCustomBrowserURLTransformation)(NSURL *_Nullable requestURL);
+
+/*! @brief An implementation of the OIDExternalUserAgent protocol for visionOS that uses
+ a custom browser (i.e. not Safari) for external requests. It is suitable for browsers that
+ offer a custom url scheme that simply replaces the "https" scheme. It is not designed
+ for browsers that require other modifications to the URL. If the browser is not installed
+ the user will be prompted to install it.
+ */
+API_UNAVAILABLE(macCatalyst)
+@interface OIDExternalUserAgentVisionCustomBrowser : NSObject
+
+/*! @brief URL transformation block for the browser.
+ */
+@property(nonatomic, readonly) OIDCustomBrowserURLTransformation URLTransformation;
+
+/*! @brief URL Scheme used to test for whether the browser is installed.
+ */
+@property(nonatomic, readonly, nullable) NSString *canOpenURLScheme;
+
+/*! @brief URL of the browser's App Store listing.
+ */
+@property(nonatomic, readonly, nullable) NSURL *appStoreURL;
+
+/*! @brief An instance of @c OIDExternalUserAgentVisionCustomBrowser for Chrome.
+ */
++ (instancetype)CustomBrowserChrome;
+
+/*! @brief An instance of @c OIDExternalUserAgentVisionCustomBrowser for Firefox.
+ */
++ (instancetype)CustomBrowserFirefox;
+
+/*! @brief An instance of @c OIDExternalUserAgentVisionCustomBrowser for Opera.
+ */
++ (instancetype)CustomBrowserOpera;
+
+/*! @brief An instance of @c OIDExternalUserAgentVisionCustomBrowser for Safari.
+ */
++ (instancetype)CustomBrowserSafari;
+
+/*! @brief Creates a @c OIDCustomBrowserURLTransformation using the scheme substitution method used
+ visionOS browsers like Chrome and Firefox.
+ */
++ (OIDCustomBrowserURLTransformation)
+ URLTransformationSchemeSubstitutionHTTPS:(NSString *)browserSchemeHTTPS
+ HTTP:(nullable NSString *)browserSchemeHTTP;
+
+/*! @brief Creates a @c OIDCustomBrowserURLTransformation with the URL prefix method used by
+ visionOS browsers like Firefox.
+ */
++ (OIDCustomBrowserURLTransformation) URLTransformationSchemeConcatPrefix:(NSString*)URLprefix;
+
+/*! @internal
+ @brief Unavailable. Please use @c initWithURLTransformation:canOpenURLScheme:appStoreURL:
+ */
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/*! @brief OIDExternalUserAgent for a custom browser. @c presentExternalUserAgentRequest:session method
+ will return NO if the browser isn't installed.
+ */
+- (nullable instancetype)initWithURLTransformation:(OIDCustomBrowserURLTransformation)URLTransformation;
+
+/*! @brief The designated initializer.
+ @param URLTransformation the transformation block to translate the URL into one that will open
+ in the desired custom browser.
+ @param canOpenURLScheme any scheme supported by the browser used to check if the browser is
+ installed.
+ @param appStoreURL URL of the browser in the app store. When this and @c canOpenURLScheme
+ are non-nil, @c presentExternalUserAgentRequest:session will redirect the user to the app store
+ if the browser is not installed.
+ */
+- (nullable instancetype)initWithURLTransformation:(OIDCustomBrowserURLTransformation)URLTransformation
+ canOpenURLScheme:(nullable NSString *)canOpenURLScheme
+ appStoreURL:(nullable NSURL *)appStoreURL
+ NS_DESIGNATED_INITIALIZER;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // TARGET_OS_VISION
diff --git a/Source/AppAuth/visionOS/OIDExternalUserAgentVisionCustomBrowser.m b/Source/AppAuth/visionOS/OIDExternalUserAgentVisionCustomBrowser.m
new file mode 100644
index 000000000..4dab4faca
--- /dev/null
+++ b/Source/AppAuth/visionOS/OIDExternalUserAgentVisionCustomBrowser.m
@@ -0,0 +1,172 @@
+/*! @file OIDExternalUserAgentVisionCustomBrowser.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2018 Google LLC
+ @copydetails
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import
+
+#if TARGET_OS_VISION
+
+#import "OIDExternalUserAgentVisionCustomBrowser.h"
+
+#import
+
+#import "OIDAuthorizationRequest.h"
+#import "OIDAuthorizationService.h"
+#import "OIDErrorUtilities.h"
+#import "OIDURLQueryComponent.h"
+
+#if !TARGET_OS_MACCATALYST
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation OIDExternalUserAgentVisionCustomBrowser
+
++ (instancetype)CustomBrowserChrome {
+ // Chrome iOS documentation: https://developer.chrome.com/multidevice/ios/links
+ OIDCustomBrowserURLTransformation transform = [[self class] URLTransformationSchemeSubstitutionHTTPS:@"googlechromes" HTTP:@"googlechrome"];
+ NSURL *appStoreURL =
+ [NSURL URLWithString:@"https://itunes.apple.com/us/app/chrome/id535886823"];
+ return [[[self class] alloc] initWithURLTransformation:transform
+ canOpenURLScheme:@"googlechromes"
+ appStoreURL:appStoreURL];
+}
+
++ (instancetype)CustomBrowserFirefox {
+ // Firefox iOS documentation: https://github.com/mozilla-mobile/firefox-ios-open-in-client
+ OIDCustomBrowserURLTransformation transform =
+ [[self class] URLTransformationSchemeConcatPrefix:@"firefox://open-url?url="];
+ NSURL *appStoreURL =
+ [NSURL URLWithString:@"https://itunes.apple.com/us/app/firefox-web-browser/id989804926"];
+ return [[[self class] alloc] initWithURLTransformation:transform
+ canOpenURLScheme:@"firefox"
+ appStoreURL:appStoreURL];
+}
+
++ (instancetype)CustomBrowserOpera {
+ OIDCustomBrowserURLTransformation transform =
+ [[self class] URLTransformationSchemeSubstitutionHTTPS:@"opera-https" HTTP:@"opera-http"];
+ NSURL *appStoreURL =
+ [NSURL URLWithString:@"https://itunes.apple.com/us/app/opera-mini-web-browser/id363729560"];
+ return [[[self class] alloc] initWithURLTransformation:transform
+ canOpenURLScheme:@"opera-https"
+ appStoreURL:appStoreURL];
+}
+
++ (instancetype)CustomBrowserSafari {
+ OIDCustomBrowserURLTransformation transformNOP = ^NSURL *(NSURL *requestURL) {
+ return requestURL;
+ };
+ OIDExternalUserAgentVisionCustomBrowser *transform =
+ [[[self class] alloc] initWithURLTransformation:transformNOP];
+ return transform;
+}
+
++ (OIDCustomBrowserURLTransformation)
+ URLTransformationSchemeSubstitutionHTTPS:(NSString *)browserSchemeHTTPS
+ HTTP:(nullable NSString *)browserSchemeHTTP {
+ OIDCustomBrowserURLTransformation transform = ^NSURL *(NSURL *requestURL) {
+ // Replace the URL Scheme with the Chrome equivalent.
+ NSString *newScheme = nil;
+ if ([requestURL.scheme isEqualToString:@"https"]) {
+ newScheme = browserSchemeHTTPS;
+ } else if ([requestURL.scheme isEqualToString:@"http"]) {
+ if (!browserSchemeHTTP) {
+ NSAssert(false, @"No HTTP scheme registered for browser");
+ return nil;
+ }
+ newScheme = browserSchemeHTTP;
+ }
+
+ // Replaces the URI scheme with the custom scheme
+ NSURLComponents *components = [NSURLComponents componentsWithURL:requestURL
+ resolvingAgainstBaseURL:YES];
+ components.scheme = newScheme;
+ return components.URL;
+ };
+ return transform;
+}
+
++ (OIDCustomBrowserURLTransformation)URLTransformationSchemeConcatPrefix:(NSString *)URLprefix {
+ OIDCustomBrowserURLTransformation transform = ^NSURL *(NSURL *requestURL) {
+ NSString *requestURLString = [requestURL absoluteString];
+ NSMutableCharacterSet *allowedParamCharacters =
+ [OIDURLQueryComponent URLParamValueAllowedCharacters];
+ NSString *encodedUrl = [requestURLString stringByAddingPercentEncodingWithAllowedCharacters:allowedParamCharacters];
+ NSString *newURL = [NSString stringWithFormat:@"%@%@", URLprefix, encodedUrl];
+ return [NSURL URLWithString:newURL];
+ };
+ return transform;
+}
+
+- (nullable instancetype)initWithURLTransformation:
+ (OIDCustomBrowserURLTransformation)URLTransformation {
+ return [self initWithURLTransformation:URLTransformation canOpenURLScheme:nil appStoreURL:nil];
+}
+
+- (nullable instancetype)
+ initWithURLTransformation:(OIDCustomBrowserURLTransformation)URLTransformation
+ canOpenURLScheme:(nullable NSString *)canOpenURLScheme
+ appStoreURL:(nullable NSURL *)appStoreURL {
+ self = [super init];
+ if (self) {
+ _URLTransformation = URLTransformation;
+ _canOpenURLScheme = canOpenURLScheme;
+ _appStoreURL = appStoreURL;
+ }
+ return self;
+}
+
+- (BOOL)presentExternalUserAgentRequest:(nonnull id)request
+ session:(nonnull id)session {
+ // If the app store URL is set, checks if the app is installed and if not opens the app store.
+ if (_appStoreURL && _canOpenURLScheme) {
+ // Verifies existence of LSApplicationQueriesSchemes Info.plist key.
+ NSArray __unused* canOpenURLs =
+ [[NSBundle mainBundle] objectForInfoDictionaryKey:@"LSApplicationQueriesSchemes"];
+ NSAssert(canOpenURLs, @"plist missing LSApplicationQueriesSchemes key");
+ NSAssert1([canOpenURLs containsObject:_canOpenURLScheme],
+ @"plist missing LSApplicationQueriesSchemes entry for '%@'", _canOpenURLScheme);
+
+ // Opens AppStore if app isn't installed
+ NSString *testURLString = [NSString stringWithFormat:@"%@://example.com", _canOpenURLScheme];
+ NSURL *testURL = [NSURL URLWithString:testURLString];
+ if (![[UIApplication sharedApplication] canOpenURL:testURL]) {
+ [[UIApplication sharedApplication] openURL:_appStoreURL options:[NSDictionary new] completionHandler:nil];
+ return NO;
+ }
+ }
+
+ // Transforms the request URL and opens it.
+ NSURL *requestURL = [request externalUserAgentRequestURL];
+ requestURL = _URLTransformation(requestURL);
+ [[UIApplication sharedApplication] openURL:requestURL options:[NSDictionary new] completionHandler:nil];
+
+ return YES;
+}
+
+- (void)dismissExternalUserAgentAnimated:(BOOL)animated
+ completion:(nonnull void (^)(void))completion {
+ completion();
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // !TARGET_OS_MACCATALYST
+
+#endif // TARGET_OS_Vision
diff --git a/Source/AppAuthCore/OIDAuthState.h b/Source/AppAuthCore/OIDAuthState.h
index 46c78a831..837babebb 100644
--- a/Source/AppAuthCore/OIDAuthState.h
+++ b/Source/AppAuthCore/OIDAuthState.h
@@ -138,7 +138,7 @@ static NSString *const kRefreshTokenRequestException =
+ (id)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
externalUserAgent:(id)externalUserAgent
- callback:(OIDAuthStateAuthorizationCallback)callback;
+ completion:(OIDAuthStateAuthorizationCallback)callback;
/*! @internal
@brief Unavailable. Please use @c initWithAuthorizationResponse:.
diff --git a/Source/AppAuthCore/OIDAuthState.m b/Source/AppAuthCore/OIDAuthState.m
index cb5a22a1e..02d869e0e 100644
--- a/Source/AppAuthCore/OIDAuthState.m
+++ b/Source/AppAuthCore/OIDAuthState.m
@@ -122,7 +122,7 @@ @implementation OIDAuthState {
+ (id)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
externalUserAgent:(id)externalUserAgent
- callback:(OIDAuthStateAuthorizationCallback)callback {
+ completion:(OIDAuthStateAuthorizationCallback)callback {
// presents the authorization request
id authFlowSession = [OIDAuthorizationService
presentAuthorizationRequest:authorizationRequest
diff --git a/Source/Framework/AppAuth.h b/Source/Framework/AppAuth.h
index f1916de77..4d9eaaf3f 100644
--- a/Source/Framework/AppAuth.h
+++ b/Source/Framework/AppAuth.h
@@ -64,6 +64,11 @@ FOUNDATION_EXPORT const unsigned char AppAuthVersionString[];
#import
#import
#import
+#elif TARGET_OS_VISION
+#import
+#import
+#import
+#import
#else
#error "Platform Undefined"
#endif