diff --git a/src/ui/osx/AppAuth-actual/LICENSE b/src/ui/osx/AppAuth-actual/LICENSE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/src/ui/osx/AppAuth-actual/README.md b/src/ui/osx/AppAuth-actual/README.md
new file mode 100644
index 0000000000..5f54c2c399
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/README.md
@@ -0,0 +1,574 @@
+![AppAuth for iOS and macOS](https://rawgit.com/openid/AppAuth-iOS/master/appauth_lockup.svg)
+[![Build Status](https://travis-ci.org/openid/AppAuth-iOS.svg?branch=master)](https://travis-ci.org/openid/AppAuth-iOS)
+[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
+
+AppAuth for iOS and macOS is a client SDK for communicating with
+[OAuth 2.0](https://tools.ietf.org/html/rfc6749) and
+[OpenID Connect](http://openid.net/specs/openid-connect-core-1_0.html) providers.
+It strives to
+directly map the requests and responses of those specifications, while following
+the idiomatic style of the implementation language. In addition to mapping the
+raw protocol flows, convenience methods are available to assist with common
+tasks like performing an action with fresh tokens.
+
+It follows the best practices set out in
+[RFC 8252 - OAuth 2.0 for Native Apps](https://tools.ietf.org/html/rfc8252)
+including using `SFAuthenticationSession` and `SFSafariViewController` on iOS
+for the auth request. `UIWebView` and `WKWebView` are explicitly *not*
+supported due to the security and usability reasons explained in
+[Section 8.12 of RFC 8252](https://tools.ietf.org/html/rfc8252#section-8.12).
+
+It also supports the [PKCE](https://tools.ietf.org/html/rfc7636) extension to
+OAuth, which was created to secure authorization codes in public clients when
+custom URI scheme redirects are used. The library is friendly to other
+extensions (standard or otherwise), with the ability to handle additional params
+in all protocol requests and responses.
+
+## Specification
+
+### iOS
+
+#### Supported Versions
+
+AppAuth supports iOS 7 and above.
+
+iOS 9+ uses the in-app browser tab pattern
+(via `SFSafariViewController`), and falls back to the system browser (mobile
+Safari) on earlier versions.
+
+#### Authorization Server Requirements
+
+Both Custom URI Schemes (all supported versions of iOS) and Universal Links
+(iOS 9+) can be used with the library.
+
+In general, AppAuth can work with any authorization server that supports
+native apps, as documented in [RFC 8252](https://tools.ietf.org/html/rfc8252),
+either through custom URI scheme redirects, or universal links.
+Authorization servers that assume all clients are web-based, or require clients to maintain
+confidentiality of the client secrets may not work well.
+
+### macOS
+
+#### Supported Versions
+
+AppAuth supports macOS (OS X) 10.9 and above.
+
+#### Authorization Server Requirements
+
+AppAuth for macOS supports both custom schemes; a loopback HTTP redirects
+via a small embedded server.
+
+In general, AppAuth can work with any authorization server that supports
+native apps, as documented in [RFC 8252](https://tools.ietf.org/html/rfc8252);
+either through custom URI schemes, or loopback HTTP redirects.
+Authorization servers that assume all clients are web-based, or require clients to maintain
+confidentiality of the client secrets may not work well.
+
+## Try
+
+Want to try out AppAuth? Just run:
+
+ pod try AppAuth
+
+Follow the instructions in [Examples/README.md](Examples/README.md) to configure
+with your own OAuth client (you need to update three configuration points with your
+client info to try the demo).
+
+## Setup
+
+AppAuth supports four options for dependency management.
+
+### Swift Package Manager
+
+With [Swift Package Manager](https://swift.org/package-manager),
+add the following `dependency` to your `Package.swift`:
+
+```swift
+dependencies: [
+ .package(url: "https://github.com/openid/AppAuth-iOS.git", .upToNextMajor(from: "1.3.0"))
+]
+```
+
+### CocoaPods
+
+With [CocoaPods](https://guides.cocoapods.org/using/getting-started.html),
+add the following line to your `Podfile`:
+
+ pod 'AppAuth'
+
+Then, run `pod install`.
+
+### Carthage
+
+With [Carthage](https://github.com/Carthage/Carthage), add the following
+line to your `Cartfile`:
+
+ github "openid/AppAuth-iOS" "master"
+
+Then, run `carthage bootstrap`.
+
+### Static Library
+
+You can also use AppAuth as a static library. This requires linking the library
+and your project, and including the headers. Here is a suggested configuration:
+
+1. Create an Xcode Workspace.
+2. Add `AppAuth.xcodeproj` to your Workspace.
+3. Include libAppAuth as a linked library for your target (in the "General ->
+Linked Framework and Libraries" section of your target).
+4. Add `AppAuth-iOS/Source` to your search paths of your target ("Build Settings ->
+"Header Search Paths").
+
+## Auth Flow
+
+AppAuth supports both manual interaction with the authorization server
+where you need to perform your own token exchanges, as well as convenience
+methods that perform some of this logic for you. This example uses the
+convenience method, which returns either an `OIDAuthState` object, or an error.
+
+`OIDAuthState` is a class that keeps track of the authorization and token
+requests and responses, and provides a convenience method to call an API with
+fresh tokens. This is the only object that you need to serialize to retain the
+authorization state of the session.
+
+### Configuration
+
+You can configure AppAuth by specifying the endpoints directly:
+
+Objective-C
+```objc
+NSURL *authorizationEndpoint =
+ [NSURL URLWithString:@"https://accounts.google.com/o/oauth2/v2/auth"];
+NSURL *tokenEndpoint =
+ [NSURL URLWithString:@"https://www.googleapis.com/oauth2/v4/token"];
+
+OIDServiceConfiguration *configuration =
+ [[OIDServiceConfiguration alloc]
+ initWithAuthorizationEndpoint:authorizationEndpoint
+ tokenEndpoint:tokenEndpoint];
+
+// perform the auth request...
+```
+
+Swift
+```swift
+let authorizationEndpoint = URL(string: "https://accounts.google.com/o/oauth2/v2/auth")!
+let tokenEndpoint = URL(string: "https://www.googleapis.com/oauth2/v4/token")!
+let configuration = OIDServiceConfiguration(authorizationEndpoint: authorizationEndpoint,
+ tokenEndpoint: tokenEndpoint)
+
+// perform the auth request...
+```
+
+Or through discovery:
+
+Objective-C
+```objc
+NSURL *issuer = [NSURL URLWithString:@"https://accounts.google.com"];
+
+[OIDAuthorizationService discoverServiceConfigurationForIssuer:issuer
+ completion:^(OIDServiceConfiguration *_Nullable configuration,
+ NSError *_Nullable error) {
+
+ if (!configuration) {
+ NSLog(@"Error retrieving discovery document: %@",
+ [error localizedDescription]);
+ return;
+ }
+
+ // perform the auth request...
+}];
+```
+
+Swift
+```swift
+let issuer = URL(string: "https://accounts.google.com")!
+
+// discovers endpoints
+OIDAuthorizationService.discoverConfiguration(forIssuer: issuer) { configuration, error in
+ guard let config = configuration else {
+ print("Error retrieving discovery document: \(error?.localizedDescription ?? "Unknown error")")
+ return
+ }
+
+ // perform the auth request...
+}
+```
+
+### Authorizing – iOS
+
+First, you need to have a property in your `UIApplicationDelegate`
+implementation to hold the session, in order to continue the authorization flow
+from the redirect. In this example, the implementation of this delegate is
+a class named `AppDelegate`, if your app's application delegate has a different
+name, please update the class name in samples below accordingly.
+
+Objective-C
+```objc
+@interface AppDelegate : UIResponder
+// property of the app's AppDelegate
+@property(nonatomic, strong, nullable) id currentAuthorizationFlow;
+@end
+```
+
+Swift
+```swift
+class AppDelegate: UIResponder, UIApplicationDelegate {
+ // property of the app's AppDelegate
+ var currentAuthorizationFlow: OIDExternalUserAgentSession?
+}
+```
+
+
+And your main class, a property to store the auth state:
+
+Objective-C
+```objc
+// property of the containing class
+@property(nonatomic, strong, nullable) OIDAuthState *authState;
+```
+Swift
+```swift
+// property of the containing class
+private var authState: OIDAuthState?
+```
+
+
+Then, initiate the authorization request. By using the
+`authStateByPresentingAuthorizationRequest` convenience method, the token
+exchange will be performed automatically, and everything will be protected with
+PKCE (if the server supports it). AppAuth also lets you perform these
+requests manually. See the `authNoCodeExchange` method in the included Example
+app for a demonstration:
+
+Objective-C
+```objc
+// builds authentication request
+OIDAuthorizationRequest *request =
+ [[OIDAuthorizationRequest alloc] initWithConfiguration:configuration
+ clientId:kClientID
+ scopes:@[OIDScopeOpenID,
+ OIDScopeProfile]
+ redirectURL:kRedirectURI
+ responseType:OIDResponseTypeCode
+ additionalParameters:nil];
+
+// performs authentication request
+AppDelegate *appDelegate =
+ (AppDelegate *)[UIApplication sharedApplication].delegate;
+appDelegate.currentAuthorizationFlow =
+ [OIDAuthState authStateByPresentingAuthorizationRequest:request
+ presentingViewController:self
+ callback:^(OIDAuthState *_Nullable authState,
+ NSError *_Nullable error) {
+ if (authState) {
+ NSLog(@"Got authorization tokens. Access token: %@",
+ authState.lastTokenResponse.accessToken);
+ [self setAuthState:authState];
+ } else {
+ NSLog(@"Authorization error: %@", [error localizedDescription]);
+ [self setAuthState:nil];
+ }
+}];
+```
+
+Swift
+```swift
+// builds authentication request
+let request = OIDAuthorizationRequest(configuration: configuration,
+ clientId: clientID,
+ clientSecret: clientSecret,
+ scopes: [OIDScopeOpenID, OIDScopeProfile],
+ redirectURL: redirectURI,
+ responseType: OIDResponseTypeCode,
+ additionalParameters: nil)
+
+// performs authentication request
+print("Initiating authorization request with scope: \(request.scope ?? "nil")")
+
+let appDelegate = UIApplication.shared.delegate as! AppDelegate
+
+appDelegate.currentAuthorizationFlow =
+ OIDAuthState.authState(byPresenting: request, presenting: self) { authState, error in
+ if let authState = authState {
+ self.setAuthState(authState)
+ print("Got authorization tokens. Access token: " +
+ "\(authState.lastTokenResponse?.accessToken ?? "nil")")
+ } else {
+ print("Authorization error: \(error?.localizedDescription ?? "Unknown error")")
+ self.setAuthState(nil)
+ }
+}
+```
+
+*Handling the Redirect*
+
+The authorization response URL is returned to the app via the iOS openURL
+app delegate method, so you need to pipe this through to the current
+authorization session (created in the previous session):
+
+Objective-C
+```objc
+- (BOOL)application:(UIApplication *)app
+ openURL:(NSURL *)url
+ options:(NSDictionary *)options {
+ // Sends the URL to the current authorization flow (if any) which will
+ // process it if it relates to an authorization response.
+ if ([_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) {
+ _currentAuthorizationFlow = nil;
+ return YES;
+ }
+
+ // Your additional URL handling (if any) goes here.
+
+ return NO;
+}
+```
+
+Swift
+```swift
+func application(_ app: UIApplication,
+ open url: URL,
+ options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
+ // Sends the URL to the current authorization flow (if any) which will
+ // process it if it relates to an authorization response.
+ if let authorizationFlow = self.currentAuthorizationFlow,
+ authorizationFlow.resumeExternalUserAgentFlow(with: url) {
+ self.currentAuthorizationFlow = nil
+ return true
+ }
+
+ // Your additional URL handling (if any)
+
+ return false
+}
+```
+
+### Authorizing – MacOS
+
+On macOS, the most popular way to get the authorization response redirect is to
+start a local HTTP server on the loopback interface (limited to incoming
+requests from the user's machine only). When the authorization is complete, the
+user is redirected to that local server, and the authorization response can be
+processed by the app. AppAuth takes care of managing the local HTTP server
+lifecycle for you.
+
+> #### :bulb: Alternative: Custom URI Schemes
+> Custom URI schemes are also supported on macOS, but some browsers display
+> an interstitial, which reduces the usability. For an example on using custom
+> URI schemes with macOS, See `Example-Mac`.
+
+To receive the authorization response using a local HTTP server, first you need
+to have an instance variable in your main class to retain the HTTP redirect
+handler:
+
+Objective-C
+```objc
+OIDRedirectHTTPHandler *_redirectHTTPHandler;
+```
+
+Then, as the port used by the local HTTP server varies, you need to start it
+before building the authorization request, in order to get the exact redirect
+URI to use:
+
+Objective-C
+```objc
+static NSString *const kSuccessURLString =
+ @"http://openid.github.io/AppAuth-iOS/redirect/";
+NSURL *successURL = [NSURL URLWithString:kSuccessURLString];
+
+// Starts a loopback HTTP redirect listener to receive the code. This needs to be started first,
+// as the exact redirect URI (including port) must be passed in the authorization request.
+_redirectHTTPHandler = [[OIDRedirectHTTPHandler alloc] initWithSuccessURL:successURL];
+NSURL *redirectURI = [_redirectHTTPHandler startHTTPListener:nil];
+```
+
+Then, initiate the authorization request. By using the
+`authStateByPresentingAuthorizationRequest` convenience method, the token
+exchange will be performed automatically, and everything will be protected with
+PKCE (if the server supports it). By assigning the return value to the
+`OIDRedirectHTTPHandler`'s `currentAuthorizationFlow`, the authorization will
+continue automatically once the user makes their choice:
+
+```objc
+// builds authentication request
+OIDAuthorizationRequest *request =
+ [[OIDAuthorizationRequest alloc] initWithConfiguration:configuration
+ clientId:kClientID
+ clientSecret:kClientSecret
+ scopes:@[ OIDScopeOpenID ]
+ redirectURL:redirectURI
+ responseType:OIDResponseTypeCode
+ additionalParameters:nil];
+// performs authentication request
+__weak __typeof(self) weakSelf = self;
+_redirectHTTPHandler.currentAuthorizationFlow =
+ [OIDAuthState authStateByPresentingAuthorizationRequest:request
+ callback:^(OIDAuthState *_Nullable authState,
+ NSError *_Nullable error) {
+ // Brings this app to the foreground.
+ [[NSRunningApplication currentApplication]
+ activateWithOptions:(NSApplicationActivateAllWindows |
+ NSApplicationActivateIgnoringOtherApps)];
+
+ // Processes the authorization response.
+ if (authState) {
+ NSLog(@"Got authorization tokens. Access token: %@",
+ authState.lastTokenResponse.accessToken);
+ } else {
+ NSLog(@"Authorization error: %@", error.localizedDescription);
+ }
+ [weakSelf setAuthState:authState];
+}];
+```
+
+### Making API Calls
+
+AppAuth gives you the raw token information, if you need it. However, we
+recommend that users of the `OIDAuthState` convenience wrapper use the provided
+`performActionWithFreshTokens:` method to perform their API calls to avoid
+needing to worry about token freshness:
+
+Objective-C
+```objc
+[_authState performActionWithFreshTokens:^(NSString *_Nonnull accessToken,
+ NSString *_Nonnull idToken,
+ NSError *_Nullable error) {
+ if (error) {
+ NSLog(@"Error fetching fresh tokens: %@", [error localizedDescription]);
+ return;
+ }
+
+ // perform your API request using the tokens
+}];
+```
+
+Swift
+```swift
+let userinfoEndpoint = URL(string:"https://openidconnect.googleapis.com/v1/userinfo")!
+self.authState?.performAction() { (accessToken, idToken, error) in
+
+ if error != nil {
+ print("Error fetching fresh tokens: \(error?.localizedDescription ?? "Unknown error")")
+ return
+ }
+ guard let accessToken = accessToken else {
+ return
+ }
+
+ // Add Bearer token to request
+ var urlRequest = URLRequest(url: userinfoEndpoint)
+ urlRequest.allHTTPHeaderFields = ["Authorization": "Bearer \(accessToken)"]
+
+ // Perform request...
+}
+```
+
+### Custom User-Agents
+
+Each OAuth flow involves presenting an external user-agent to the user, that
+allows them to interact with the OAuth authorization server. Typical examples
+of a user-agent are the user's browser, or an in-app browser tab incarnation
+like `ASWebAuthenticationSession` on iOS.
+
+AppAuth ships with several implementations of an external user-agent out of the
+box, including defaults for iOS and macOS suitable for most cases. The default
+user-agents typically share persistent cookies with the system default browser,
+to improve the chance that the user doesn't need to sign-in all over again.
+
+It is possible to change the user-agent that AppAuth uses, and even write your
+own - all without needing to fork the library.
+
+All implementations of the external user-agent, be they included or created by
+you need to conform to the
+[`OIDExternalUserAgent`](http://openid.github.io/AppAuth-iOS/docs/latest/protocol_o_i_d_external_user_agent-p.html)
+protocol.
+
+Instances of the `OIDExternalUserAgent`are passed into
+[`OIDAuthState.authStateByPresentingAuthorizationRequest:externalUserAgent:callback`](http://openid.github.io/AppAuth-iOS/docs/latest/interface_o_i_d_auth_state.html#ac762fe2bf95c116f0b437419be211fa1)
+and/or
+[`OIDAuthorizationService.presentAuthorizationRequest:externalUserAgent:callback:`](http://openid.github.io/AppAuth-iOS/docs/latest/interface_o_i_d_authorization_service.html#ae551f8e6887366a46e49b09b37389b8f)
+rather than using the platform-specific convenience methods (which use the
+default user-agents for their respective platforms), like
+[`OIDAuthState.authStateByPresentingAuthorizationRequest:presentingViewController:callback:`](http://openid.github.io/AppAuth-iOS/docs/latest/category_o_i_d_auth_state_07_i_o_s_08.html#ae32fd0732cd3192cd5219f2655a4c85c).
+
+Popular use-cases for writing your own user-agent implementation include needing
+to style the user-agent in ways not supported by AppAuth, and implementing a
+fully custom flow with your own business logic. You can take one of the existing
+implementations as a starting point to copy, rename, and customize to your
+needs.
+
+#### Custom Browser User-Agent
+
+AppAuth for iOS includes a few extra user-agent implementations which you can
+try, or use as a reference for your own implementation. One of them,
+[`OIDExternalUserAgentIOSCustomBrowser`](http://openid.github.io/AppAuth-iOS/docs/latest/interface_o_i_d_external_user_agent_i_o_s_custom_browser.html)
+enables you to use a different browser for authentication, like Chrome for iOS
+or Firefox for iOS.
+
+Here's how to configure AppAuth to use a custom browser using the
+`OIDExternalUserAgentIOSCustomBrowser` user agent:
+
+First, add the following array to your
+[Info.plist](https://github.com/openid/AppAuth-iOS/blob/135f99d2cb4e9d18d310ac2588b905e612461561/Examples/Example-iOS_ObjC/Source/Info.plist#L34)
+(in XCode, right click -> Open As -> Source Code)
+
+```
+ LSApplicationQueriesSchemes
+
+ googlechromes
+ opera-https
+ firefox
+
+```
+
+This is required so that AppAuth can test for the browser and open the app store
+if it's not installed (the default behavior of this user-agent). You only need
+to include the URL scheme of the actual browser you intend to use.
+
+Objective-C
+```objc
+// performs authentication request
+AppDelegate *appDelegate =
+ (AppDelegate *)[UIApplication sharedApplication].delegate;
+id userAgent =
+ [OIDExternalUserAgentIOSCustomBrowser CustomBrowserChrome];
+appDelegate.currentAuthorizationFlow =
+ [OIDAuthState authStateByPresentingAuthorizationRequest:request
+ externalUserAgent:self
+ callback:^(OIDAuthState *_Nullable authState,
+ NSError *_Nullable error) {
+ if (authState) {
+ NSLog(@"Got authorization tokens. Access token: %@",
+ authState.lastTokenResponse.accessToken);
+ [self setAuthState:authState];
+ } else {
+ NSLog(@"Authorization error: %@", [error localizedDescription]);
+ [self setAuthState:nil];
+ }
+}];
+```
+
+That's it! With those two changes (which you can try on the included sample),
+AppAuth will use Chrome iOS for the authorization request (and open Chrome in
+the App Store if it's not installed).
+
+⚠️**Note: the `OIDExternalUserAgentIOSCustomBrowser` user-agent is not intended for consumer apps**. It is designed for
+advanced enterprise use-cases where the app developers have greater control over
+the operating environment and have special requirements that require a custom
+browser like Chrome.
+
+You don't need to stop with the included external user agents either! Since the
+[`OIDExternalUserAgent`](http://openid.github.io/AppAuth-iOS/docs/latest/protocol_o_i_d_external_user_agent-p.html)
+protocol is part of AppAuth's public API, you can implement your own versions of
+it. In the above example,
+`userAgent = [OIDExternalUserAgentIOSCustomBrowser CustomBrowserChrome]` would
+be replaced with an instantiation of your user-agent implementation.
+
+## API Documentation
+
+Browse the [API documentation](http://openid.github.io/AppAuth-iOS/docs/latest/annotated.html).
+
+## Included Samples
+
+Sample apps that explore core AppAuth features are available for iOS and macOS; follow the instructions in [Examples/README.md](Examples/README.md) to get started.
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuth.h b/src/ui/osx/AppAuth-actual/Source/AppAuth.h
new file mode 100644
index 0000000000..4f779df38e
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuth.h
@@ -0,0 +1,92 @@
+/*! @file AppAuth.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDAuthState.h"
+#import "OIDAuthStateChangeDelegate.h"
+#import "OIDAuthStateErrorDelegate.h"
+#import "OIDAuthorizationRequest.h"
+#import "OIDAuthorizationResponse.h"
+#import "OIDAuthorizationService.h"
+#import "OIDError.h"
+#import "OIDErrorUtilities.h"
+#import "OIDExternalUserAgent.h"
+#import "OIDExternalUserAgentRequest.h"
+#import "OIDExternalUserAgentSession.h"
+#import "OIDGrantTypes.h"
+#import "OIDIDToken.h"
+#import "OIDRegistrationRequest.h"
+#import "OIDRegistrationResponse.h"
+#import "OIDResponseTypes.h"
+#import "OIDScopes.h"
+#import "OIDScopeUtilities.h"
+#import "OIDServiceConfiguration.h"
+#import "OIDServiceDiscovery.h"
+#import "OIDTokenRequest.h"
+#import "OIDTokenResponse.h"
+#import "OIDTokenUtilities.h"
+#import "OIDURLSessionProvider.h"
+#import "OIDEndSessionRequest.h"
+#import "OIDEndSessionResponse.h"
+
+#if TARGET_OS_TV
+#elif TARGET_OS_WATCH
+#elif TARGET_OS_IOS || TARGET_OS_MACCATALYST
+#import "OIDAuthState+IOS.h"
+#import "OIDAuthorizationService+IOS.h"
+#import "OIDExternalUserAgentIOS.h"
+#import "OIDExternalUserAgentIOSCustomBrowser.h"
+#import "OIDExternalUserAgentCatalyst.h"
+#elif TARGET_OS_MAC
+#import "OIDAuthState+Mac.h"
+#import "OIDAuthorizationService+Mac.h"
+#import "OIDExternalUserAgentMac.h"
+#import "OIDRedirectHTTPHandler.h"
+#else
+#error "Platform Undefined"
+#endif
+
+/*! @mainpage AppAuth for iOS and macOS
+
+ @section introduction Introduction
+
+ AppAuth for iOS and macOS is a client SDK for communicating with [OAuth 2.0]
+ (https://tools.ietf.org/html/rfc6749) and [OpenID Connect]
+ (http://openid.net/specs/openid-connect-core-1_0.html) providers. It strives to
+ directly map the requests and responses of those specifications, while following
+ the idiomatic style of the implementation language. In addition to mapping the
+ raw protocol flows, convenience methods are available to assist with common
+ tasks like performing an action with fresh tokens.
+
+ It follows the best practices set out in
+ [RFC 8252 - OAuth 2.0 for Native Apps](https://tools.ietf.org/html/rfc8252)
+ including using `SFAuthenticationSession` and `SFSafariViewController` on iOS
+ for the auth request. Web view and `WKWebView` are explicitly *not*
+ supported due to the security and usability reasons explained in
+ [Section 8.12 of RFC 8252](https://tools.ietf.org/html/rfc8252#section-8.12).
+
+ It also supports the [PKCE](https://tools.ietf.org/html/rfc7636) extension to
+ OAuth which was created to secure authorization codes in public clients when
+ custom URI scheme redirects are used. The library is friendly to other
+ extensions (standard or otherwise) with the ability to handle additional params
+ in all protocol requests and responses.
+
+ Homepage: http://openid.github.io/AppAuth-iOS/
+ API Documentation: http://openid.github.io/AppAuth-iOS/docs/latest
+ Git Repository: https://github.com/openid/AppAuth-iOS
+
+ */
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/LoopbackHTTPServer/OIDLoopbackHTTPServer.h b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/LoopbackHTTPServer/OIDLoopbackHTTPServer.h
new file mode 100644
index 0000000000..ed2ac87947
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/LoopbackHTTPServer/OIDLoopbackHTTPServer.h
@@ -0,0 +1,192 @@
+/*! @file OIDLoopbackHTTPServer.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 The AppAuth Authors.
+ @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.
+ */
+
+// Based on the MiniSOAP Sample
+// https://developer.apple.com/library/mac/samplecode/MiniSOAP/Introduction/Intro.html
+// Modified to limit connections to the loopback interface only.
+
+#import
+
+#if TARGET_OS_OSX
+
+#import
+#import
+
+@class HTTPConnection, HTTPServerRequest, TCPServer;
+
+extern NSString * const TCPServerErrorDomain;
+
+typedef enum {
+ kTCPServerCouldNotBindToIPv4Address = 1,
+ kTCPServerCouldNotBindToIPv6Address = 2,
+ kTCPServerNoSocketsAvailable = 3,
+} TCPServerErrorCode;
+
+@protocol TCPServerDelegate
+
+- (void)TCPServer:(TCPServer *)server
+ didReceiveConnectionFromAddress:(NSData *)addr
+ inputStream:(NSInputStream *)istr
+ outputStream:(NSOutputStream *)ostr;
+
+@end
+
+@interface TCPServer : NSObject {
+@private
+ __weak id delegate;
+ NSString *domain;
+ NSString *name;
+ NSString *type;
+ uint16_t port;
+ CFSocketRef ipv4socket;
+ CFSocketRef ipv6socket;
+ NSNetService *netService;
+}
+
+- (id)delegate;
+- (void)setDelegate:(id)value;
+
+- (NSString *)domain;
+- (void)setDomain:(NSString *)value;
+
+- (NSString *)name;
+- (void)setName:(NSString *)value;
+
+- (NSString *)type;
+- (void)setType:(NSString *)value;
+
+- (uint16_t)port;
+- (void)setPort:(uint16_t)value;
+
+- (BOOL)start:(NSError **)error;
+- (BOOL)stop;
+
+- (BOOL)hasIPv4Socket;
+- (BOOL)hasIPv6Socket;
+
+// called when a new connection comes in; by default, informs the delegate
+- (void)handleNewConnectionFromAddress:(NSData *)addr
+ inputStream:(NSInputStream *)istr
+ outputStream:(NSOutputStream *)ostr;
+
+@end
+
+@interface HTTPServer : TCPServer {
+@private
+ Class connClass;
+ NSURL *docRoot;
+ // Currently active connections spawned from the HTTPServer.
+ NSMutableArray *connections;
+}
+
+- (Class)connectionClass;
+// used to configure the subclass of HTTPConnection to create when
+// a new connection comes in; by default, this is HTTPConnection
+- (void)setConnectionClass:(Class)value;
+
+@end
+
+@interface HTTPServer (HTTPServerDelegateMethods)
+// If the delegate implements this method, this is called
+// by an HTTPServer when a new connection comes in. If the
+// delegate wishes to refuse the connection, then it should
+// invalidate the connection object from within this method.
+- (void)HTTPServer:(HTTPServer *)serv didMakeNewConnection:(HTTPConnection *)conn;
+@end
+
+
+// This class represents each incoming client connection.
+@interface HTTPConnection : NSObject {
+@private
+ __weak id delegate;
+ NSData *peerAddress;
+ __weak HTTPServer *server;
+ NSMutableArray *requests;
+ NSInputStream *istream;
+ NSOutputStream *ostream;
+ NSMutableData *ibuffer;
+ NSMutableData *obuffer;
+ BOOL isValid;
+ BOOL firstResponseDone;
+}
+
+- (id)initWithPeerAddress:(NSData *)addr
+ inputStream:(NSInputStream *)istr
+ outputStream:(NSOutputStream *)ostr
+ forServer:(HTTPServer *)serv;
+
+- (id)delegate;
+- (void)setDelegate:(id)value;
+
+- (NSData *)peerAddress;
+
+- (HTTPServer *)server;
+
+// get the next request that needs to be responded to
+- (HTTPServerRequest *)nextRequest;
+
+- (BOOL)isValid;
+// shut down the connection
+- (void)invalidate;
+
+// perform the default handling action: GET and HEAD requests for files
+// in the local file system (relative to the documentRoot of the server)
+- (void)performDefaultRequestHandling:(HTTPServerRequest *)sreq;
+
+@end
+
+@interface HTTPConnection (HTTPConnectionDelegateMethods)
+// The "didReceiveRequest:" tells the delegate when a new request comes in.
+- (void)HTTPConnection:(HTTPConnection *)conn didReceiveRequest:(HTTPServerRequest *)mess;
+- (void)HTTPConnection:(HTTPConnection *)conn didSendResponse:(HTTPServerRequest *)mess;
+@end
+
+
+// As NSURLRequest and NSURLResponse are not entirely suitable for use from
+// the point of view of an HTTP server, we use CFHTTPMessageRef to encapsulate
+// requests and responses. This class packages the (future) response with a
+// request and other info for convenience.
+@interface HTTPServerRequest : NSObject {
+@private
+ HTTPConnection *connection;
+ CFHTTPMessageRef request;
+ CFHTTPMessageRef response;
+ NSInputStream *responseStream;
+}
+
+- (id)initWithRequest:(CFHTTPMessageRef)req connection:(HTTPConnection *)conn;
+
+- (HTTPConnection *)connection;
+
+- (CFHTTPMessageRef)request;
+
+// The response may include a body. As soon as the response is set,
+// the response may be written out to the network.
+- (CFHTTPMessageRef)response;
+- (void)setResponse:(CFHTTPMessageRef)value;
+
+- (NSInputStream *)responseBodyStream;
+// If there is to be a response body stream (when, say, a big
+// file is to be returned, rather than reading the whole thing
+// into memory), then it must be set on the request BEFORE the
+// response [headers] itself.
+- (void)setResponseBodyStream:(NSInputStream *)value;
+
+@end
+
+#endif // TARGET_OS_OSX
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/LoopbackHTTPServer/OIDLoopbackHTTPServer.m b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/LoopbackHTTPServer/OIDLoopbackHTTPServer.m
new file mode 100644
index 0000000000..dca381c04a
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/LoopbackHTTPServer/OIDLoopbackHTTPServer.m
@@ -0,0 +1,618 @@
+/*! @file OIDLoopbackHTTPServer.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 The AppAuth Authors.
+ @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_OSX
+
+#import "OIDLoopbackHTTPServer.h"
+#include
+#include
+#include
+
+// We'll ignore the pointer arithmetic warnings for now.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpointer-arith"
+
+@implementation HTTPServer
+
+- (id)init {
+ self = [super init];
+ connClass = [HTTPConnection self];
+ connections = [[NSMutableArray alloc] init];
+ return self;
+}
+
+- (Class)connectionClass {
+ return connClass;
+}
+
+- (void)setConnectionClass:(Class)value {
+ connClass = value;
+}
+
+// Removes the connection from the list of active connections.
+- (void)removeConnection:(HTTPConnection *)connection {
+ [connections removeObject:connection];
+}
+
+// Converts the TCPServer delegate notification into the HTTPServer delegate method.
+- (void)handleNewConnectionFromAddress:(NSData *)addr inputStream:(NSInputStream *)istr outputStream:(NSOutputStream *)ostr {
+ HTTPConnection *connection = [[connClass alloc] initWithPeerAddress:addr inputStream:istr outputStream:ostr forServer:self];
+ // Adds connection to the active connection list to retain it.
+ [connections addObject:connection];
+ [connection setDelegate:[self delegate]];
+ if ([self delegate] && [[self delegate] respondsToSelector:@selector(HTTPServer:didMakeNewConnection:)]) {
+ [[self delegate] HTTPServer:self didMakeNewConnection:connection];
+ }
+}
+
+@end
+
+
+@implementation HTTPConnection
+
+- (id)init {
+ return nil;
+}
+
+- (id)initWithPeerAddress:(NSData *)addr inputStream:(NSInputStream *)istr outputStream:(NSOutputStream *)ostr forServer:(HTTPServer *)serv {
+ peerAddress = [addr copy];
+ server = serv;
+ istream = istr;
+ ostream = ostr;
+ [istream setDelegate:self];
+ [ostream setDelegate:self];
+ [istream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:(id)kCFRunLoopCommonModes];
+ [ostream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:(id)kCFRunLoopCommonModes];
+ [istream open];
+ [ostream open];
+ isValid = YES;
+ return self;
+}
+
+- (void)dealloc {
+ [self invalidate];
+}
+
+- (id)delegate {
+ return delegate;
+}
+
+- (void)setDelegate:(id)value {
+ delegate = value;
+}
+
+- (NSData *)peerAddress {
+ return peerAddress;
+}
+
+- (HTTPServer *)server {
+ return server;
+}
+
+- (HTTPServerRequest *)nextRequest {
+ for (HTTPServerRequest *request in requests) {
+ if (![request response]) {
+ return request;
+ }
+ }
+ return nil;
+}
+
+- (BOOL)isValid {
+ return isValid;
+}
+
+- (void)invalidate {
+ if (isValid) {
+ isValid = NO;
+ [server removeConnection:self];
+ [istream setDelegate:nil];
+ [ostream setDelegate:nil];
+ [istream close];
+ [ostream close];
+ istream = nil;
+ ostream = nil;
+ ibuffer = nil;
+ obuffer = nil;
+ requests = nil;
+ }
+}
+
+// YES return means that a complete request was parsed, and the caller
+// should call again as the buffered bytes may have another complete
+// request available.
+- (BOOL)processIncomingBytes {
+ CFHTTPMessageRef working = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE);
+ CFHTTPMessageAppendBytes(working, [ibuffer bytes], [ibuffer length]);
+
+ // This "try and possibly succeed" approach is potentially expensive
+ // (lots of bytes being copied around), but the only API available for
+ // the server to use, short of doing the parsing itself.
+
+ // HTTPConnection does not handle the chunked transfer encoding
+ // described in the HTTP spec. And if there is no Content-Length
+ // header, then the request is the remainder of the stream bytes.
+
+ if (CFHTTPMessageIsHeaderComplete(working)) {
+ NSString *contentLengthValue = (__bridge_transfer NSString *)CFHTTPMessageCopyHeaderFieldValue(working, (CFStringRef)@"Content-Length");
+
+ unsigned contentLength = contentLengthValue ? [contentLengthValue intValue] : 0;
+ NSData *body = (__bridge_transfer NSData *)CFHTTPMessageCopyBody(working);
+ NSUInteger bodyLength = [body length];
+ if (contentLength <= bodyLength) {
+ NSData *newBody = [NSData dataWithBytes:[body bytes] length:contentLength];
+ [ibuffer setLength:0];
+ [ibuffer appendBytes:([body bytes] + contentLength) length:(bodyLength - contentLength)];
+ CFHTTPMessageSetBody(working, (__bridge CFDataRef)newBody);
+ } else {
+ CFRelease(working);
+ return NO;
+ }
+ } else {
+ return NO;
+ }
+
+ HTTPServerRequest *request = [[HTTPServerRequest alloc] initWithRequest:working connection:self];
+ if (!requests) {
+ requests = [[NSMutableArray alloc] init];
+ }
+ [requests addObject:request];
+ if (delegate && [delegate respondsToSelector:@selector(HTTPConnection:didReceiveRequest:)]) {
+ // Schedules the delegate to be executed later on the main thread. Cannot call the delegate
+ // directly as this method is called in a loop in order to process multiple messages, and
+ // the delegate may choose to stop and dealloc the listener – so we need queue the messages
+ // and process them separately.
+ id myDelegate = delegate;
+ dispatch_async(dispatch_get_main_queue(), ^() {
+ [myDelegate HTTPConnection:self didReceiveRequest:request];
+ });
+ } else {
+ [self performDefaultRequestHandling:request];
+ }
+
+ CFRelease(working);
+ return YES;
+}
+
+- (void)processOutgoingBytes {
+ // The HTTP headers, then the body if any, then the response stream get
+ // written out, in that order. The Content-Length: header is assumed to
+ // be properly set in the response. Outgoing responses are processed in
+ // the order the requests were received (required by HTTP).
+
+ // Write as many bytes as possible, from buffered bytes, response
+ // headers and body, and response stream.
+
+ if (![ostream hasSpaceAvailable]) {
+ return;
+ }
+
+ NSUInteger olen = [obuffer length];
+ if (0 < olen) {
+ NSInteger writ = [ostream write:[obuffer bytes] maxLength:olen];
+ // buffer any unwritten bytes for later writing
+ if (writ < olen) {
+ memmove([obuffer mutableBytes], [obuffer mutableBytes] + writ, olen - writ);
+ [obuffer setLength:olen - writ];
+ return;
+ }
+ [obuffer setLength:0];
+ }
+
+ NSUInteger cnt = requests ? [requests count] : 0;
+ HTTPServerRequest *req = (0 < cnt) ? [requests objectAtIndex:0] : nil;
+
+ CFHTTPMessageRef cfresp = req ? [req response] : NULL;
+ if (!cfresp) return;
+
+ if (!obuffer) {
+ obuffer = [[NSMutableData alloc] init];
+ }
+
+ if (!firstResponseDone) {
+ firstResponseDone = YES;
+ NSData *serialized = (__bridge_transfer NSData *)CFHTTPMessageCopySerializedMessage(cfresp);
+ NSUInteger olen = [serialized length];
+ if (0 < olen) {
+ NSInteger writ = [ostream write:[serialized bytes] maxLength:olen];
+ if (writ < olen) {
+ // buffer any unwritten bytes for later writing
+ [obuffer setLength:(olen - writ)];
+ memmove([obuffer mutableBytes], [serialized bytes] + writ, olen - writ);
+ return;
+ }
+ }
+ }
+
+ NSInputStream *respStream = [req responseBodyStream];
+ if (respStream) {
+ if ([respStream streamStatus] == NSStreamStatusNotOpen) {
+ [respStream open];
+ }
+ // read some bytes from the stream into our local buffer
+ [obuffer setLength:16 * 1024];
+ NSInteger read = [respStream read:[obuffer mutableBytes] maxLength:[obuffer length]];
+ [obuffer setLength:read];
+ }
+
+ if (0 == [obuffer length]) {
+ // When we get to this point with an empty buffer, then the
+ // processing of the response is done. If the input stream
+ // is closed or at EOF, then no more requests are coming in.
+ if (delegate && [delegate respondsToSelector:@selector(HTTPConnection:didSendResponse:)]) {
+ [delegate HTTPConnection:self didSendResponse:req];
+ }
+ [requests removeObjectAtIndex:0];
+ firstResponseDone = NO;
+ if ([istream streamStatus] == NSStreamStatusAtEnd && [requests count] == 0) {
+ [self invalidate];
+ }
+ return;
+ }
+
+ olen = [obuffer length];
+ if (0 < olen) {
+ NSInteger writ = [ostream write:[obuffer bytes] maxLength:olen];
+ // buffer any unwritten bytes for later writing
+ if (writ < olen) {
+ memmove([obuffer mutableBytes], [obuffer mutableBytes] + writ, olen - writ);
+ }
+ [obuffer setLength:olen - writ];
+ }
+}
+
+- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)streamEvent {
+ switch(streamEvent) {
+ case NSStreamEventHasBytesAvailable:;
+ uint8_t buf[16 * 1024];
+ uint8_t *buffer = NULL;
+ NSUInteger len = 0;
+ if (![istream getBuffer:&buffer length:&len]) {
+ NSInteger amount = [istream read:buf maxLength:sizeof(buf)];
+ buffer = buf;
+ len = amount;
+ }
+ if (0 < len) {
+ if (!ibuffer) {
+ ibuffer = [[NSMutableData alloc] init];
+ }
+ [ibuffer appendBytes:buffer length:len];
+ }
+ do {} while ([self processIncomingBytes]);
+ break;
+ case NSStreamEventHasSpaceAvailable:;
+ [self processOutgoingBytes];
+ break;
+ case NSStreamEventEndEncountered:;
+ [self processIncomingBytes];
+ if (stream == ostream) {
+ // When the output stream is closed, no more writing will succeed and
+ // will abandon the processing of any pending requests and further
+ // incoming bytes.
+ [self invalidate];
+ }
+ break;
+ case NSStreamEventErrorOccurred:;
+ NSLog(@"HTTPServer stream error: %@", [stream streamError]);
+ break;
+ default:
+ break;
+ }
+}
+
+- (void)performDefaultRequestHandling:(HTTPServerRequest *)mess {
+ CFHTTPMessageRef request = [mess request];
+
+ NSString *vers = (__bridge_transfer id)CFHTTPMessageCopyVersion(request);
+ if (!vers || ![vers isEqual:(id)kCFHTTPVersion1_1]) {
+ CFHTTPMessageRef response = CFHTTPMessageCreateResponse(kCFAllocatorDefault, 505, NULL, (__bridge CFStringRef)vers); // Version Not Supported
+ [mess setResponse:response];
+ CFRelease(response);
+ return;
+ }
+
+ // 500s all requests when no delegate set to handle them.
+ CFHTTPMessageRef response = CFHTTPMessageCreateResponse(kCFAllocatorDefault, 500, NULL, kCFHTTPVersion1_1); // Bad Request
+ [mess setResponse:response];
+ CFRelease(response);
+}
+
+@end
+
+
+@implementation HTTPServerRequest
+
+- (id)init {
+ return nil;
+}
+
+- (id)initWithRequest:(CFHTTPMessageRef)req connection:(HTTPConnection *)conn {
+ connection = conn;
+ request = (CFHTTPMessageRef)CFRetain(req);
+ return self;
+}
+
+- (void)dealloc {
+ if (request) CFRelease(request);
+ if (response) CFRelease(response);
+}
+
+- (HTTPConnection *)connection {
+ return connection;
+}
+
+- (CFHTTPMessageRef)request {
+ return request;
+}
+
+- (CFHTTPMessageRef)response {
+ return response;
+}
+
+- (void)setResponse:(CFHTTPMessageRef)value {
+ if (value != response) {
+ if (response) CFRelease(response);
+ response = (CFHTTPMessageRef)CFRetain(value);
+ if (response) {
+ // check to see if the response can now be sent out
+ [connection processOutgoingBytes];
+ }
+ }
+}
+
+- (NSInputStream *)responseBodyStream {
+ return responseStream;
+}
+
+- (void)setResponseBodyStream:(NSInputStream *)value {
+ if (value != responseStream) {
+ responseStream = value;
+ }
+}
+
+@end
+
+NSString * const TCPServerErrorDomain = @"TCPServerErrorDomain";
+
+@implementation TCPServer
+
+- (id)init {
+ return self;
+}
+
+- (void)dealloc {
+ [self stop];
+}
+
+- (id)delegate {
+ return delegate;
+}
+
+- (void)setDelegate:(id)value {
+ delegate = value;
+}
+
+- (NSString *)domain {
+ return domain;
+}
+
+- (void)setDomain:(NSString *)value {
+ if (domain != value) {
+ domain = [value copy];
+ }
+}
+
+- (NSString *)name {
+ return name;
+}
+
+- (void)setName:(NSString *)value {
+ if (name != value) {
+ name = [value copy];
+ }
+}
+
+- (NSString *)type {
+ return type;
+}
+
+- (void)setType:(NSString *)value {
+ if (type != value) {
+ type = [value copy];
+ }
+}
+
+- (uint16_t)port {
+ return port;
+}
+
+- (void)setPort:(uint16_t)value {
+ port = value;
+}
+
+- (void)handleNewConnectionFromAddress:(NSData *)addr inputStream:(NSInputStream *)istr outputStream:(NSOutputStream *)ostr {
+ // if the delegate implements the delegate method, call it
+ if (delegate && [(NSObject*)delegate respondsToSelector:@selector(TCPServer:didReceiveConnectionFromAddress:inputStream:outputStream:)]) {
+ [delegate TCPServer:self didReceiveConnectionFromAddress:addr inputStream:istr outputStream:ostr];
+ }
+}
+
+// This function is called by CFSocket when a new connection comes in.
+// We gather some data here, and convert the function call to a method
+// invocation on TCPServer.
+static void TCPServerAcceptCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
+ TCPServer *server = (__bridge TCPServer *)info;
+ if (kCFSocketAcceptCallBack == type) {
+ // for an AcceptCallBack, the data parameter is a pointer to a CFSocketNativeHandle
+ CFSocketNativeHandle nativeSocketHandle = *(CFSocketNativeHandle *)data;
+ uint8_t name[SOCK_MAXADDRLEN];
+ socklen_t namelen = sizeof(name);
+ NSData *peer = nil;
+ if (0 == getpeername(nativeSocketHandle, (struct sockaddr *)name, &namelen)) {
+ peer = [NSData dataWithBytes:name length:namelen];
+ }
+ CFReadStreamRef readStream = NULL;
+ CFWriteStreamRef writeStream = NULL;
+ CFStreamCreatePairWithSocket(kCFAllocatorDefault, nativeSocketHandle, &readStream, &writeStream);
+ if (readStream && writeStream) {
+ CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
+ CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
+ [server handleNewConnectionFromAddress:peer inputStream:(__bridge NSInputStream *)readStream outputStream:(__bridge NSOutputStream *)writeStream];
+ } else {
+ // on any failure, need to destroy the CFSocketNativeHandle
+ // since we are not going to use it any more
+ close(nativeSocketHandle);
+ }
+ if (readStream) CFRelease(readStream);
+ if (writeStream) CFRelease(writeStream);
+ }
+}
+
+- (BOOL)start:(NSError **)error {
+ CFSocketContext socketCtxt = {0, (__bridge void *)(self), NULL, NULL, NULL};
+ ipv4socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)&TCPServerAcceptCallBack, &socketCtxt);
+ ipv6socket = CFSocketCreate(kCFAllocatorDefault, PF_INET6, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)&TCPServerAcceptCallBack, &socketCtxt);
+
+ if (NULL == ipv4socket || NULL == ipv6socket) {
+ if (error) *error = [[NSError alloc] initWithDomain:TCPServerErrorDomain code:kTCPServerNoSocketsAvailable userInfo:nil];
+ if (ipv4socket) CFRelease(ipv4socket);
+ if (ipv6socket) CFRelease(ipv6socket);
+ ipv4socket = NULL;
+ ipv6socket = NULL;
+ return NO;
+ }
+
+ int yes = 1;
+ setsockopt(CFSocketGetNative(ipv4socket), SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));
+ setsockopt(CFSocketGetNative(ipv6socket), SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));
+
+ // set up the IPv4 endpoint; if port is 0, this will cause the kernel to choose a port for us
+ struct sockaddr_in addr4;
+ memset(&addr4, 0, sizeof(addr4));
+ addr4.sin_len = sizeof(addr4);
+ addr4.sin_family = AF_INET;
+ addr4.sin_port = htons(port);
+ addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ NSData *address4 = [NSData dataWithBytes:&addr4 length:sizeof(addr4)];
+
+ if (kCFSocketSuccess == CFSocketSetAddress(ipv4socket, (CFDataRef)address4)) {
+ if (0 == port) {
+ // now that the binding was successful, we get the port number
+ // -- we will need it for the v6 endpoint and for the NSNetService
+ NSData *addr = (__bridge_transfer NSData *)CFSocketCopyAddress(ipv4socket);
+ memcpy(&addr4, [addr bytes], [addr length]);
+ port = ntohs(addr4.sin_port);
+ }
+ } else {
+ if (ipv4socket) CFRelease(ipv4socket);
+ ipv4socket = NULL;
+ }
+
+ // set up the IPv6 endpoint
+ struct sockaddr_in6 addr6;
+ memset(&addr6, 0, sizeof(addr6));
+ addr6.sin6_len = sizeof(addr6);
+ addr6.sin6_family = AF_INET6;
+ addr6.sin6_port = htons(port);
+ memcpy(&(addr6.sin6_addr), &in6addr_loopback, sizeof(addr6.sin6_addr));
+ NSData *address6 = [NSData dataWithBytes:&addr6 length:sizeof(addr6)];
+
+ if (kCFSocketSuccess == CFSocketSetAddress(ipv6socket, (CFDataRef)address6)) {
+ if (0 == port) {
+ // In this case the IPv4 socket failed to bind but the IPv6 socket succeeded
+ // Get the port number of the IPv6 socket
+ NSData *addr = (__bridge_transfer NSData *)CFSocketCopyAddress(ipv6socket);
+ memcpy(&addr6, [addr bytes], [addr length]);
+ port = ntohs(addr6.sin6_port);
+ }
+ } else {
+ if (ipv6socket) CFRelease(ipv6socket);
+ ipv6socket = NULL;
+ }
+
+ if (!ipv4socket && !ipv6socket) {
+ // Couldn't bind an IPv4 or IPv6 socket, return an error
+ if (error) *error = [[NSError alloc] initWithDomain:TCPServerErrorDomain code:kTCPServerCouldNotBindToIPv4Address userInfo:nil];
+ return NO;
+ }
+
+ // set up the run loop sources for the sockets
+ CFRunLoopRef cfrl = CFRunLoopGetCurrent();
+
+ if (ipv4socket) {
+ CFRunLoopSourceRef source4 = CFSocketCreateRunLoopSource(kCFAllocatorDefault, ipv4socket, 0);
+ CFRunLoopAddSource(cfrl, source4, kCFRunLoopCommonModes);
+ CFRelease(source4);
+ }
+
+ if (ipv6socket) {
+ CFRunLoopSourceRef source6 = CFSocketCreateRunLoopSource(kCFAllocatorDefault, ipv6socket, 0);
+ CFRunLoopAddSource(cfrl, source6, kCFRunLoopCommonModes);
+ CFRelease(source6);
+ }
+
+ // we can only publish the service if we have a type to publish with
+ if (nil != type) {
+ NSString *publishingDomain = domain ? domain : @"";
+ NSString *publishingName = nil;
+ if (nil != name) {
+ publishingName = name;
+ } else {
+ NSString * thisHostName = [[NSProcessInfo processInfo] hostName];
+ if ([thisHostName hasSuffix:@".local"]) {
+ publishingName = [thisHostName substringToIndex:([thisHostName length] - 6)];
+ }
+ }
+ netService = [[NSNetService alloc] initWithDomain:publishingDomain type:type name:publishingName port:port];
+ [netService publish];
+ }
+
+ return YES;
+}
+
+- (BOOL)stop {
+ [netService stop];
+ netService = nil;
+ if (ipv4socket) {
+ CFSocketInvalidate(ipv4socket);
+ CFRelease(ipv4socket);
+ ipv4socket = NULL;
+ }
+ if (ipv6socket) {
+ CFSocketInvalidate(ipv6socket);
+ CFRelease(ipv6socket);
+ ipv6socket = NULL;
+ }
+ return YES;
+}
+
+- (BOOL)hasIPv4Socket {
+ return ipv4socket != nil;
+}
+
+- (BOOL)hasIPv6Socket {
+ return ipv6socket != nil;
+}
+
+@end
+
+#pragma GCC diagnostic pop
+
+#endif // TARGET_OS_OSX
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDAuthState+Mac.h b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDAuthState+Mac.h
new file mode 100644
index 0000000000..f32d27c083
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDAuthState+Mac.h
@@ -0,0 +1,51 @@
+/*! @file OIDAuthState+Mac.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_OSX
+
+#import "OIDAuthState.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief macOS specific convenience methods for @c OIDAuthState.
+ */
+@interface OIDAuthState (Mac)
+
+/*! @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 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
+ callback:(OIDAuthStateAuthorizationCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // TARGET_OS_OSX
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDAuthState+Mac.m b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDAuthState+Mac.m
new file mode 100644
index 0000000000..16b0617240
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDAuthState+Mac.m
@@ -0,0 +1,40 @@
+/*! @file OIDAuthState+Mac.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_OSX
+
+#import "OIDAuthState+Mac.h"
+
+#import "OIDExternalUserAgentMac.h"
+
+@implementation OIDAuthState (Mac)
+
++ (id)
+ authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
+ callback:(OIDAuthStateAuthorizationCallback)callback {
+ OIDExternalUserAgentMac *externalUserAgent = [[OIDExternalUserAgentMac alloc] init];
+ return [self authStateByPresentingAuthorizationRequest:authorizationRequest
+ externalUserAgent:externalUserAgent
+ callback:callback];
+}
+
+@end
+
+#endif // TARGET_OS_OSX
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDAuthorizationService+Mac.h b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDAuthorizationService+Mac.h
new file mode 100644
index 0000000000..37de63f16c
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDAuthorizationService+Mac.h
@@ -0,0 +1,45 @@
+/*! @file OIDAuthorizationService+Mac.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_OSX
+
+#import "OIDAuthorizationService.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Provides macOS specific authorization request handling.
+ */
+@interface OIDAuthorizationService (Mac)
+
+/*! @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;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // TARGET_OS_OSX
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDAuthorizationService+Mac.m b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDAuthorizationService+Mac.m
new file mode 100644
index 0000000000..c0abec8a44
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDAuthorizationService+Mac.m
@@ -0,0 +1,43 @@
+/*! @file OIDAuthorizationService+Mac.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_OSX
+
+#import "OIDAuthorizationService+Mac.h"
+
+#import "OIDExternalUserAgentMac.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation OIDAuthorizationService (Mac)
+
++ (id) presentAuthorizationRequest:(OIDAuthorizationRequest *)request
+ callback:(OIDAuthorizationCallback)callback {
+ OIDExternalUserAgentMac *externalUserAgent = [[OIDExternalUserAgentMac alloc] init];
+ return [self presentAuthorizationRequest:request
+ externalUserAgent:externalUserAgent
+ callback:callback];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // TARGET_OS_OSX
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDExternalUserAgentMac.h b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDExternalUserAgentMac.h
new file mode 100644
index 0000000000..b7122aee07
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDExternalUserAgentMac.h
@@ -0,0 +1,36 @@
+/*! @file OIDExternalUserAgentMac.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_OSX
+
+#import "OIDExternalUserAgent.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief A Mac-specific external user-agent UI Coordinator that uses the default browser to
+ present an external user-agent request.
+ */
+@interface OIDExternalUserAgentMac : NSObject
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // TARGET_OS_OSX
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDExternalUserAgentMac.m b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDExternalUserAgentMac.m
new file mode 100644
index 0000000000..c35a7a327b
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDExternalUserAgentMac.m
@@ -0,0 +1,81 @@
+/*! @file OIDExternalUserAgentMac.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_OSX
+
+#import "OIDExternalUserAgentMac.h"
+
+#import
+
+#import "OIDErrorUtilities.h"
+#import "OIDExternalUserAgentSession.h"
+#import "OIDExternalUserAgentRequest.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation OIDExternalUserAgentMac {
+ BOOL _externalUserAgentFlowInProgress;
+ __weak id _session;
+}
+
+- (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];
+
+ BOOL openedBrowser = [[NSWorkspace sharedWorkspace] openURL:requestURL];
+ if (!openedBrowser) {
+ [self cleanUp];
+ NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeBrowserOpenError
+ underlyingError:nil
+ description:@"Unable to open the browser."];
+ [session failExternalUserAgentFlowWithError:safariError];
+ }
+ return openedBrowser;
+}
+
+- (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;
+ }
+ // Ideally the browser tab with the URL should be closed here, but the AppAuth library does not
+ // control the browser.
+ [self cleanUp];
+ if (completion) completion();
+}
+
+- (void)cleanUp {
+ _session = nil;
+ _externalUserAgentFlowInProgress = NO;
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // TARGET_OS_MAC
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDRedirectHTTPHandler.h b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDRedirectHTTPHandler.h
new file mode 100644
index 0000000000..831eb0bb3d
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDRedirectHTTPHandler.h
@@ -0,0 +1,90 @@
+/*! @file OIDRedirectHTTPHandler.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_OSX
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+@protocol OIDExternalUserAgentSession;
+
+/*! @brief Start a HTTP server on the loopback interface (i.e. @c 127.0.0.1) to receive the OAuth
+ response redirects on macOS.
+ */
+@interface OIDRedirectHTTPHandler : NSObject
+
+/*! @brief The external user-agent request flow session which receives the return URL from the
+ browser.
+ @discussion The loopback HTTP server will try sending incoming request URLs to the OAuth
+ redirect handler to continue the flow. This should be set while an external user-agent
+ request flow is in progress.
+ */
+@property(nonatomic, strong, nullable) id currentAuthorizationFlow;
+
+/*! @brief Creates an a loopback HTTP redirect URI handler with the given success URL.
+ @param successURL The URL that the user is redirected to after the external user-agent request flow completes
+ either with a result of success or error. The contents of this page should instruct the user
+ to return to the app.
+ @discussion Once you have initiated the external user-agent request, be sure to set
+ @c currentAuthorizationFlow on this object so that any responses received by this listener will
+ be routed accordingly.
+ */
+- (instancetype)initWithSuccessURL:(nullable NSURL *)successURL;
+
+/*! @brief Starts listening on the loopback interface on a specified port, and returns a URL
+ with the base address. Use the returned redirect URI to build a @c OIDExternalUserAgentRequest,
+ and once you initiate the request, set the resulting @c OIDExternalUserAgentSession to
+ @c currentAuthorizationFlow so the response can be handled.
+ @param returnError The error if an error occurred while starting the local HTTP server.
+ @param port The manually specified port, or 0 for a random available port.
+ @return The URL containing the address of the server with the specified port, or nil if there was an error.
+ @discussion Each instance of @c OIDRedirectHTTPHandler can only listen for a single response.
+ Calling this more than once will result in the previous listener being cancelled (equivalent
+ of @c cancelHTTPListener being called).
+ */
+- (NSURL *)startHTTPListener:(NSError **)returnError withPort:(uint16_t)port;
+
+/*! @brief Starts listening on the loopback interface on a random available port, and returns a URL
+ with the base address. Use the returned redirect URI to build a @c OIDExternalUserAgentRequest,
+ and once you initiate the request, set the resulting @c OIDExternalUserAgentSession to
+ @c currentAuthorizationFlow so the response can be handled.
+ @param returnError The error if an error occurred while starting the local HTTP server.
+ @return The URL containing the address of the server with the randomly assigned available port.
+ @discussion Each instance of @c OIDRedirectHTTPHandler can only listen for a single response.
+ Calling this more than once will result in the previous listener being cancelled (equivalent
+ of @c cancelHTTPListener being called).
+ */
+- (NSURL *)startHTTPListener:(NSError **)returnError;
+
+/*! @brief Stops listening the loopback interface and sends an cancellation error (in the domain
+ ::OIDGeneralErrorDomain, with the code ::OIDErrorCodeProgramCanceledAuthorizationFlow) to
+ the @c currentAuthorizationFlow. Has no effect if called when no requests are pending.
+ @discussion The HTTP listener is stopped automatically on receiving a valid response (regardless
+ of whether the request succeeded or not), this method should not be called except when
+ abandoning the external user-agent request.
+ */
+- (void)cancelHTTPListener;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // TARGET_OS_OSX
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDRedirectHTTPHandler.m b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDRedirectHTTPHandler.m
new file mode 100644
index 0000000000..8a3df6cc24
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuth/macOS/OIDRedirectHTTPHandler.m
@@ -0,0 +1,177 @@
+/*! @file OIDRedirectHTTPHandler.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_OSX
+
+#import "OIDRedirectHTTPHandler.h"
+
+#import "OIDAuthorizationService.h"
+#import "OIDErrorUtilities.h"
+#import "OIDExternalUserAgentSession.h"
+#import "OIDLoopbackHTTPServer.h"
+
+/*! @brief Page that is returned following a completed authorization. Show your own page instead by
+ supplying a URL in @c initWithSuccessURL that the user will be redirected to.
+ */
+static NSString *const kHTMLAuthorizationComplete =
+ @"Authorization complete.
Return to the app.";
+
+/*! @brief Error warning that the @c currentAuthorizationFlow is not set on this object (likely a
+ developer error, unless the user stumbled upon the loopback server before the authorization
+ had started completely).
+ @description An object conforming to @c OIDExternalUserAgentSession is returned when the
+ authorization is presented with
+ @c OIDAuthorizationService::presentAuthorizationRequest:callback:. It should be set to
+ @c currentAuthorization when using a loopback redirect.
+ */
+static NSString *const kHTMLErrorMissingCurrentAuthorizationFlow =
+ @"AppAuth Error: No currentAuthorizationFlow
is set on the "
+ "OIDRedirectHTTPHandler
. Cannot process redirect.";
+
+/*! @brief Error warning that the URL does not represent a valid redirect. This should be rare, may
+ happen if the user stumbles upon the loopback server randomly.
+ */
+static NSString *const kHTMLErrorRedirectNotValid =
+ @"AppAuth Error: Not a valid redirect.";
+
+@implementation OIDRedirectHTTPHandler {
+ HTTPServer *_httpServ;
+ NSURL *_successURL;
+}
+
+- (instancetype)init {
+ return [self initWithSuccessURL:nil];
+}
+
+- (instancetype)initWithSuccessURL:(nullable NSURL *)successURL {
+ self = [super init];
+ if (self) {
+ _successURL = [successURL copy];
+ }
+ return self;
+}
+
+- (NSURL *)startHTTPListener:(NSError **)returnError withPort:(uint16_t)port {
+ // Cancels any pending requests.
+ [self cancelHTTPListener];
+
+ // Starts a HTTP server on the loopback interface.
+ // By not specifying a port, a random available one will be assigned.
+ _httpServ = [[HTTPServer alloc] init];
+ [_httpServ setPort:port];
+ [_httpServ setDelegate:self];
+ NSError *error = nil;
+ if (![_httpServ start:&error]) {
+ if (returnError) {
+ *returnError = error;
+ }
+ return nil;
+ } else if ([_httpServ hasIPv4Socket]) {
+ // Prefer the IPv4 loopback address
+ NSString *serverURL = [NSString stringWithFormat:@"http://127.0.0.1:%d/", [_httpServ port]];
+ return [NSURL URLWithString:serverURL];
+ } else if ([_httpServ hasIPv6Socket]) {
+ // Use the IPv6 loopback address if IPv4 isn't available
+ NSString *serverURL = [NSString stringWithFormat:@"http://[::1]:%d/", [_httpServ port]];
+ return [NSURL URLWithString:serverURL];
+ }
+
+ return nil;
+}
+
+- (NSURL *)startHTTPListener:(NSError **)returnError {
+ // A port of 0 requests a random available port
+ return [self startHTTPListener:returnError withPort:0];
+}
+
+- (void)cancelHTTPListener {
+ [self stopHTTPListener];
+
+ // Cancels the pending authorization flow (if any) with error.
+ NSError *cancelledError =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeProgramCanceledAuthorizationFlow
+ underlyingError:nil
+ description:@"The HTTP listener was cancelled programmatically."];
+ [_currentAuthorizationFlow failExternalUserAgentFlowWithError:cancelledError];
+ _currentAuthorizationFlow = nil;
+}
+
+/*! @brief Stops listening on the loopback interface without modifying the state of the
+ @c currentAuthorizationFlow. Should be called when the authorization flow completes or is
+ cancelled.
+ */
+- (void)stopHTTPListener {
+ _httpServ.delegate = nil;
+ [_httpServ stop];
+ _httpServ = nil;
+}
+
+- (void)HTTPConnection:(HTTPConnection *)conn didReceiveRequest:(HTTPServerRequest *)mess {
+ // Sends URL to AppAuth.
+ CFURLRef url = CFHTTPMessageCopyRequestURL(mess.request);
+ BOOL handled = [_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:(__bridge NSURL *)url];
+
+ // Stops listening to further requests after the first valid authorization response.
+ if (handled) {
+ _currentAuthorizationFlow = nil;
+ [self stopHTTPListener];
+ }
+
+ // Responds to browser request.
+ NSString *bodyText = kHTMLAuthorizationComplete;
+ NSInteger httpResponseCode = (_successURL) ? 302 : 200;
+ // Returns an error page if a URL other than the expected redirect is requested.
+ if (!handled) {
+ if (_currentAuthorizationFlow) {
+ bodyText = kHTMLErrorRedirectNotValid;
+ httpResponseCode = 404;
+ } else {
+ bodyText = kHTMLErrorMissingCurrentAuthorizationFlow;
+ httpResponseCode = 400;
+ }
+ }
+ NSData *data = [bodyText dataUsingEncoding:NSUTF8StringEncoding];
+
+ CFHTTPMessageRef response = CFHTTPMessageCreateResponse(kCFAllocatorDefault,
+ httpResponseCode,
+ NULL,
+ kCFHTTPVersion1_1);
+ if (httpResponseCode == 302) {
+ CFHTTPMessageSetHeaderFieldValue(response,
+ (__bridge CFStringRef)@"Location",
+ (__bridge CFStringRef)_successURL.absoluteString);
+ }
+ CFHTTPMessageSetHeaderFieldValue(response,
+ (__bridge CFStringRef)@"Content-Length",
+ (__bridge CFStringRef)[NSString stringWithFormat:@"%lu",
+ (unsigned long)data.length]);
+ CFHTTPMessageSetBody(response, (__bridge CFDataRef)data);
+
+ [mess setResponse:response];
+ CFRelease(response);
+}
+
+- (void)dealloc {
+ [self cancelHTTPListener];
+}
+
+@end
+
+#endif // TARGET_OS_MAC
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore.h
new file mode 100644
index 0000000000..c30af46488
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore.h
@@ -0,0 +1,44 @@
+/*! @file AppAuthCore.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDAuthState.h"
+#import "OIDAuthStateChangeDelegate.h"
+#import "OIDAuthStateErrorDelegate.h"
+#import "OIDAuthorizationRequest.h"
+#import "OIDAuthorizationResponse.h"
+#import "OIDAuthorizationService.h"
+#import "OIDError.h"
+#import "OIDErrorUtilities.h"
+#import "OIDExternalUserAgent.h"
+#import "OIDExternalUserAgentRequest.h"
+#import "OIDExternalUserAgentSession.h"
+#import "OIDGrantTypes.h"
+#import "OIDIDToken.h"
+#import "OIDRegistrationRequest.h"
+#import "OIDRegistrationResponse.h"
+#import "OIDResponseTypes.h"
+#import "OIDScopes.h"
+#import "OIDScopeUtilities.h"
+#import "OIDServiceConfiguration.h"
+#import "OIDServiceDiscovery.h"
+#import "OIDTokenRequest.h"
+#import "OIDTokenResponse.h"
+#import "OIDTokenUtilities.h"
+#import "OIDURLSessionProvider.h"
+#import "OIDEndSessionRequest.h"
+#import "OIDEndSessionResponse.h"
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthState.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthState.h
new file mode 100644
index 0000000000..68697d2cac
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthState.h
@@ -0,0 +1,272 @@
+/*! @file OIDAuthState.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+@class OIDAuthorizationRequest;
+@class OIDAuthorizationResponse;
+@class OIDAuthState;
+@class OIDRegistrationResponse;
+@class OIDTokenResponse;
+@class OIDTokenRequest;
+@protocol OIDAuthStateChangeDelegate;
+@protocol OIDAuthStateErrorDelegate;
+@protocol OIDExternalUserAgent;
+@protocol OIDExternalUserAgentSession;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Represents a block used to call an action with a fresh access token.
+ @param accessToken A valid access token if available.
+ @param idToken A valid ID token if available.
+ @param error The error if an error occurred.
+ */
+typedef void (^OIDAuthStateAction)(NSString *_Nullable accessToken,
+ NSString *_Nullable idToken,
+ NSError *_Nullable error);
+
+/*! @brief The method called when the @c
+ OIDAuthState.authStateByPresentingAuthorizationRequest:presentingViewController:callback:
+ method has completed or failed.
+ @param authState The auth state, if the authorization request succeeded.
+ @param error The error if an error occurred.
+ */
+typedef void (^OIDAuthStateAuthorizationCallback)(OIDAuthState *_Nullable authState,
+ NSError *_Nullable error);
+
+/*! @brief A convenience class that retains the auth state between @c OIDAuthorizationResponse%s
+ and @c OIDTokenResponse%s.
+ */
+@interface OIDAuthState : NSObject
+
+/*! @brief The most recent refresh token received from the server.
+ @discussion Rather than using this property directly, you should call
+ @c OIDAuthState.performActionWithFreshTokens:.
+ @remarks refresh_token
+ @see https://tools.ietf.org/html/rfc6749#section-5.1
+ */
+@property(nonatomic, readonly, nullable) NSString *refreshToken;
+
+/*! @brief The scope of the current authorization grant.
+ @discussion This represents the latest scope returned by the server and may be a subset of the
+ scope that was initially granted.
+ @remarks scope
+ */
+@property(nonatomic, readonly, nullable) NSString *scope;
+
+/*! @brief The most recent authorization response used to update the authorization state. For the
+ implicit flow, this will contain the latest access token.
+ */
+@property(nonatomic, readonly) OIDAuthorizationResponse *lastAuthorizationResponse;
+
+/*! @brief The most recent token response used to update this authorization state. This will
+ contain the latest access token.
+ */
+@property(nonatomic, readonly, nullable) OIDTokenResponse *lastTokenResponse;
+
+/*! @brief The most recent registration response used to update this authorization state. This will
+ contain the latest client credentials.
+ */
+@property(nonatomic, readonly, nullable) OIDRegistrationResponse *lastRegistrationResponse;
+
+/*! @brief The authorization error that invalidated this @c OIDAuthState.
+ @discussion The authorization error encountered by @c OIDAuthState or set by the user via
+ @c OIDAuthState.updateWithAuthorizationError: that invalidated this @c OIDAuthState.
+ Authorization errors from @c OIDAuthState will always have a domain of
+ @c ::OIDOAuthAuthorizationErrorDomain or @c ::OIDOAuthTokenErrorDomain. Note: that after
+ unarchiving the @c OIDAuthState object, the \NSError_userInfo property of this error will
+ be nil.
+ */
+@property(nonatomic, readonly, nullable) NSError *authorizationError;
+
+/*! @brief Returns YES if the authorization state is not known to be invalid.
+ @discussion Returns YES if no OAuth errors have been received, and the last call resulted in a
+ successful access token or id token. This does not mean that the access is fresh - just
+ that it was valid the last time it was used. Note that network and other transient errors
+ do not invalidate the authorized state. If NO, you should authenticate the user again,
+ using a fresh authorization request. Invalid @c OIDAuthState objects may still be useful in
+ that case, to hint at the previously authorized user and streamline the re-authentication
+ experience.
+ */
+@property(nonatomic, readonly) BOOL isAuthorized;
+
+/*! @brief The @c OIDAuthStateChangeDelegate delegate.
+ @discussion Use the delegate to observe state changes (and update storage) as well as error
+ states.
+ */
+@property(nonatomic, weak, nullable) id stateChangeDelegate;
+
+/*! @brief The @c OIDAuthStateErrorDelegate delegate.
+ @discussion Use the delegate to observe state changes (and update storage) as well as error
+ states.
+ */
+@property(nonatomic, weak, nullable) id errorDelegate;
+
+/*! @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 externalUserAgent A external user agent that can present an external user-agent 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)
+ authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
+ externalUserAgent:(id)externalUserAgent
+ callback:(OIDAuthStateAuthorizationCallback)callback;
+
+/*! @internal
+ @brief Unavailable. Please use @c initWithAuthorizationResponse:.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @brief Creates an auth state from an authorization response.
+ @param authorizationResponse The authorization response.
+ */
+- (instancetype)initWithAuthorizationResponse:(OIDAuthorizationResponse *)authorizationResponse;
+
+/*! @brief Creates an auth state from an authorization and token response.
+ @param authorizationResponse The authorization response.
+ @param tokenResponse The token response.
+ */
+- (instancetype)initWithAuthorizationResponse:(OIDAuthorizationResponse *)authorizationResponse
+ tokenResponse:(nullable OIDTokenResponse *)tokenResponse;
+
+/*! @brief Creates an auth state from an registration response.
+ @param registrationResponse The registration response.
+ */
+- (instancetype)initWithRegistrationResponse:(OIDRegistrationResponse *)registrationResponse;
+
+/*! @brief Creates an auth state from an authorization, token and registration response.
+ @param authorizationResponse The authorization response.
+ @param tokenResponse The token response.
+ @param registrationResponse The registration response.
+ */
+- (instancetype)initWithAuthorizationResponse:
+ (nullable OIDAuthorizationResponse *)authorizationResponse
+ tokenResponse:(nullable OIDTokenResponse *)tokenResponse
+ registrationResponse:(nullable OIDRegistrationResponse *)registrationResponse
+ NS_DESIGNATED_INITIALIZER;
+
+/*! @brief Updates the authorization state based on a new authorization response.
+ @param authorizationResponse The new authorization response to update the state with.
+ @param error Any error encountered when performing the authorization request. Errors in the
+ domain @c ::OIDOAuthAuthorizationErrorDomain are reflected in the auth state, other errors
+ are assumed to be transient, and ignored.
+ @discussion Typically called with the response from an incremental authorization request,
+ or if using the implicit flow. Will clear the @c #lastTokenResponse property.
+ */
+- (void)updateWithAuthorizationResponse:(nullable OIDAuthorizationResponse *)authorizationResponse
+ error:(nullable NSError *)error;
+
+/*! @brief Updates the authorization state based on a new token response.
+ @param tokenResponse The new token response to update the state from.
+ @param error Any error encountered when performing the authorization request. Errors in the
+ domain @c ::OIDOAuthTokenErrorDomain are reflected in the auth state, other errors
+ are assumed to be transient, and ignored.
+ @discussion Typically called with the response from an authorization code exchange, or a token
+ refresh.
+ */
+- (void)updateWithTokenResponse:(nullable OIDTokenResponse *)tokenResponse
+ error:(nullable NSError *)error;
+
+/*! @brief Updates the authorization state based on a new registration response.
+ @param registrationResponse The new registration response to update the state with.
+ @discussion Typically called with the response from a successful client registration
+ request. Will reset the auth state.
+ */
+- (void)updateWithRegistrationResponse:(nullable OIDRegistrationResponse *)registrationResponse;
+
+/*! @brief Updates the authorization state based on an authorization error.
+ @param authorizationError The authorization error.
+ @discussion Call this method if you receive an authorization error during an API call to
+ invalidate the authentication state of this @c OIDAuthState. Don't call with errors
+ unrelated to authorization, such as transient network errors.
+ The OIDAuthStateErrorDelegate.authState:didEncounterAuthorizationError: method of
+ @c #errorDelegate will be called with the error.
+ You may optionally use the convenience method
+ OIDErrorUtilities.resourceServerAuthorizationErrorWithCode:errorResponse:underlyingError:
+ to create \NSError objects for use here.
+ The latest error received is stored in @c #authorizationError. Note: that after unarchiving
+ this object, the \NSError_userInfo property of this error will be nil.
+ */
+- (void)updateWithAuthorizationError:(NSError *)authorizationError;
+
+/*! @brief Calls the block with a valid access token (refreshing it first, if needed), or if a
+ refresh was needed and failed, with the error that caused it to fail.
+ @param action The block to execute with a fresh token. This block will be executed on the main
+ thread.
+ */
+- (void)performActionWithFreshTokens:(OIDAuthStateAction)action;
+
+/*! @brief Calls the block with a valid access token (refreshing it first, if needed), or if a
+ refresh was needed and failed, with the error that caused it to fail.
+ @param action The block to execute with a fresh token. This block will be executed on the main
+ thread.
+ @param additionalParameters Additional parameters for the token request if token is
+ refreshed.
+ */
+- (void)performActionWithFreshTokens:(OIDAuthStateAction)action
+ additionalRefreshParameters:
+ (nullable NSDictionary *)additionalParameters;
+
+/*! @brief Calls the block with a valid access token (refreshing it first, if needed), or if a
+ refresh was needed and failed, with the error that caused it to fail.
+ @param action The block to execute with a fresh token. This block will be executed on the main
+ thread.
+ @param additionalParameters Additional parameters for the token request if token is
+ refreshed.
+ @param dispatchQueue The dispatchQueue on which to dispatch the action block.
+ */
+- (void)performActionWithFreshTokens:(OIDAuthStateAction)action
+ additionalRefreshParameters:
+ (nullable NSDictionary *)additionalParameters
+ dispatchQueue:(dispatch_queue_t)dispatchQueue;
+
+/*! @brief Forces a token refresh the next time @c OIDAuthState.performActionWithFreshTokens: is
+ called, even if the current tokens are considered valid.
+ */
+- (void)setNeedsTokenRefresh;
+
+/*! @brief Creates a token request suitable for refreshing an access token.
+ @return A @c OIDTokenRequest suitable for using a refresh token to obtain a new access token.
+ @discussion After performing the refresh, call @c OIDAuthState.updateWithTokenResponse:error:
+ to update the authorization state based on the response. Rather than doing the token refresh
+ yourself, you should use @c OIDAuthState.performActionWithFreshTokens:.
+ @see https://tools.ietf.org/html/rfc6749#section-1.5
+ */
+- (nullable OIDTokenRequest *)tokenRefreshRequest;
+
+/*! @brief Creates a token request suitable for refreshing an access token.
+ @param additionalParameters Additional parameters for the token request.
+ @return A @c OIDTokenRequest suitable for using a refresh token to obtain a new access token.
+ @discussion After performing the refresh, call @c OIDAuthState.updateWithTokenResponse:error:
+ to update the authorization state based on the response. Rather than doing the token refresh
+ yourself, you should use @c OIDAuthState.performActionWithFreshTokens:.
+ @see https://tools.ietf.org/html/rfc6749#section-1.5
+ */
+- (nullable OIDTokenRequest *)tokenRefreshRequestWithAdditionalParameters:
+ (nullable NSDictionary *)additionalParameters;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthState.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthState.m
new file mode 100644
index 0000000000..fe8a162217
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthState.m
@@ -0,0 +1,570 @@
+/*! @file OIDAuthState.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDAuthState.h"
+
+#import "OIDAuthStateChangeDelegate.h"
+#import "OIDAuthStateErrorDelegate.h"
+#import "OIDAuthorizationRequest.h"
+#import "OIDAuthorizationResponse.h"
+#import "OIDAuthorizationService.h"
+#import "OIDDefines.h"
+#import "OIDError.h"
+#import "OIDErrorUtilities.h"
+#import "OIDRegistrationResponse.h"
+#import "OIDTokenRequest.h"
+#import "OIDTokenResponse.h"
+#import "OIDTokenUtilities.h"
+
+/*! @brief Key used to encode the @c refreshToken property for @c NSSecureCoding.
+ */
+static NSString *const kRefreshTokenKey = @"refreshToken";
+
+/*! @brief Key used to encode the @c needsTokenRefresh property for @c NSSecureCoding.
+ */
+static NSString *const kNeedsTokenRefreshKey = @"needsTokenRefresh";
+
+/*! @brief Key used to encode the @c scope property for @c NSSecureCoding.
+ */
+static NSString *const kScopeKey = @"scope";
+
+/*! @brief Key used to encode the @c lastAuthorizationResponse property for @c NSSecureCoding.
+ */
+static NSString *const kLastAuthorizationResponseKey = @"lastAuthorizationResponse";
+
+/*! @brief Key used to encode the @c lastTokenResponse property for @c NSSecureCoding.
+ */
+static NSString *const kLastTokenResponseKey = @"lastTokenResponse";
+
+/*! @brief Key used to encode the @c lastOAuthError property for @c NSSecureCoding.
+ */
+static NSString *const kAuthorizationErrorKey = @"authorizationError";
+
+/*! @brief The exception thrown when a developer tries to create a refresh request from an
+ authorization request with no authorization code.
+ */
+static NSString *const kRefreshTokenRequestException =
+ @"Attempted to create a token refresh request from a token response with no refresh token.";
+
+/*! @brief Number of seconds the access token is refreshed before it actually expires.
+ */
+static const NSUInteger kExpiryTimeTolerance = 60;
+
+/*! @brief Object to hold OIDAuthState pending actions.
+ */
+@interface OIDAuthStatePendingAction : NSObject
+@property(nonatomic, readonly, nullable) OIDAuthStateAction action;
+@property(nonatomic, readonly, nullable) dispatch_queue_t dispatchQueue;
+@end
+@implementation OIDAuthStatePendingAction
+- (id)initWithAction:(OIDAuthStateAction)action andDispatchQueue:(dispatch_queue_t)dispatchQueue {
+ self = [super init];
+ if (self) {
+ _action = action;
+ _dispatchQueue = dispatchQueue;
+ }
+ return self;
+}
+@end
+
+@interface OIDAuthState ()
+
+/*! @brief The access token generated by the authorization server.
+ @discussion Rather than using this property directly, you should call
+ @c OIDAuthState.withFreshTokenPerformAction:.
+ */
+@property(nonatomic, readonly, nullable) NSString *accessToken;
+
+/*! @brief The approximate expiration date & time of the access token.
+ @discussion Rather than using this property directly, you should call
+ @c OIDAuthState.withFreshTokenPerformAction:.
+ */
+@property(nonatomic, readonly, nullable) NSDate *accessTokenExpirationDate;
+
+/*! @brief ID Token value associated with the authenticated session.
+ @discussion Rather than using this property directly, you should call
+ OIDAuthState.withFreshTokenPerformAction:.
+ */
+@property(nonatomic, readonly, nullable) NSString *idToken;
+
+/*! @brief Private method, called when the internal state changes.
+ */
+- (void)didChangeState;
+
+@end
+
+
+@implementation OIDAuthState {
+ /*! @brief Array of pending actions (use @c _pendingActionsSyncObject to synchronize access).
+ */
+ NSMutableArray *_pendingActions;
+
+ /*! @brief Object for synchronizing access to @c pendingActions.
+ */
+ id _pendingActionsSyncObject;
+
+ /*! @brief If YES, tokens will be refreshed on the next API call regardless of expiry.
+ */
+ BOOL _needsTokenRefresh;
+}
+
+#pragma mark - Convenience initializers
+
++ (id)
+ authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
+ externalUserAgent:(id)externalUserAgent
+ callback:(OIDAuthStateAuthorizationCallback)callback {
+ // presents the authorization request
+ id authFlowSession = [OIDAuthorizationService
+ presentAuthorizationRequest:authorizationRequest
+ externalUserAgent:externalUserAgent
+ callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse,
+ NSError *_Nullable authorizationError) {
+ // inspects response and processes further if needed (e.g. authorization
+ // code exchange)
+ if (authorizationResponse) {
+ if ([authorizationRequest.responseType
+ isEqualToString:OIDResponseTypeCode]) {
+ // if the request is for the code flow (NB. not hybrid), assumes the
+ // code is intended for this client, and performs the authorization
+ // code exchange
+ OIDTokenRequest *tokenExchangeRequest =
+ [authorizationResponse tokenExchangeRequest];
+ [OIDAuthorizationService performTokenRequest:tokenExchangeRequest
+ originalAuthorizationResponse:authorizationResponse
+ callback:^(OIDTokenResponse *_Nullable tokenResponse,
+ NSError *_Nullable tokenError) {
+ OIDAuthState *authState;
+ if (tokenResponse) {
+ authState = [[OIDAuthState alloc]
+ initWithAuthorizationResponse:
+ authorizationResponse
+ tokenResponse:tokenResponse];
+ }
+ callback(authState, tokenError);
+ }];
+ } else {
+ // hybrid flow (code id_token). Two possible cases:
+ // 1. The code is not for this client, ie. will be sent to a
+ // webservice that performs the id token verification and token
+ // exchange
+ // 2. The code is for this client and, for security reasons, the
+ // application developer must verify the id_token signature and
+ // c_hash before calling the token endpoint
+ OIDAuthState *authState = [[OIDAuthState alloc]
+ initWithAuthorizationResponse:authorizationResponse];
+ callback(authState, authorizationError);
+ }
+ } else {
+ callback(nil, authorizationError);
+ }
+ }];
+ return authFlowSession;
+}
+
+#pragma mark - Initializers
+
+- (nonnull instancetype)init
+ OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithAuthorizationResponse:tokenResponse:))
+
+/*! @brief Creates an auth state from an authorization response.
+ @param authorizationResponse The authorization response.
+ */
+- (instancetype)initWithAuthorizationResponse:(OIDAuthorizationResponse *)authorizationResponse {
+ return [self initWithAuthorizationResponse:authorizationResponse tokenResponse:nil];
+}
+
+
+/*! @brief Designated initializer.
+ @param authorizationResponse The authorization response.
+ @discussion Creates an auth state from an authorization response and token response.
+ */
+- (instancetype)initWithAuthorizationResponse:(OIDAuthorizationResponse *)authorizationResponse
+ tokenResponse:(nullable OIDTokenResponse *)tokenResponse {
+ return [self initWithAuthorizationResponse:authorizationResponse
+ tokenResponse:tokenResponse
+ registrationResponse:nil];
+}
+
+/*! @brief Creates an auth state from an registration response.
+ @param registrationResponse The registration response.
+ */
+- (instancetype)initWithRegistrationResponse:(OIDRegistrationResponse *)registrationResponse {
+ return [self initWithAuthorizationResponse:nil
+ tokenResponse:nil
+ registrationResponse:registrationResponse];
+}
+
+- (instancetype)initWithAuthorizationResponse:
+ (nullable OIDAuthorizationResponse *)authorizationResponse
+ tokenResponse:(nullable OIDTokenResponse *)tokenResponse
+ registrationResponse:(nullable OIDRegistrationResponse *)registrationResponse {
+ self = [super init];
+ if (self) {
+ _pendingActionsSyncObject = [[NSObject alloc] init];
+
+ if (registrationResponse) {
+ [self updateWithRegistrationResponse:registrationResponse];
+ }
+
+ if (authorizationResponse) {
+ [self updateWithAuthorizationResponse:authorizationResponse error:nil];
+ }
+
+ if (tokenResponse) {
+ [self updateWithTokenResponse:tokenResponse error:nil];
+ }
+ }
+ return self;
+}
+
+#pragma mark - NSObject overrides
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@: %p, isAuthorized: %@, refreshToken: \"%@\", "
+ "scope: \"%@\", accessToken: \"%@\", "
+ "accessTokenExpirationDate: %@, idToken: \"%@\", "
+ "lastAuthorizationResponse: %@, lastTokenResponse: %@, "
+ "lastRegistrationResponse: %@, authorizationError: %@>",
+ NSStringFromClass([self class]),
+ (void *)self,
+ (self.isAuthorized) ? @"YES" : @"NO",
+ [OIDTokenUtilities redact:_refreshToken],
+ _scope,
+ [OIDTokenUtilities redact:self.accessToken],
+ self.accessTokenExpirationDate,
+ [OIDTokenUtilities redact:self.idToken],
+ _lastAuthorizationResponse,
+ _lastTokenResponse,
+ _lastRegistrationResponse,
+ _authorizationError];
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+ return YES;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+ _lastAuthorizationResponse = [aDecoder decodeObjectOfClass:[OIDAuthorizationResponse class]
+ forKey:kLastAuthorizationResponseKey];
+ _lastTokenResponse = [aDecoder decodeObjectOfClass:[OIDTokenResponse class]
+ forKey:kLastTokenResponseKey];
+ self = [self initWithAuthorizationResponse:_lastAuthorizationResponse
+ tokenResponse:_lastTokenResponse];
+ if (self) {
+ _authorizationError =
+ [aDecoder decodeObjectOfClass:[NSError class] forKey:kAuthorizationErrorKey];
+ _scope = [aDecoder decodeObjectOfClass:[NSString class] forKey:kScopeKey];
+ _refreshToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:kRefreshTokenKey];
+ _needsTokenRefresh = [aDecoder decodeBoolForKey:kNeedsTokenRefreshKey];
+ }
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+ [aCoder encodeObject:_lastAuthorizationResponse forKey:kLastAuthorizationResponseKey];
+ [aCoder encodeObject:_lastTokenResponse forKey:kLastTokenResponseKey];
+ if (_authorizationError) {
+ NSError *codingSafeAuthorizationError = [NSError errorWithDomain:_authorizationError.domain
+ code:_authorizationError.code
+ userInfo:nil];
+ [aCoder encodeObject:codingSafeAuthorizationError forKey:kAuthorizationErrorKey];
+ }
+ [aCoder encodeObject:_scope forKey:kScopeKey];
+ [aCoder encodeObject:_refreshToken forKey:kRefreshTokenKey];
+ [aCoder encodeBool:_needsTokenRefresh forKey:kNeedsTokenRefreshKey];
+}
+
+#pragma mark - Private convenience getters
+
+- (NSString *)accessToken {
+ if (_authorizationError) {
+ return nil;
+ }
+ return _lastTokenResponse ? _lastTokenResponse.accessToken
+ : _lastAuthorizationResponse.accessToken;
+}
+
+- (NSString *)tokenType {
+ if (_authorizationError) {
+ return nil;
+ }
+ return _lastTokenResponse ? _lastTokenResponse.tokenType
+ : _lastAuthorizationResponse.tokenType;
+}
+
+- (NSDate *)accessTokenExpirationDate {
+ if (_authorizationError) {
+ return nil;
+ }
+ return _lastTokenResponse ? _lastTokenResponse.accessTokenExpirationDate
+ : _lastAuthorizationResponse.accessTokenExpirationDate;
+}
+
+- (NSString *)idToken {
+ if (_authorizationError) {
+ return nil;
+ }
+ return _lastTokenResponse ? _lastTokenResponse.idToken
+ : _lastAuthorizationResponse.idToken;
+}
+
+#pragma mark - Getters
+
+- (BOOL)isAuthorized {
+ return !self.authorizationError && (self.accessToken || self.idToken || self.refreshToken);
+}
+
+#pragma mark - Updating the state
+
+- (void)updateWithRegistrationResponse:(OIDRegistrationResponse *)registrationResponse {
+ _lastRegistrationResponse = registrationResponse;
+ _refreshToken = nil;
+ _scope = nil;
+ _lastAuthorizationResponse = nil;
+ _lastTokenResponse = nil;
+ _authorizationError = nil;
+ [self didChangeState];
+}
+
+- (void)updateWithAuthorizationResponse:(nullable OIDAuthorizationResponse *)authorizationResponse
+ error:(nullable NSError *)error {
+ // If the error is an OAuth authorization error, updates the state. Other errors are ignored.
+ if (error.domain == OIDOAuthAuthorizationErrorDomain) {
+ [self updateWithAuthorizationError:error];
+ return;
+ }
+ if (!authorizationResponse) {
+ return;
+ }
+
+ _lastAuthorizationResponse = authorizationResponse;
+
+ // clears the last token response and refresh token as these now relate to an old authorization
+ // that is no longer relevant
+ _lastTokenResponse = nil;
+ _refreshToken = nil;
+ _authorizationError = nil;
+
+ // if the response's scope is nil, it means that it equals that of the request
+ // see: https://tools.ietf.org/html/rfc6749#section-5.1
+ _scope = (authorizationResponse.scope) ? authorizationResponse.scope
+ : authorizationResponse.request.scope;
+
+ [self didChangeState];
+}
+
+- (void)updateWithTokenResponse:(nullable OIDTokenResponse *)tokenResponse
+ error:(nullable NSError *)error {
+ if (_authorizationError) {
+ // Calling updateWithTokenResponse while in an error state probably means the developer obtained
+ // a new token and did the exchange without also calling updateWithAuthorizationResponse.
+ // Attempts to handle gracefully, but warns the developer that this is unexpected.
+ NSLog(@"OIDAuthState:updateWithTokenResponse should not be called in an error state [%@] call"
+ "updateWithAuthorizationResponse with the result of the fresh authorization response"
+ "first",
+ _authorizationError);
+
+ _authorizationError = nil;
+ }
+
+ // If the error is an OAuth authorization error, updates the state. Other errors are ignored.
+ if (error.domain == OIDOAuthTokenErrorDomain) {
+ [self updateWithAuthorizationError:error];
+ return;
+ }
+ if (!tokenResponse) {
+ return;
+ }
+
+ _lastTokenResponse = tokenResponse;
+
+ // updates the scope and refresh token if they are present on the TokenResponse.
+ // according to the spec, these may be changed by the server, including when refreshing the
+ // access token. See: https://tools.ietf.org/html/rfc6749#section-5.1 and
+ // https://tools.ietf.org/html/rfc6749#section-6
+ if (tokenResponse.scope) {
+ _scope = tokenResponse.scope;
+ }
+ if (tokenResponse.refreshToken) {
+ _refreshToken = tokenResponse.refreshToken;
+ }
+
+ [self didChangeState];
+}
+
+- (void)updateWithAuthorizationError:(NSError *)oauthError {
+ _authorizationError = oauthError;
+
+ [self didChangeState];
+
+ [_errorDelegate authState:self didEncounterAuthorizationError:oauthError];
+}
+
+#pragma mark - OAuth Requests
+
+- (OIDTokenRequest *)tokenRefreshRequest {
+ return [self tokenRefreshRequestWithAdditionalParameters:nil];
+}
+
+- (OIDTokenRequest *)tokenRefreshRequestWithAdditionalParameters:
+ (NSDictionary *)additionalParameters {
+
+ // TODO: Add unit test to confirm exception is thrown when expected
+
+ if (!_refreshToken) {
+ [OIDErrorUtilities raiseException:kRefreshTokenRequestException];
+ }
+ return [[OIDTokenRequest alloc]
+ initWithConfiguration:_lastAuthorizationResponse.request.configuration
+ grantType:OIDGrantTypeRefreshToken
+ authorizationCode:nil
+ redirectURL:nil
+ clientID:_lastAuthorizationResponse.request.clientID
+ clientSecret:_lastAuthorizationResponse.request.clientSecret
+ scope:nil
+ refreshToken:_refreshToken
+ codeVerifier:nil
+ additionalParameters:additionalParameters];
+}
+
+#pragma mark - Stateful Actions
+
+- (void)didChangeState {
+ [_stateChangeDelegate didChangeState:self];
+}
+
+- (void)setNeedsTokenRefresh {
+ _needsTokenRefresh = YES;
+}
+
+- (void)performActionWithFreshTokens:(OIDAuthStateAction)action {
+ [self performActionWithFreshTokens:action additionalRefreshParameters:nil];
+}
+
+- (void)performActionWithFreshTokens:(OIDAuthStateAction)action
+ additionalRefreshParameters:
+ (nullable NSDictionary *)additionalParameters {
+ [self performActionWithFreshTokens:action
+ additionalRefreshParameters:additionalParameters
+ dispatchQueue:dispatch_get_main_queue()];
+}
+
+- (void)performActionWithFreshTokens:(OIDAuthStateAction)action
+ additionalRefreshParameters:
+ (nullable NSDictionary *)additionalParameters
+ dispatchQueue:(dispatch_queue_t)dispatchQueue {
+
+ if ([self isTokenFresh]) {
+ // access token is valid within tolerance levels, perform action
+ dispatch_async(dispatchQueue, ^{
+ action(self.accessToken, self.idToken, nil);
+ });
+ return;
+ }
+
+ if (!_refreshToken) {
+ // no refresh token available and token has expired
+ NSError *tokenRefreshError = [
+ OIDErrorUtilities errorWithCode:OIDErrorCodeTokenRefreshError
+ underlyingError:nil
+ description:@"Unable to refresh expired token without a refresh token."];
+ dispatch_async(dispatchQueue, ^{
+ action(nil, nil, tokenRefreshError);
+ });
+ return;
+ }
+
+ // access token is expired, first refresh the token, then perform action
+ NSAssert(_pendingActionsSyncObject, @"_pendingActionsSyncObject cannot be nil", @"");
+ OIDAuthStatePendingAction* pendingAction =
+ [[OIDAuthStatePendingAction alloc] initWithAction:action andDispatchQueue:dispatchQueue];
+ @synchronized(_pendingActionsSyncObject) {
+ // if a token is already in the process of being refreshed, adds to pending actions
+ if (_pendingActions) {
+ [_pendingActions addObject:pendingAction];
+ return;
+ }
+
+ // creates a list of pending actions, starting with this one
+ _pendingActions = [NSMutableArray arrayWithObject:pendingAction];
+ }
+
+ // refresh the tokens
+ OIDTokenRequest *tokenRefreshRequest =
+ [self tokenRefreshRequestWithAdditionalParameters:additionalParameters];
+ [OIDAuthorizationService performTokenRequest:tokenRefreshRequest
+ originalAuthorizationResponse:_lastAuthorizationResponse
+ callback:^(OIDTokenResponse *_Nullable response,
+ NSError *_Nullable error) {
+ // update OIDAuthState based on response
+ if (response) {
+ self->_needsTokenRefresh = NO;
+ [self updateWithTokenResponse:response error:nil];
+ } else {
+ if (error.domain == OIDOAuthTokenErrorDomain) {
+ self->_needsTokenRefresh = NO;
+ [self updateWithAuthorizationError:error];
+ } else {
+ if ([self->_errorDelegate respondsToSelector:
+ @selector(authState:didEncounterTransientError:)]) {
+ [self->_errorDelegate authState:self didEncounterTransientError:error];
+ }
+ }
+ }
+
+ // nil the pending queue and process everything that was queued up
+ NSArray *actionsToProcess;
+ @synchronized(self->_pendingActionsSyncObject) {
+ actionsToProcess = self->_pendingActions;
+ self->_pendingActions = nil;
+ }
+ for (OIDAuthStatePendingAction* actionToProcess in actionsToProcess) {
+ dispatch_async(actionToProcess.dispatchQueue, ^{
+ actionToProcess.action(self.accessToken, self.idToken, error);
+ });
+ }
+ }];
+}
+
+#pragma mark -
+
+/*! @fn isTokenFresh
+ @brief Determines whether a token refresh request must be made to refresh the tokens.
+ */
+- (BOOL)isTokenFresh {
+ if (_needsTokenRefresh) {
+ // forced refresh
+ return NO;
+ }
+
+ if (!self.accessTokenExpirationDate) {
+ // if there is no expiration time but we have an access token, it is assumed to never expire
+ return !!self.accessToken;
+ }
+
+ // has the token expired?
+ BOOL tokenFresh = [self.accessTokenExpirationDate timeIntervalSinceNow] > kExpiryTimeTolerance;
+ return tokenFresh;
+}
+
+@end
+
+
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthStateChangeDelegate.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthStateChangeDelegate.h
new file mode 100644
index 0000000000..2570df131f
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthStateChangeDelegate.h
@@ -0,0 +1,39 @@
+/*! @file OIDAuthStateChangeDelegate.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+@class OIDAuthState;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @protocol OIDAuthStateChangeDelegate
+ @brief Delegate of the OIDAuthState used to monitor various changes in state.
+ */
+@protocol OIDAuthStateChangeDelegate
+
+/*! @brief Called when the authorization state changes and any backing storage needs to be updated.
+ @param state The @c OIDAuthState that changed.
+ @discussion If you are storing the authorization state, you should update the storage when the
+ state changes.
+ */
+- (void)didChangeState:(OIDAuthState *)state;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthStateErrorDelegate.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthStateErrorDelegate.h
new file mode 100644
index 0000000000..91a9b1cd00
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthStateErrorDelegate.h
@@ -0,0 +1,62 @@
+/*! @file OIDAuthStateErrorDelegate.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+@class OIDAuthState;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @protocol OIDAuthStateErrorDelegate
+ @brief Delegate of the OIDAuthState used to monitor errors.
+ */
+@protocol OIDAuthStateErrorDelegate
+
+/*! @brief Called when an authentication occurs, which indicates the auth session is invalid.
+ @param state The @c OIDAuthState on which the error occurred.
+ @param error The authorization error.
+ @discussion This is a hard error (not a transient network issue) that indicates a problem with
+ the authorization. You should stop using the @c OIDAuthState when such an error is
+ encountered. If the \NSError_code is @c ::OIDErrorCodeOAuthInvalidGrant then
+ the session may be recoverable with user interaction (i.e. re-authentication). In all cases
+ you should consider the user unauthorized, and remove locally cached resources that require
+ that authorization. @c OIDAuthState will call this method automatically if it encounters
+ an OAuth error (that is, an HTTP 400 response with a valid OAuth error response) during
+ authorization or token refresh (such as performed automatically when using
+ @c OIDAuthState.performActionWithFreshTokens:). You can signal authorization errors with
+ @c OIDAuthState.updateWithAuthorizationError:.
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+- (void)authState:(OIDAuthState *)state didEncounterAuthorizationError:(NSError *)error;
+
+@optional
+
+/*! @brief Called when a network or other transient error occurs.
+ @param state The @c OIDAuthState on which the error occurred.
+ @param error The transient error.
+ @discussion This is a soft error, typically network related. The @c OIDAuthState is likely
+ still valid, and should not be discarded. Retry the request using an incremental backoff
+ strategy. This is only called when using the @c OIDAuthState convenience methods such as
+ @c OIDAuthState.performActionWithFreshTokens:. If you are refreshing the tokens yourself
+ outside of @c OIDAuthState class, it will never be called.
+ */
+- (void)authState:(OIDAuthState *)state didEncounterTransientError:(NSError *)error;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationRequest.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationRequest.h
new file mode 100644
index 0000000000..594f01d876
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationRequest.h
@@ -0,0 +1,250 @@
+/*! @file OIDAuthorizationRequest.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+// These files only declare string constants useful for constructing a @c OIDAuthorizationRequest,
+// so they are imported here for convenience.
+#import "OIDExternalUserAgentRequest.h"
+#import "OIDResponseTypes.h"
+#import "OIDScopes.h"
+
+@class OIDServiceConfiguration;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief The @c code_challenge_method value for the S256 code challenge.
+ @see https://tools.ietf.org/html/rfc7636#section-4.3
+ */
+extern NSString *const OIDOAuthorizationRequestCodeChallengeMethodS256;
+
+
+/*! @brief Represents an authorization request.
+ @see https://tools.ietf.org/html/rfc6749#section-4
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.1
+ */
+@interface OIDAuthorizationRequest :
+ NSObject
+
+/*! @brief The service's configuration.
+ @remarks This configuration specifies how to connect to a particular OAuth provider.
+ Configurations may be created manually, or via an OpenID Connect Discovery Document.
+ */
+@property(nonatomic, readonly) OIDServiceConfiguration *configuration;
+
+/*! @brief The expected response type.
+ @remarks response_type
+ @discussion Generally 'code' if pure OAuth, otherwise a space-delimited list of of response
+ types including 'code', 'token', and 'id_token' for OpenID Connect.
+ @see https://tools.ietf.org/html/rfc6749#section-3.1.1
+ @see http://openid.net/specs/openid-connect-core-1_0.html#rfc.section.3
+ */
+@property(nonatomic, readonly) NSString *responseType;
+
+/*! @brief The client identifier.
+ @remarks client_id
+ @see https://tools.ietf.org/html/rfc6749#section-2.2
+ */
+@property(nonatomic, readonly) NSString *clientID;
+
+/*! @brief The client secret.
+ @remarks client_secret
+ @discussion The client secret is used to prove that identity of the client when exchaning an
+ authorization code for an access token.
+ The client secret is not passed in the authorizationRequestURL. It is only used when
+ exchanging the authorization code for an access token.
+ @see https://tools.ietf.org/html/rfc6749#section-2.3.1
+ */
+@property(nonatomic, readonly, nullable) NSString *clientSecret;
+
+/*! @brief The value of the scope parameter is expressed as a list of space-delimited,
+ case-sensitive strings.
+ @remarks scope
+ @see https://tools.ietf.org/html/rfc6749#section-3.3
+ */
+@property(nonatomic, readonly, nullable) NSString *scope;
+
+/*! @brief The client's redirect URI.
+ @remarks redirect_uri
+ @see https://tools.ietf.org/html/rfc6749#section-3.1.2
+ */
+@property(nonatomic, readonly, nullable) NSURL *redirectURL;
+
+/*! @brief An opaque value used by the client to maintain state between the request and callback.
+ @remarks state
+ @discussion If this value is not explicitly set, this library will automatically add state and
+ perform appropriate validation of the state in the authorization response. It is recommended
+ that the default implementation of this parameter be used wherever possible. Typically used
+ to prevent CSRF attacks, as recommended in RFC6819 Section 5.3.5.
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.1
+ @see https://tools.ietf.org/html/rfc6819#section-5.3.5
+ */
+@property(nonatomic, readonly, nullable) NSString *state;
+
+/*! @brief String value used to associate a Client session with an ID Token, and to mitigate replay
+ attacks. The value is passed through unmodified from the Authentication Request to the ID
+ Token. Sufficient entropy MUST be present in the nonce values used to prevent attackers from
+ guessing values.
+ @remarks nonce
+ @discussion If this value is not explicitly set, this library will automatically add nonce and
+ perform appropriate validation of the nonce in the ID Token.
+ @see https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
+ */
+@property(nonatomic, readonly, nullable) NSString *nonce;
+
+/*! @brief The PKCE code verifier.
+ @remarks code_verifier
+ @discussion The code verifier itself is not included in the authorization request that is sent
+ on the wire, but needs to be in the token exchange request.
+ @c OIDAuthorizationResponse.tokenExchangeRequest will create a @c OIDTokenRequest that
+ includes this parameter automatically.
+ @see https://tools.ietf.org/html/rfc7636#section-4.1
+ */
+@property(nonatomic, readonly, nullable) NSString *codeVerifier;
+
+/*! @brief The PKCE code challenge, derived from #codeVerifier.
+ @remarks code_challenge
+ @see https://tools.ietf.org/html/rfc7636#section-4.2
+ */
+@property(nonatomic, readonly, nullable) NSString *codeChallenge;
+
+/*! @brief The method used to compute the @c #codeChallenge
+ @remarks code_challenge_method
+ @see https://tools.ietf.org/html/rfc7636#section-4.3
+ */
+@property(nonatomic, readonly, nullable) NSString *codeChallengeMethod;
+
+/*! @brief The client's additional authorization parameters.
+ @see https://tools.ietf.org/html/rfc6749#section-3.1
+ */
+@property(nonatomic, readonly, nullable) NSDictionary *additionalParameters;
+
+/*! @internal
+ @brief Unavailable. Please use
+ @c initWithConfiguration:clientId:scopes:redirectURL:responseType:additionalParameters:.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @brief Creates an authorization request with opinionated defaults (a secure @c state, and
+ PKCE with S256 as the @c code_challenge_method).
+ @param configuration The service's configuration.
+ @param clientID The client identifier.
+ @param scopes An array of scopes to combine into a single scope string per the OAuth2 spec.
+ @param redirectURL The client's redirect URI.
+ @param responseType The expected response type.
+ @param additionalParameters The client's additional authorization parameters.
+ @remarks This convenience initializer generates a state parameter and PKCE challenges
+ automatically.
+ */
+- (instancetype)
+ initWithConfiguration:(OIDServiceConfiguration *)configuration
+ clientId:(NSString *)clientID
+ scopes:(nullable NSArray *)scopes
+ redirectURL:(NSURL *)redirectURL
+ responseType:(NSString *)responseType
+ additionalParameters:(nullable NSDictionary *)additionalParameters;
+
+/*! @brief Creates an authorization request with opinionated defaults (a secure @c state, @c nonce,
+ and PKCE with S256 as the @c code_challenge_method).
+ @param configuration The service's configuration.
+ @param clientID The client identifier.
+ @param clientSecret The client secret.
+ @param scopes An array of scopes to combine into a single scope string per the OAuth2 spec.
+ @param redirectURL The client's redirect URI.
+ @param responseType The expected response type.
+ @param additionalParameters The client's additional authorization parameters.
+ @remarks This convenience initializer generates a state parameter and PKCE challenges
+ automatically.
+ */
+- (instancetype)
+ initWithConfiguration:(OIDServiceConfiguration *)configuration
+ clientId:(NSString *)clientID
+ clientSecret:(nullable NSString *)clientSecret
+ scopes:(nullable NSArray *)scopes
+ redirectURL:(NSURL *)redirectURL
+ responseType:(NSString *)responseType
+ additionalParameters:(nullable NSDictionary *)additionalParameters;
+
+/*! @brief Designated initializer.
+ @param configuration The service's configuration.
+ @param clientID The client identifier.
+ @param scope A scope string per the OAuth2 spec (a space-delimited set of scopes).
+ @param redirectURL The client's redirect URI.
+ @param responseType The expected response type.
+ @param state An opaque value used by the client to maintain state between the request and
+ callback.
+ @param nonce String value used to associate a Client session with an ID Token. Can be set to nil
+ if not using OpenID Connect, although pure OAuth servers should ignore params they don't
+ understand anyway.
+ @param codeVerifier The PKCE code verifier. See @c OIDAuthorizationRequest.generateCodeVerifier.
+ @param codeChallenge The PKCE code challenge, calculated from the code verifier such as with
+ @c OIDAuthorizationRequest.codeChallengeS256ForVerifier:.
+ @param codeChallengeMethod The PKCE code challenge method.
+ ::OIDOAuthorizationRequestCodeChallengeMethodS256 when
+ @c OIDAuthorizationRequest.codeChallengeS256ForVerifier: is used to create the code
+ challenge.
+ @param additionalParameters The client's additional authorization parameters.
+ */
+- (instancetype)
+ initWithConfiguration:(OIDServiceConfiguration *)configuration
+ clientId:(NSString *)clientID
+ clientSecret:(nullable NSString *)clientSecret
+ scope:(nullable NSString *)scope
+ redirectURL:(nullable NSURL *)redirectURL
+ responseType:(NSString *)responseType
+ state:(nullable NSString *)state
+ nonce:(nullable NSString *)nonce
+ codeVerifier:(nullable NSString *)codeVerifier
+ codeChallenge:(nullable NSString *)codeChallenge
+ codeChallengeMethod:(nullable NSString *)codeChallengeMethod
+ additionalParameters:(nullable NSDictionary *)additionalParameters
+ NS_DESIGNATED_INITIALIZER;
+
+/*! @brief Constructs the request URI by adding the request parameters to the query component of the
+ authorization endpoint URI using the "application/x-www-form-urlencoded" format.
+ @return A URL representing the authorization request.
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.1
+ */
+- (NSURL *)authorizationRequestURL;
+
+/*! @brief Generates an OAuth state param using a random source.
+ @return The generated state.
+ @see https://tools.ietf.org/html/rfc6819#section-5.3.5
+ */
++ (nullable NSString *)generateState;
+
+/*! @brief Constructs a PKCE-compliant code verifier.
+ @return The generated code verifier.
+ @see https://tools.ietf.org/html/rfc7636#section-4.1
+ */
++ (nullable NSString *)generateCodeVerifier;
+
+/*! @brief Creates a PKCE S256 codeChallenge from the codeVerifier.
+ @param codeVerifier The code verifier from which the code challenge will be derived.
+ @return The generated code challenge.
+ @details Generate a secure code verifier to pass into this method with
+ @c OIDAuthorizationRequest.generateCodeVerifier. The matching @c #codeChallengeMethod for
+ @c #codeChallenge%s created by this method is
+ ::OIDOAuthorizationRequestCodeChallengeMethodS256.
+ @see https://tools.ietf.org/html/rfc7636#section-4.1
+ */
++ (nullable NSString *)codeChallengeS256ForVerifier:(nullable NSString *)codeVerifier;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationRequest.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationRequest.m
new file mode 100644
index 0000000000..ccfacda0fd
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationRequest.m
@@ -0,0 +1,351 @@
+/*! @file OIDAuthorizationRequest.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDAuthorizationRequest.h"
+
+#import "OIDDefines.h"
+#import "OIDScopeUtilities.h"
+#import "OIDServiceConfiguration.h"
+#import "OIDTokenUtilities.h"
+#import "OIDURLQueryComponent.h"
+
+/*! @brief The key for the @c configuration property for @c NSSecureCoding
+ */
+static NSString *const kConfigurationKey = @"configuration";
+
+/*! @brief Key used to encode the @c responseType property for @c NSSecureCoding, and on the URL
+ request.
+ */
+static NSString *const kResponseTypeKey = @"response_type";
+
+/*! @brief Key used to encode the @c clientID property for @c NSSecureCoding, and on the URL
+ request.
+ */
+static NSString *const kClientIDKey = @"client_id";
+
+/*! @brief Key used to encode the @c clientSecret property for @c NSSecureCoding.
+ */
+static NSString *const kClientSecretKey = @"client_secret";
+
+/*! @brief Key used to encode the @c scope property for @c NSSecureCoding, and on the URL request.
+ */
+static NSString *const kScopeKey = @"scope";
+
+/*! @brief Key used to encode the @c redirectURL property for @c NSSecureCoding, and on the URL
+ request.
+ */
+static NSString *const kRedirectURLKey = @"redirect_uri";
+
+/*! @brief Key used to encode the @c state property for @c NSSecureCoding, and on the URL request.
+ */
+static NSString *const kStateKey = @"state";
+
+/*! @brief Key used to encode the @c nonce property for @c NSSecureCoding, and on the URL request.
+ */
+static NSString *const kNonceKey = @"nonce";
+
+/*! @brief Key used to encode the @c codeVerifier property for @c NSSecureCoding.
+ */
+static NSString *const kCodeVerifierKey = @"code_verifier";
+
+/*! @brief Key used to send the @c codeChallenge on the URL request.
+ */
+static NSString *const kCodeChallengeKey = @"code_challenge";
+
+/*! @brief Key used to send the @c codeChallengeMethod on the URL request.
+ */
+static NSString *const kCodeChallengeMethodKey = @"code_challenge_method";
+
+/*! @brief Key used to encode the @c additionalParameters property for
+ @c NSSecureCoding
+ */
+static NSString *const kAdditionalParametersKey = @"additionalParameters";
+
+/*! @brief Number of random bytes generated for the @ state.
+ */
+static NSUInteger const kStateSizeBytes = 32;
+
+/*! @brief Number of random bytes generated for the @ codeVerifier.
+ */
+static NSUInteger const kCodeVerifierBytes = 32;
+
+/*! @brief Assertion text for unsupported response types.
+ */
+static NSString *const OIDOAuthUnsupportedResponseTypeMessage =
+ @"The response_type \"%@\" isn't supported. AppAuth only supports the \"code\" or \"code id_token\" response_type.";
+
+/*! @brief Code challenge request method.
+ */
+NSString *const OIDOAuthorizationRequestCodeChallengeMethodS256 = @"S256";
+
+@implementation OIDAuthorizationRequest
+
+- (instancetype)init
+ OID_UNAVAILABLE_USE_INITIALIZER(
+ @selector(initWithConfiguration:
+ clientId:
+ scopes:
+ redirectURL:
+ responseType:
+ additionalParameters:)
+ )
+
+/*! @brief Check if the response type is one AppAuth supports
+ @remarks AppAuth only supports the `code` and `code id_token` response types.
+ @see https://github.com/openid/AppAuth-iOS/issues/98
+ @see https://github.com/openid/AppAuth-iOS/issues/292
+ */
++ (BOOL)isSupportedResponseType:(NSString *)responseType
+{
+ NSString *codeIdToken = [@[OIDResponseTypeCode, OIDResponseTypeIDToken]
+ componentsJoinedByString:@" "];
+ NSString *idTokenCode = [@[OIDResponseTypeIDToken, OIDResponseTypeCode]
+ componentsJoinedByString:@" "];
+
+ return [responseType isEqualToString:OIDResponseTypeCode]
+ || [responseType isEqualToString:codeIdToken]
+ || [responseType isEqualToString:idTokenCode];
+}
+
+- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
+ clientId:(NSString *)clientID
+ clientSecret:(nullable NSString *)clientSecret
+ scope:(nullable NSString *)scope
+ redirectURL:(NSURL *)redirectURL
+ responseType:(NSString *)responseType
+ state:(nullable NSString *)state
+ nonce:(nullable NSString *)nonce
+ codeVerifier:(nullable NSString *)codeVerifier
+ codeChallenge:(nullable NSString *)codeChallenge
+ codeChallengeMethod:(nullable NSString *)codeChallengeMethod
+ additionalParameters:(nullable NSDictionary *)additionalParameters
+{
+ self = [super init];
+ if (self) {
+ _configuration = [configuration copy];
+ _clientID = [clientID copy];
+ _clientSecret = [clientSecret copy];
+ _scope = [scope copy];
+ _redirectURL = [redirectURL copy];
+ _responseType = [responseType copy];
+ if (![[self class] isSupportedResponseType:_responseType]) {
+ NSAssert(NO, OIDOAuthUnsupportedResponseTypeMessage, _responseType);
+ return nil;
+ }
+ _state = [state copy];
+ _nonce = [nonce copy];
+ _codeVerifier = [codeVerifier copy];
+ _codeChallenge = [codeChallenge copy];
+ _codeChallengeMethod = [codeChallengeMethod copy];
+
+ _additionalParameters =
+ [[NSDictionary alloc] initWithDictionary:additionalParameters copyItems:YES];
+ }
+ return self;
+}
+
+- (instancetype)
+ initWithConfiguration:(OIDServiceConfiguration *)configuration
+ clientId:(NSString *)clientID
+ clientSecret:(NSString *)clientSecret
+ scopes:(nullable NSArray *)scopes
+ redirectURL:(NSURL *)redirectURL
+ responseType:(NSString *)responseType
+ additionalParameters:(nullable NSDictionary *)additionalParameters {
+
+ // generates PKCE code verifier and challenge
+ NSString *codeVerifier = [[self class] generateCodeVerifier];
+ NSString *codeChallenge = [[self class] codeChallengeS256ForVerifier:codeVerifier];
+
+ return [self initWithConfiguration:configuration
+ clientId:clientID
+ clientSecret:clientSecret
+ scope:[OIDScopeUtilities scopesWithArray:scopes]
+ redirectURL:redirectURL
+ responseType:responseType
+ state:[[self class] generateState]
+ nonce:[[self class] generateState]
+ codeVerifier:codeVerifier
+ codeChallenge:codeChallenge
+ codeChallengeMethod:OIDOAuthorizationRequestCodeChallengeMethodS256
+ additionalParameters:additionalParameters];
+}
+
+- (instancetype)
+ initWithConfiguration:(OIDServiceConfiguration *)configuration
+ clientId:(NSString *)clientID
+ scopes:(nullable NSArray *)scopes
+ redirectURL:(NSURL *)redirectURL
+ responseType:(NSString *)responseType
+ additionalParameters:(nullable NSDictionary *)additionalParameters {
+ return [self initWithConfiguration:configuration
+ clientId:clientID
+ clientSecret:nil
+ scopes:scopes
+ redirectURL:redirectURL
+ responseType:responseType
+ additionalParameters:additionalParameters];
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(nullable NSZone *)zone {
+ // The documentation for NSCopying specifically advises us to return a reference to the original
+ // instance in the case where instances are immutable (as ours is):
+ // "Implement NSCopying by retaining the original instead of creating a new copy when the class
+ // and its contents are immutable."
+ return self;
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+ return YES;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+ OIDServiceConfiguration *configuration =
+ [aDecoder decodeObjectOfClass:[OIDServiceConfiguration class]
+ forKey:kConfigurationKey];
+ NSString *responseType = [aDecoder decodeObjectOfClass:[NSString class] forKey:kResponseTypeKey];
+ NSString *clientID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kClientIDKey];
+ NSString *clientSecret = [aDecoder decodeObjectOfClass:[NSString class] forKey:kClientSecretKey];
+ NSString *scope = [aDecoder decodeObjectOfClass:[NSString class] forKey:kScopeKey];
+ NSURL *redirectURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kRedirectURLKey];
+ NSString *state = [aDecoder decodeObjectOfClass:[NSString class] forKey:kStateKey];
+ NSString *nonce = [aDecoder decodeObjectOfClass:[NSString class] forKey:kNonceKey];
+ NSString *codeVerifier = [aDecoder decodeObjectOfClass:[NSString class] forKey:kCodeVerifierKey];
+ NSString *codeChallenge =
+ [aDecoder decodeObjectOfClass:[NSString class] forKey:kCodeChallengeKey];
+ NSString *codeChallengeMethod =
+ [aDecoder decodeObjectOfClass:[NSString class] forKey:kCodeChallengeMethodKey];
+ NSSet *additionalParameterCodingClasses = [NSSet setWithArray:@[
+ [NSDictionary class],
+ [NSString class]
+ ]];
+ NSDictionary *additionalParameters =
+ [aDecoder decodeObjectOfClasses:additionalParameterCodingClasses
+ forKey:kAdditionalParametersKey];
+
+ self = [self initWithConfiguration:configuration
+ clientId:clientID
+ clientSecret:clientSecret
+ scope:scope
+ redirectURL:redirectURL
+ responseType:responseType
+ state:state
+ nonce:nonce
+ codeVerifier:codeVerifier
+ codeChallenge:codeChallenge
+ codeChallengeMethod:codeChallengeMethod
+ additionalParameters:additionalParameters];
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+ [aCoder encodeObject:_configuration forKey:kConfigurationKey];
+ [aCoder encodeObject:_responseType forKey:kResponseTypeKey];
+ [aCoder encodeObject:_clientID forKey:kClientIDKey];
+ [aCoder encodeObject:_clientSecret forKey:kClientSecretKey];
+ [aCoder encodeObject:_scope forKey:kScopeKey];
+ [aCoder encodeObject:_redirectURL forKey:kRedirectURLKey];
+ [aCoder encodeObject:_state forKey:kStateKey];
+ [aCoder encodeObject:_nonce forKey:kNonceKey];
+ [aCoder encodeObject:_codeVerifier forKey:kCodeVerifierKey];
+ [aCoder encodeObject:_codeChallenge forKey:kCodeChallengeKey];
+ [aCoder encodeObject:_codeChallengeMethod forKey:kCodeChallengeMethodKey];
+ [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey];
+}
+
+#pragma mark - NSObject overrides
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@: %p, request: %@>",
+ NSStringFromClass([self class]),
+ (void *)self,
+ self.authorizationRequestURL];
+}
+
+#pragma mark - State and PKCE verifier/challenge generation Methods
+
++ (nullable NSString *)generateCodeVerifier {
+ return [OIDTokenUtilities randomURLSafeStringWithSize:kCodeVerifierBytes];
+}
+
++ (nullable NSString *)generateState {
+ return [OIDTokenUtilities randomURLSafeStringWithSize:kStateSizeBytes];
+}
+
++ (nullable NSString *)codeChallengeS256ForVerifier:(NSString *)codeVerifier {
+ if (!codeVerifier) {
+ return nil;
+ }
+ // generates the code_challenge per spec https://tools.ietf.org/html/rfc7636#section-4.2
+ // code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
+ // NB. the ASCII conversion on the code_verifier entropy was done at time of generation.
+ NSData *sha256Verifier = [OIDTokenUtilities sha256:codeVerifier];
+ return [OIDTokenUtilities encodeBase64urlNoPadding:sha256Verifier];
+}
+
+#pragma mark -
+
+- (NSURL *)authorizationRequestURL {
+ OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] init];
+
+ // Required parameters.
+ [query addParameter:kResponseTypeKey value:_responseType];
+ [query addParameter:kClientIDKey value:_clientID];
+
+ // Add any additional parameters the client has specified.
+ [query addParameters:_additionalParameters];
+
+ // Add optional parameters, as applicable.
+ if (_redirectURL) {
+ [query addParameter:kRedirectURLKey value:_redirectURL.absoluteString];
+ }
+ if (_scope) {
+ [query addParameter:kScopeKey value:_scope];
+ }
+ if (_state) {
+ [query addParameter:kStateKey value:_state];
+ }
+ if (_nonce) {
+ [query addParameter:kNonceKey value:_nonce];
+ }
+ if (_codeChallenge) {
+ [query addParameter:kCodeChallengeKey value:_codeChallenge];
+ }
+ if (_codeChallengeMethod) {
+ [query addParameter:kCodeChallengeMethodKey value:_codeChallengeMethod];
+ }
+
+ // Construct the URL:
+ return [query URLByReplacingQueryInURL:_configuration.authorizationEndpoint];
+}
+
+#pragma mark - OIDExternalUserAgentRequest
+
+- (NSURL *)externalUserAgentRequestURL {
+ return [self authorizationRequestURL];
+}
+
+- (NSString *)redirectScheme {
+ return [[self redirectURL] scheme];
+}
+
+@end
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationResponse.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationResponse.h
new file mode 100644
index 0000000000..e7552fe59b
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationResponse.h
@@ -0,0 +1,128 @@
+/*! @file OIDAuthorizationResponse.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+@class OIDAuthorizationRequest;
+@class OIDTokenRequest;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Represents the response to an authorization request.
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2
+ @see https://tools.ietf.org/html/rfc6749#section-5.1
+ @see http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthResponse
+ */
+@interface OIDAuthorizationResponse : NSObject
+
+/*! @brief The request which was serviced.
+ */
+@property(nonatomic, readonly) OIDAuthorizationRequest *request;
+
+/*! @brief The authorization code generated by the authorization server.
+ @discussion Set when the response_type requested includes 'code'.
+ @remarks code
+ */
+@property(nonatomic, readonly, nullable) NSString *authorizationCode;
+
+/*! @brief REQUIRED if the "state" parameter was present in the client authorization request. The
+ exact value received from the client.
+ @remarks state
+ */
+@property(nonatomic, readonly, nullable) NSString *state;
+
+/*! @brief The access token generated by the authorization server.
+ @discussion Set when the response_type requested includes 'token'.
+ @remarks access_token
+ @see http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthResponse
+ */
+@property(nonatomic, readonly, nullable) NSString *accessToken;
+
+/*! @brief The approximate expiration date & time of the access token.
+ @discussion Set when the response_type requested includes 'token'.
+ @remarks expires_in
+ @seealso OIDAuthorizationResponse.accessToken
+ @see http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthResponse
+ */
+@property(nonatomic, readonly, nullable) NSDate *accessTokenExpirationDate;
+
+/*! @brief Typically "Bearer" when present. Otherwise, another token_type value that the Client has
+ negotiated with the Authorization Server.
+ @discussion Set when the response_type requested includes 'token'.
+ @remarks token_type
+ @see http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthResponse
+ */
+@property(nonatomic, readonly, nullable) NSString *tokenType;
+
+/*! @brief ID Token value associated with the authenticated session.
+ @discussion Set when the response_type requested includes 'id_token'.
+ @remarks id_token
+ @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken
+ @see http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthResponse
+ */
+@property(nonatomic, readonly, nullable) NSString *idToken;
+
+/*! @brief The scope of the access token. OPTIONAL, if identical to the scopes requested, otherwise,
+ REQUIRED.
+ @remarks scope
+ @see https://tools.ietf.org/html/rfc6749#section-5.1
+ */
+@property(nonatomic, readonly, nullable) NSString *scope;
+
+/*! @brief Additional parameters returned from the authorization server.
+ */
+@property(nonatomic, readonly, nullable)
+ NSDictionary *> *additionalParameters;
+
+/*! @internal
+ @brief Unavailable. Please use initWithRequest:parameters:.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @brief Designated initializer.
+ @param request The serviced request.
+ @param parameters The decoded parameters returned from the Authorization Server.
+ @remarks Known parameters are extracted from the @c parameters parameter and the normative
+ properties are populated. Non-normative parameters are placed in the
+ @c #additionalParameters dictionary.
+ */
+- (instancetype)initWithRequest:(OIDAuthorizationRequest *)request
+ parameters:(NSDictionary *> *)parameters
+ NS_DESIGNATED_INITIALIZER;
+
+/*! @brief Creates a token request suitable for exchanging an authorization code for an access
+ token.
+ @return A @c OIDTokenRequest suitable for exchanging an authorization code for an access
+ token.
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.3
+ */
+- (nullable OIDTokenRequest *)tokenExchangeRequest;
+
+/*! @brief Creates a token request suitable for exchanging an authorization code for an access
+ token.
+ @param additionalParameters Additional parameters for the token request.
+ @return A @c OIDTokenRequest suitable for exchanging an authorization code for an access
+ token.
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.3
+ */
+- (nullable OIDTokenRequest *)tokenExchangeRequestWithAdditionalParameters:
+ (nullable NSDictionary *)additionalParameters;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationResponse.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationResponse.m
new file mode 100644
index 0000000000..a8f92c75e7
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationResponse.m
@@ -0,0 +1,210 @@
+/*! @file OIDAuthorizationResponse.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDAuthorizationResponse.h"
+
+#import "OIDAuthorizationRequest.h"
+#import "OIDDefines.h"
+#import "OIDError.h"
+#import "OIDFieldMapping.h"
+#import "OIDTokenRequest.h"
+#import "OIDTokenUtilities.h"
+
+/*! @brief The key for the @c authorizationCode property in the incoming parameters and for
+ @c NSSecureCoding.
+ */
+static NSString *const kAuthorizationCodeKey = @"code";
+
+/*! @brief The key for the @c state property in the incoming parameters and for @c NSSecureCoding.
+ */
+static NSString *const kStateKey = @"state";
+
+/*! @brief The key for the @c accessToken property in the incoming parameters and for
+ @c NSSecureCoding.
+ */
+static NSString *const kAccessTokenKey = @"access_token";
+
+/*! @brief The key for the @c accessTokenExpirationDate property in the incoming parameters and for
+ @c NSSecureCoding.
+ */
+static NSString *const kExpiresInKey = @"expires_in";
+
+/*! @brief The key for the @c tokenType property in the incoming parameters and for
+ @c NSSecureCoding.
+ */
+static NSString *const kTokenTypeKey = @"token_type";
+
+/*! @brief The key for the @c idToken property in the incoming parameters and for @c NSSecureCoding.
+ */
+static NSString *const kIDTokenKey = @"id_token";
+
+/*! @brief The key for the @c scope property in the incoming parameters and for @c NSSecureCoding.
+ */
+static NSString *const kScopeKey = @"scope";
+
+/*! @brief Key used to encode the @c additionalParameters property for @c NSSecureCoding
+ */
+static NSString *const kAdditionalParametersKey = @"additionalParameters";
+
+/*! @brief Key used to encode the @c request property for @c NSSecureCoding
+ */
+static NSString *const kRequestKey = @"request";
+
+/*! @brief The exception thrown when a developer tries to create a token exchange request from an
+ authorization request with no authorization code.
+ */
+static NSString *const kTokenExchangeRequestException =
+ @"Attempted to create a token exchange request from an authorization response with no "
+ "authorization code.";
+
+@implementation OIDAuthorizationResponse
+
+/*! @brief Returns a mapping of incoming parameters to instance variables.
+ @return A mapping of incoming parameters to instance variables.
+ */
++ (NSDictionary *)fieldMap {
+ static NSMutableDictionary *fieldMap;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ fieldMap = [NSMutableDictionary dictionary];
+ fieldMap[kStateKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_state" type:[NSString class]];
+ fieldMap[kAuthorizationCodeKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_authorizationCode" type:[NSString class]];
+ fieldMap[kAccessTokenKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_accessToken" type:[NSString class]];
+ fieldMap[kExpiresInKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_accessTokenExpirationDate"
+ type:[NSDate class]
+ conversion:^id _Nullable(NSObject *_Nullable value) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ return value;
+ }
+ NSNumber *valueAsNumber = (NSNumber *)value;
+ return [NSDate dateWithTimeIntervalSinceNow:[valueAsNumber longLongValue]];
+ }];
+ fieldMap[kTokenTypeKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_tokenType" type:[NSString class]];
+ fieldMap[kIDTokenKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_idToken" type:[NSString class]];
+ fieldMap[kScopeKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_scope" type:[NSString class]];
+ });
+ return fieldMap;
+}
+
+#pragma mark - Initializers
+
+- (instancetype)init
+ OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithRequest:parameters:))
+
+- (instancetype)initWithRequest:(OIDAuthorizationRequest *)request
+ parameters:(NSDictionary *> *)parameters {
+ self = [super init];
+ if (self) {
+ _request = [request copy];
+ NSDictionary *> *additionalParameters =
+ [OIDFieldMapping remainingParametersWithMap:[[self class] fieldMap]
+ parameters:parameters
+ instance:self];
+ _additionalParameters = additionalParameters;
+ }
+ return self;
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(nullable NSZone *)zone {
+ // The documentation for NSCopying specifically advises us to return a reference to the original
+ // instance in the case where instances are immutable (as ours is):
+ // "Implement NSCopying by retaining the original instead of creating a new copy when the class
+ // and its contents are immutable."
+ return self;
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+ return YES;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+ OIDAuthorizationRequest *request =
+ [aDecoder decodeObjectOfClass:[OIDAuthorizationRequest class] forKey:kRequestKey];
+ self = [self initWithRequest:request parameters:@{ }];
+ if (self) {
+ [OIDFieldMapping decodeWithCoder:aDecoder map:[[self class] fieldMap] instance:self];
+ _additionalParameters = [aDecoder decodeObjectOfClasses:[OIDFieldMapping JSONTypes]
+ forKey:kAdditionalParametersKey];
+ }
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+ [aCoder encodeObject:_request forKey:kRequestKey];
+ [OIDFieldMapping encodeWithCoder:aCoder map:[[self class] fieldMap] instance:self];
+ [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey];
+}
+
+#pragma mark - NSObject overrides
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@: %p, authorizationCode: %@, state: \"%@\", accessToken: "
+ "\"%@\", accessTokenExpirationDate: %@, tokenType: %@, "
+ "idToken: \"%@\", scope: \"%@\", additionalParameters: %@, "
+ "request: %@>",
+ NSStringFromClass([self class]),
+ (void *)self,
+ _authorizationCode,
+ _state,
+ [OIDTokenUtilities redact:_accessToken],
+ _accessTokenExpirationDate,
+ _tokenType,
+ [OIDTokenUtilities redact:_idToken],
+ _scope,
+ _additionalParameters,
+ _request];
+}
+
+#pragma mark -
+
+- (OIDTokenRequest *)tokenExchangeRequest {
+ return [self tokenExchangeRequestWithAdditionalParameters:nil];
+}
+
+- (OIDTokenRequest *)tokenExchangeRequestWithAdditionalParameters:
+ (NSDictionary *)additionalParameters {
+ // TODO: add a unit test to confirm exception is thrown when expected and the request is created
+ // with the correct parameters.
+ if (!_authorizationCode) {
+ [NSException raise:kTokenExchangeRequestException
+ format:kTokenExchangeRequestException];
+ }
+ return [[OIDTokenRequest alloc] initWithConfiguration:_request.configuration
+ grantType:OIDGrantTypeAuthorizationCode
+ authorizationCode:_authorizationCode
+ redirectURL:_request.redirectURL
+ clientID:_request.clientID
+ clientSecret:_request.clientSecret
+ scope:nil
+ refreshToken:nil
+ codeVerifier:_request.codeVerifier
+ additionalParameters:additionalParameters];
+}
+
+@end
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationService.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationService.h
new file mode 100644
index 0000000000..c8fee5358d
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationService.h
@@ -0,0 +1,170 @@
+/*! @file OIDAuthorizationService.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+@class OIDAuthorization;
+@class OIDAuthorizationRequest;
+@class OIDAuthorizationResponse;
+@class OIDEndSessionRequest;
+@class OIDEndSessionResponse;
+@class OIDRegistrationRequest;
+@class OIDRegistrationResponse;
+@class OIDServiceConfiguration;
+@class OIDTokenRequest;
+@class OIDTokenResponse;
+@protocol OIDExternalUserAgent;
+@protocol OIDExternalUserAgentSession;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Represents the type of block used as a callback for creating a service configuration from
+ a remote OpenID Connect Discovery document.
+ @param configuration The service configuration, if available.
+ @param error The error if an error occurred.
+ */
+typedef void (^OIDDiscoveryCallback)(OIDServiceConfiguration *_Nullable configuration,
+ NSError *_Nullable error);
+
+/*! @brief Represents the type of block used as a callback for various methods of
+ @c OIDAuthorizationService.
+ @param authorizationResponse The authorization response, if available.
+ @param error The error if an error occurred.
+ */
+typedef void (^OIDAuthorizationCallback)(OIDAuthorizationResponse *_Nullable authorizationResponse,
+ NSError *_Nullable error);
+
+/*! @brief Block used as a callback for the end-session request of @c OIDAuthorizationService.
+ @param endSessionResponse The end-session response, if available.
+ @param error The error if an error occurred.
+ */
+typedef void (^OIDEndSessionCallback)(OIDEndSessionResponse *_Nullable endSessionResponse,
+ NSError *_Nullable error);
+
+/*! @brief Represents the type of block used as a callback for various methods of
+ @c OIDAuthorizationService.
+ @param tokenResponse The token response, if available.
+ @param error The error if an error occurred.
+ */
+typedef void (^OIDTokenCallback)(OIDTokenResponse *_Nullable tokenResponse,
+ NSError *_Nullable error);
+
+/*! @brief Represents the type of dictionary used to specify additional querystring parameters
+ when making authorization or token endpoint requests.
+ */
+typedef NSDictionary *_Nullable OIDTokenEndpointParameters;
+
+/*! @brief Represents the type of block used as a callback for various methods of
+ @c OIDAuthorizationService.
+ @param registrationResponse The registration response, if available.
+ @param error The error if an error occurred.
+*/
+typedef void (^OIDRegistrationCompletion)(OIDRegistrationResponse *_Nullable registrationResponse,
+ NSError *_Nullable error);
+
+/*! @brief Performs various OAuth and OpenID Connect related calls via the user agent or
+ \NSURLSession.
+ */
+@interface OIDAuthorizationService : NSObject
+
+/*! @brief The service's configuration.
+ @remarks Each authorization service is initialized with a configuration. This configuration
+ specifies how to connect to a particular OAuth provider. Clients should use separate
+ authorization service instances for each provider they wish to integrate with.
+ Configurations may be created manually, or via an OpenID Connect Discovery Document.
+ */
+@property(nonatomic, readonly) OIDServiceConfiguration *configuration;
+
+/*! @internal
+ @brief Unavailable. This class should not be initialized.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @brief Convenience method for creating an authorization service configuration from an OpenID
+ Connect compliant issuer URL.
+ @param issuerURL The service provider's OpenID Connect issuer.
+ @param completion A block which will be invoked when the authorization service configuration has
+ been created, or when an error has occurred.
+ @see https://openid.net/specs/openid-connect-discovery-1_0.html
+ */
++ (void)discoverServiceConfigurationForIssuer:(NSURL *)issuerURL
+ completion:(OIDDiscoveryCallback)completion;
+
+
+/*! @brief Convenience method for creating an authorization service configuration from an OpenID
+ Connect compliant identity provider's discovery document.
+ @param discoveryURL The URL of the service provider's OpenID Connect discovery document.
+ @param completion A block which will be invoked when the authorization service configuration has
+ been created, or when an error has occurred.
+ @see https://openid.net/specs/openid-connect-discovery-1_0.html
+ */
++ (void)discoverServiceConfigurationForDiscoveryURL:(NSURL *)discoveryURL
+ completion:(OIDDiscoveryCallback)completion;
+
+/*! @brief Perform an authorization flow using a generic flow shim.
+ @param request The authorization request.
+ @param externalUserAgent Generic external user-agent that can present an 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
+ externalUserAgent:(id)externalUserAgent
+ callback:(OIDAuthorizationCallback)callback;
+
+/*! @brief Perform a logout request.
+ @param request The end-session logout request.
+ @param externalUserAgent Generic external user-agent that can present user-agent requests.
+ @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.
+ @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout
+ */
++ (id)
+ presentEndSessionRequest:(OIDEndSessionRequest *)request
+ externalUserAgent:(id)externalUserAgent
+ callback:(OIDEndSessionCallback)callback;
+
+/*! @brief Performs a token request.
+ @param request The token request.
+ @param callback The method called when the request has completed or failed.
+ */
++ (void)performTokenRequest:(OIDTokenRequest *)request callback:(OIDTokenCallback)callback;
+
+/*! @brief Performs a token request.
+ @param request The token request.
+ @param authorizationResponse The original authorization response related to this token request.
+ @param callback The method called when the request has completed or failed.
+ */
++ (void)performTokenRequest:(OIDTokenRequest *)request
+ originalAuthorizationResponse:(OIDAuthorizationResponse *_Nullable)authorizationResponse
+ callback:(OIDTokenCallback)callback;
+
+/*! @brief Performs a registration request.
+ @param request The registration request.
+ @param completion The method called when the request has completed or failed.
+ */
++ (void)performRegistrationRequest:(OIDRegistrationRequest *)request
+ completion:(OIDRegistrationCompletion)completion;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationService.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationService.m
new file mode 100644
index 0000000000..cc749a3f9d
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDAuthorizationService.m
@@ -0,0 +1,790 @@
+/*! @file OIDAuthorizationService.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDAuthorizationService.h"
+
+#import "OIDAuthorizationRequest.h"
+#import "OIDAuthorizationResponse.h"
+#import "OIDDefines.h"
+#import "OIDEndSessionRequest.h"
+#import "OIDEndSessionResponse.h"
+#import "OIDErrorUtilities.h"
+#import "OIDExternalUserAgent.h"
+#import "OIDExternalUserAgentSession.h"
+#import "OIDIDToken.h"
+#import "OIDRegistrationRequest.h"
+#import "OIDRegistrationResponse.h"
+#import "OIDServiceConfiguration.h"
+#import "OIDServiceDiscovery.h"
+#import "OIDTokenRequest.h"
+#import "OIDTokenResponse.h"
+#import "OIDURLQueryComponent.h"
+#import "OIDURLSessionProvider.h"
+
+/*! @brief Path appended to an OpenID Connect issuer for discovery
+ @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig
+ */
+static NSString *const kOpenIDConfigurationWellKnownPath = @".well-known/openid-configuration";
+
+/*! @brief Max allowable iat (Issued At) time skew
+ @see https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
+ */
+static int const kOIDAuthorizationSessionIATMaxSkew = 600;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OIDAuthorizationSession : NSObject
+
+- (instancetype)init NS_UNAVAILABLE;
+
+- (instancetype)initWithRequest:(OIDAuthorizationRequest *)request
+ NS_DESIGNATED_INITIALIZER;
+
+@end
+
+@implementation OIDAuthorizationSession {
+ OIDAuthorizationRequest *_request;
+ id _externalUserAgent;
+ OIDAuthorizationCallback _pendingauthorizationFlowCallback;
+}
+
+- (instancetype)initWithRequest:(OIDAuthorizationRequest *)request {
+ self = [super init];
+ if (self) {
+ _request = [request copy];
+ }
+ return self;
+}
+
+- (void)presentAuthorizationWithExternalUserAgent:(id)externalUserAgent
+ callback:(OIDAuthorizationCallback)authorizationFlowCallback {
+ _externalUserAgent = externalUserAgent;
+ _pendingauthorizationFlowCallback = authorizationFlowCallback;
+ BOOL authorizationFlowStarted =
+ [_externalUserAgent presentExternalUserAgentRequest:_request session:self];
+ if (!authorizationFlowStarted) {
+ NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeSafariOpenError
+ underlyingError:nil
+ description:@"Unable to open Safari."];
+ [self didFinishWithResponse:nil error:safariError];
+ }
+}
+
+- (void)cancel {
+ [self cancelWithCompletion:nil];
+}
+
+- (void)cancelWithCompletion:(nullable void (^)(void))completion {
+ [_externalUserAgent dismissExternalUserAgentAnimated:YES completion:^{
+ NSError *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
+ underlyingError:nil
+ description:@"Authorization flow was cancelled."];
+ [self didFinishWithResponse:nil error:error];
+ if (completion) completion();
+ }];
+}
+
+/*! @brief Does the redirection URL equal another URL down to the path component?
+ @param URL The first redirect URI to compare.
+ @param redirectionURL The second redirect URI to compare.
+ @return YES if the URLs match down to the path level (query params are ignored).
+ */
++ (BOOL)URL:(NSURL *)URL matchesRedirectionURL:(NSURL *)redirectionURL {
+ NSURL *standardizedURL = [URL standardizedURL];
+ NSURL *standardizedRedirectURL = [redirectionURL standardizedURL];
+
+ return [standardizedURL.scheme caseInsensitiveCompare:standardizedRedirectURL.scheme] == NSOrderedSame
+ && OIDIsEqualIncludingNil(standardizedURL.user, standardizedRedirectURL.user)
+ && OIDIsEqualIncludingNil(standardizedURL.password, standardizedRedirectURL.password)
+ && OIDIsEqualIncludingNil(standardizedURL.host, standardizedRedirectURL.host)
+ && OIDIsEqualIncludingNil(standardizedURL.port, standardizedRedirectURL.port)
+ && OIDIsEqualIncludingNil(standardizedURL.path, standardizedRedirectURL.path);
+}
+
+- (BOOL)shouldHandleURL:(NSURL *)URL {
+ return [[self class] URL:URL matchesRedirectionURL:_request.redirectURL];
+}
+
+- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL {
+ // rejects URLs that don't match redirect (these may be completely unrelated to the authorization)
+ if (![self shouldHandleURL:URL]) {
+ return NO;
+ }
+
+ AppAuthRequestTrace(@"Authorization Response: %@", URL);
+
+ // checks for an invalid state
+ if (!_pendingauthorizationFlowCallback) {
+ [NSException raise:OIDOAuthExceptionInvalidAuthorizationFlow
+ format:@"%@", OIDOAuthExceptionInvalidAuthorizationFlow, nil];
+ }
+
+ OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] initWithURL:URL];
+
+ NSError *error;
+ OIDAuthorizationResponse *response = nil;
+
+ // checks for an OAuth error response as per RFC6749 Section 4.1.2.1
+ if (query.dictionaryValue[OIDOAuthErrorFieldError]) {
+ error = [OIDErrorUtilities OAuthErrorWithDomain:OIDOAuthAuthorizationErrorDomain
+ OAuthResponse:query.dictionaryValue
+ underlyingError:nil];
+ }
+
+ // no error, should be a valid OAuth 2.0 response
+ if (!error) {
+ response = [[OIDAuthorizationResponse alloc] initWithRequest:_request
+ parameters:query.dictionaryValue];
+
+ // verifies that the state in the response matches the state in the request, or both are nil
+ if (!OIDIsEqualIncludingNil(_request.state, response.state)) {
+ NSMutableDictionary *userInfo = [query.dictionaryValue mutableCopy];
+ userInfo[NSLocalizedDescriptionKey] =
+ [NSString stringWithFormat:@"State mismatch, expecting %@ but got %@ in authorization "
+ "response %@",
+ _request.state,
+ response.state,
+ response];
+ response = nil;
+ error = [NSError errorWithDomain:OIDOAuthAuthorizationErrorDomain
+ code:OIDErrorCodeOAuthAuthorizationClientError
+ userInfo:userInfo];
+ }
+ }
+
+ [_externalUserAgent dismissExternalUserAgentAnimated:YES completion:^{
+ [self didFinishWithResponse:response error:error];
+ }];
+
+ return YES;
+}
+
+- (void)failExternalUserAgentFlowWithError:(NSError *)error {
+ [self didFinishWithResponse:nil error:error];
+}
+
+/*! @brief Invokes the pending callback and performs cleanup.
+ @param response The authorization response, if any to return to the callback.
+ @param error The error, if any, to return to the callback.
+ */
+- (void)didFinishWithResponse:(nullable OIDAuthorizationResponse *)response
+ error:(nullable NSError *)error {
+ OIDAuthorizationCallback callback = _pendingauthorizationFlowCallback;
+ _pendingauthorizationFlowCallback = nil;
+ _externalUserAgent = nil;
+ if (callback) {
+ callback(response, error);
+ }
+}
+
+@end
+
+@interface OIDEndSessionImplementation : NSObject {
+ // private variables
+ OIDEndSessionRequest *_request;
+ id _externalUserAgent;
+ OIDEndSessionCallback _pendingEndSessionCallback;
+}
+- (instancetype)init NS_UNAVAILABLE;
+
+- (instancetype)initWithRequest:(OIDEndSessionRequest *)request
+ NS_DESIGNATED_INITIALIZER;
+@end
+
+
+@implementation OIDEndSessionImplementation
+
+- (instancetype)initWithRequest:(OIDEndSessionRequest *)request {
+ self = [super init];
+ if (self) {
+ _request = [request copy];
+ }
+ return self;
+}
+
+- (void)presentAuthorizationWithExternalUserAgent:(id)externalUserAgent
+ callback:(OIDEndSessionCallback)authorizationFlowCallback {
+ _externalUserAgent = externalUserAgent;
+ _pendingEndSessionCallback = authorizationFlowCallback;
+ BOOL authorizationFlowStarted =
+ [_externalUserAgent presentExternalUserAgentRequest:_request session:self];
+ if (!authorizationFlowStarted) {
+ NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeSafariOpenError
+ underlyingError:nil
+ description:@"Unable to open Safari."];
+ [self didFinishWithResponse:nil error:safariError];
+ }
+}
+
+- (void)cancel {
+ [self cancelWithCompletion:nil];
+}
+
+- (void)cancelWithCompletion:(nullable void (^)(void))completion {
+ [_externalUserAgent dismissExternalUserAgentAnimated:YES completion:^{
+ NSError *error = [OIDErrorUtilities
+ errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
+ underlyingError:nil
+ description:nil];
+ [self didFinishWithResponse:nil error:error];
+ if (completion) completion();
+ }];
+}
+
+- (BOOL)shouldHandleURL:(NSURL *)URL {
+ // The logic of when to handle the URL is the same as for authorization requests: should match
+ // down to the path component.
+ return [[OIDAuthorizationSession class] URL:URL
+ matchesRedirectionURL:_request.postLogoutRedirectURL];
+}
+
+- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL {
+ // rejects URLs that don't match redirect (these may be completely unrelated to the authorization)
+ if (![self shouldHandleURL:URL]) {
+ return NO;
+ }
+ // checks for an invalid state
+ if (!_pendingEndSessionCallback) {
+ [NSException raise:OIDOAuthExceptionInvalidAuthorizationFlow
+ format:@"%@", OIDOAuthExceptionInvalidAuthorizationFlow, nil];
+ }
+
+
+ NSError *error;
+ OIDEndSessionResponse *response = nil;
+
+ OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] initWithURL:URL];
+ response = [[OIDEndSessionResponse alloc] initWithRequest:_request
+ parameters:query.dictionaryValue];
+
+ // verifies that the state in the response matches the state in the request, or both are nil
+ if (!OIDIsEqualIncludingNil(_request.state, response.state)) {
+ NSMutableDictionary *userInfo = [query.dictionaryValue mutableCopy];
+ userInfo[NSLocalizedDescriptionKey] =
+ [NSString stringWithFormat:@"State mismatch, expecting %@ but got %@ in authorization "
+ "response %@",
+ _request.state,
+ response.state,
+ response];
+ response = nil;
+ error = [NSError errorWithDomain:OIDOAuthAuthorizationErrorDomain
+ code:OIDErrorCodeOAuthAuthorizationClientError
+ userInfo:userInfo];
+ }
+
+ [_externalUserAgent dismissExternalUserAgentAnimated:YES completion:^{
+ [self didFinishWithResponse:response error:error];
+ }];
+
+ return YES;
+}
+
+- (void)failExternalUserAgentFlowWithError:(NSError *)error {
+ [self didFinishWithResponse:nil error:error];
+}
+
+/*! @brief Invokes the pending callback and performs cleanup.
+ @param response The authorization response, if any to return to the callback.
+ @param error The error, if any, to return to the callback.
+ */
+- (void)didFinishWithResponse:(nullable OIDEndSessionResponse *)response
+ error:(nullable NSError *)error {
+ OIDEndSessionCallback callback = _pendingEndSessionCallback;
+ _pendingEndSessionCallback = nil;
+ _externalUserAgent = nil;
+ if (callback) {
+ callback(response, error);
+ }
+}
+
+@end
+
+@implementation OIDAuthorizationService
+
++ (void)discoverServiceConfigurationForIssuer:(NSURL *)issuerURL
+ completion:(OIDDiscoveryCallback)completion {
+ NSURL *fullDiscoveryURL =
+ [issuerURL URLByAppendingPathComponent:kOpenIDConfigurationWellKnownPath];
+
+ [[self class] discoverServiceConfigurationForDiscoveryURL:fullDiscoveryURL
+ completion:completion];
+}
+
++ (void)discoverServiceConfigurationForDiscoveryURL:(NSURL *)discoveryURL
+ completion:(OIDDiscoveryCallback)completion {
+
+ NSURLSession *session = [OIDURLSessionProvider session];
+ NSURLSessionDataTask *task =
+ [session dataTaskWithURL:discoveryURL
+ completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
+ // If we got any sort of error, just report it.
+ if (error || !data) {
+ NSString *errorDescription =
+ [NSString stringWithFormat:@"Connection error fetching discovery document '%@': %@.",
+ discoveryURL,
+ error.localizedDescription];
+ error = [OIDErrorUtilities errorWithCode:OIDErrorCodeNetworkError
+ underlyingError:error
+ description:errorDescription];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(nil, error);
+ });
+ return;
+ }
+
+ NSHTTPURLResponse *urlResponse = (NSHTTPURLResponse *)response;
+
+ // Check for non-200 status codes.
+ // https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse
+ if (urlResponse.statusCode != 200) {
+ NSError *URLResponseError = [OIDErrorUtilities HTTPErrorWithHTTPResponse:urlResponse
+ data:data];
+ NSString *errorDescription =
+ [NSString stringWithFormat:@"Non-200 HTTP response (%d) fetching discovery document "
+ "'%@'.",
+ (int)urlResponse.statusCode,
+ discoveryURL];
+ error = [OIDErrorUtilities errorWithCode:OIDErrorCodeNetworkError
+ underlyingError:URLResponseError
+ description:errorDescription];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(nil, error);
+ });
+ return;
+ }
+
+ // Construct an OIDServiceDiscovery with the received JSON.
+ OIDServiceDiscovery *discovery =
+ [[OIDServiceDiscovery alloc] initWithJSONData:data error:&error];
+ if (error || !discovery) {
+ NSString *errorDescription =
+ [NSString stringWithFormat:@"JSON error parsing document at '%@': %@",
+ discoveryURL,
+ error.localizedDescription];
+ error = [OIDErrorUtilities errorWithCode:OIDErrorCodeNetworkError
+ underlyingError:error
+ description:errorDescription];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(nil, error);
+ });
+ return;
+ }
+
+ // Create our service configuration with the discovery document and return it.
+ OIDServiceConfiguration *configuration =
+ [[OIDServiceConfiguration alloc] initWithDiscoveryDocument:discovery];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(configuration, nil);
+ });
+ }];
+ [task resume];
+}
+
+#pragma mark - Authorization Endpoint
+
++ (id) presentAuthorizationRequest:(OIDAuthorizationRequest *)request
+ externalUserAgent:(id)externalUserAgent
+ callback:(OIDAuthorizationCallback)callback {
+
+ AppAuthRequestTrace(@"Authorization Request: %@", request);
+
+ OIDAuthorizationSession *flowSession = [[OIDAuthorizationSession alloc] initWithRequest:request];
+ [flowSession presentAuthorizationWithExternalUserAgent:externalUserAgent callback:callback];
+ return flowSession;
+}
+
++ (id)
+ presentEndSessionRequest:(OIDEndSessionRequest *)request
+ externalUserAgent:(id)externalUserAgent
+ callback:(OIDEndSessionCallback)callback {
+ OIDEndSessionImplementation *flowSession =
+ [[OIDEndSessionImplementation alloc] initWithRequest:request];
+ [flowSession presentAuthorizationWithExternalUserAgent:externalUserAgent callback:callback];
+ return flowSession;
+}
+
+#pragma mark - Token Endpoint
+
++ (void)performTokenRequest:(OIDTokenRequest *)request callback:(OIDTokenCallback)callback {
+ [[self class] performTokenRequest:request
+ originalAuthorizationResponse:nil
+ callback:callback];
+}
+
++ (void)performTokenRequest:(OIDTokenRequest *)request
+ originalAuthorizationResponse:(OIDAuthorizationResponse *_Nullable)authorizationResponse
+ callback:(OIDTokenCallback)callback {
+
+ NSURLRequest *URLRequest = [request URLRequest];
+
+ AppAuthRequestTrace(@"Token Request: %@\nHeaders:%@\nHTTPBody: %@",
+ URLRequest.URL,
+ URLRequest.allHTTPHeaderFields,
+ [[NSString alloc] initWithData:URLRequest.HTTPBody
+ encoding:NSUTF8StringEncoding]);
+
+ NSURLSession *session = [OIDURLSessionProvider session];
+ [[session dataTaskWithRequest:URLRequest
+ completionHandler:^(NSData *_Nullable data,
+ NSURLResponse *_Nullable response,
+ NSError *_Nullable error) {
+ if (error) {
+ // A network error or server error occurred.
+ NSString *errorDescription =
+ [NSString stringWithFormat:@"Connection error making token request to '%@': %@.",
+ URLRequest.URL,
+ error.localizedDescription];
+ NSError *returnedError =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeNetworkError
+ underlyingError:error
+ description:errorDescription];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(nil, returnedError);
+ });
+ return;
+ }
+
+ NSHTTPURLResponse *HTTPURLResponse = (NSHTTPURLResponse *)response;
+ NSInteger statusCode = HTTPURLResponse.statusCode;
+ AppAuthRequestTrace(@"Token Response: HTTP Status %d\nHTTPBody: %@",
+ (int)statusCode,
+ [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
+ if (statusCode != 200) {
+ // A server error occurred.
+ NSError *serverError =
+ [OIDErrorUtilities HTTPErrorWithHTTPResponse:HTTPURLResponse data:data];
+
+ // HTTP 4xx may indicate an RFC6749 Section 5.2 error response, attempts to parse as such.
+ if (statusCode >= 400 && statusCode < 500) {
+ NSError *jsonDeserializationError;
+ NSDictionary *> *json =
+ [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonDeserializationError];
+
+ // If the HTTP 4xx response parses as JSON and has an 'error' key, it's an OAuth error.
+ // These errors are special as they indicate a problem with the authorization grant.
+ if (json[OIDOAuthErrorFieldError]) {
+ NSError *oauthError =
+ [OIDErrorUtilities OAuthErrorWithDomain:OIDOAuthTokenErrorDomain
+ OAuthResponse:json
+ underlyingError:serverError];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(nil, oauthError);
+ });
+ return;
+ }
+ }
+
+ // Status code indicates this is an error, but not an RFC6749 Section 5.2 error.
+ NSString *errorDescription =
+ [NSString stringWithFormat:@"Non-200 HTTP response (%d) making token request to '%@'.",
+ (int)statusCode,
+ URLRequest.URL];
+ NSError *returnedError =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeServerError
+ underlyingError:serverError
+ description:errorDescription];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(nil, returnedError);
+ });
+ return;
+ }
+
+ NSError *jsonDeserializationError;
+ NSDictionary *> *json =
+ [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonDeserializationError];
+ if (jsonDeserializationError) {
+ // A problem occurred deserializing the response/JSON.
+ NSString *errorDescription =
+ [NSString stringWithFormat:@"JSON error parsing token response: %@",
+ jsonDeserializationError.localizedDescription];
+ NSError *returnedError =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeJSONDeserializationError
+ underlyingError:jsonDeserializationError
+ description:errorDescription];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(nil, returnedError);
+ });
+ return;
+ }
+
+ OIDTokenResponse *tokenResponse =
+ [[OIDTokenResponse alloc] initWithRequest:request parameters:json];
+ if (!tokenResponse) {
+ // A problem occurred constructing the token response from the JSON.
+ NSError *returnedError =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeTokenResponseConstructionError
+ underlyingError:jsonDeserializationError
+ description:@"Token response invalid."];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(nil, returnedError);
+ });
+ return;
+ }
+
+ // If an ID Token is included in the response, validates the ID Token following the rules
+ // in OpenID Connect Core Section 3.1.3.7 for features that AppAuth directly supports
+ // (which excludes rules #1, #4, #5, #7, #8, #12, and #13). Regarding rule #6, ID Tokens
+ // received by this class are received via direct communication between the Client and the Token
+ // Endpoint, thus we are exercising the option to rely only on the TLS validation. AppAuth
+ // has a zero dependencies policy, and verifying the JWT signature would add a dependency.
+ // Users of the library are welcome to perform the JWT signature verification themselves should
+ // they wish.
+ if (tokenResponse.idToken) {
+ OIDIDToken *idToken = [[OIDIDToken alloc] initWithIDTokenString:tokenResponse.idToken];
+ if (!idToken) {
+ NSError *invalidIDToken =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeIDTokenParsingError
+ underlyingError:nil
+ description:@"ID Token parsing failed"];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(nil, invalidIDToken);
+ });
+ return;
+ }
+
+ // OpenID Connect Core Section 3.1.3.7. rule #1
+ // Not supported: AppAuth does not support JWT encryption.
+
+ // OpenID Connect Core Section 3.1.3.7. rule #2
+ // Validates that the issuer in the ID Token matches that of the discovery document.
+ NSURL *issuer = tokenResponse.request.configuration.issuer;
+ if (issuer && ![idToken.issuer isEqual:issuer]) {
+ NSError *invalidIDToken =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeIDTokenFailedValidationError
+ underlyingError:nil
+ description:@"Issuer mismatch"];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(nil, invalidIDToken);
+ });
+ return;
+ }
+
+ // OpenID Connect Core Section 3.1.3.7. rule #3 & Section 2 azp Claim
+ // Validates that the aud (audience) Claim contains the client ID, or that the azp
+ // (authorized party) Claim matches the client ID.
+ NSString *clientID = tokenResponse.request.clientID;
+ if (![idToken.audience containsObject:clientID] &&
+ ![idToken.claims[@"azp"] isEqualToString:clientID]) {
+ NSError *invalidIDToken =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeIDTokenFailedValidationError
+ underlyingError:nil
+ description:@"Audience mismatch"];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(nil, invalidIDToken);
+ });
+ return;
+ }
+
+ // OpenID Connect Core Section 3.1.3.7. rules #4 & #5
+ // Not supported.
+
+ // OpenID Connect Core Section 3.1.3.7. rule #6
+ // As noted above, AppAuth only supports the code flow which results in direct communication
+ // of the ID Token from the Token Endpoint to the Client, and we are exercising the option to
+ // use TSL server validation instead of checking the token signature. Users may additionally
+ // check the token signature should they wish.
+
+ // OpenID Connect Core Section 3.1.3.7. rules #7 & #8
+ // Not applicable. See rule #6.
+
+ // OpenID Connect Core Section 3.1.3.7. rule #9
+ // Validates that the current time is before the expiry time.
+ NSTimeInterval expiresAtDifference = [idToken.expiresAt timeIntervalSinceNow];
+ if (expiresAtDifference < 0) {
+ NSError *invalidIDToken =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeIDTokenFailedValidationError
+ underlyingError:nil
+ description:@"ID Token expired"];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(nil, invalidIDToken);
+ });
+ return;
+ }
+
+ // OpenID Connect Core Section 3.1.3.7. rule #10
+ // Validates that the issued at time is not more than +/- 10 minutes on the current time.
+ NSTimeInterval issuedAtDifference = [idToken.issuedAt timeIntervalSinceNow];
+ if (fabs(issuedAtDifference) > kOIDAuthorizationSessionIATMaxSkew) {
+ NSString *message =
+ [NSString stringWithFormat:@"Issued at time is more than %d seconds before or after "
+ "the current time",
+ kOIDAuthorizationSessionIATMaxSkew];
+ NSError *invalidIDToken =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeIDTokenFailedValidationError
+ underlyingError:nil
+ description:message];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(nil, invalidIDToken);
+ });
+ return;
+ }
+
+ // Only relevant for the authorization_code response type
+ if ([tokenResponse.request.grantType isEqual:OIDGrantTypeAuthorizationCode]) {
+ // OpenID Connect Core Section 3.1.3.7. rule #11
+ // Validates the nonce.
+ NSString *nonce = authorizationResponse.request.nonce;
+ if (nonce && ![idToken.nonce isEqual:nonce]) {
+ NSError *invalidIDToken =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeIDTokenFailedValidationError
+ underlyingError:nil
+ description:@"Nonce mismatch"];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(nil, invalidIDToken);
+ });
+ return;
+ }
+ }
+
+ // OpenID Connect Core Section 3.1.3.7. rules #12
+ // ACR is not directly supported by AppAuth.
+
+ // OpenID Connect Core Section 3.1.3.7. rules #12
+ // max_age is not directly supported by AppAuth.
+ }
+
+ // Success
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(tokenResponse, nil);
+ });
+ }] resume];
+}
+
+
+#pragma mark - Registration Endpoint
+
++ (void)performRegistrationRequest:(OIDRegistrationRequest *)request
+ completion:(OIDRegistrationCompletion)completion {
+ NSURLRequest *URLRequest = [request URLRequest];
+ if (!URLRequest) {
+ // A problem occurred deserializing the response/JSON.
+ NSError *returnedError = [OIDErrorUtilities errorWithCode:OIDErrorCodeJSONSerializationError
+ underlyingError:nil
+ description:@"The registration request could not "
+ "be serialized as JSON."];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(nil, returnedError);
+ });
+ return;
+ }
+
+ NSURLSession *session = [OIDURLSessionProvider session];
+ [[session dataTaskWithRequest:URLRequest
+ completionHandler:^(NSData *_Nullable data,
+ NSURLResponse *_Nullable response,
+ NSError *_Nullable error) {
+ if (error) {
+ // A network error or server error occurred.
+ NSString *errorDescription =
+ [NSString stringWithFormat:@"Connection error making registration request to '%@': %@.",
+ URLRequest.URL,
+ error.localizedDescription];
+ NSError *returnedError = [OIDErrorUtilities errorWithCode:OIDErrorCodeNetworkError
+ underlyingError:error
+ description:errorDescription];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(nil, returnedError);
+ });
+ return;
+ }
+
+ NSHTTPURLResponse *HTTPURLResponse = (NSHTTPURLResponse *) response;
+
+ if (HTTPURLResponse.statusCode != 201 && HTTPURLResponse.statusCode != 200) {
+ // A server error occurred.
+ NSError *serverError = [OIDErrorUtilities HTTPErrorWithHTTPResponse:HTTPURLResponse
+ data:data];
+
+ // HTTP 400 may indicate an OpenID Connect Dynamic Client Registration 1.0 Section 3.3 error
+ // response, checks for that
+ if (HTTPURLResponse.statusCode == 400) {
+ NSError *jsonDeserializationError;
+ NSDictionary *> *json =
+ [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonDeserializationError];
+
+ // if the HTTP 400 response parses as JSON and has an 'error' key, it's an OAuth error
+ // these errors are special as they indicate a problem with the authorization grant
+ if (json[OIDOAuthErrorFieldError]) {
+ NSError *oauthError =
+ [OIDErrorUtilities OAuthErrorWithDomain:OIDOAuthRegistrationErrorDomain
+ OAuthResponse:json
+ underlyingError:serverError];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(nil, oauthError);
+ });
+ return;
+ }
+ }
+
+ // not an OAuth error, just a generic server error
+ NSString *errorDescription =
+ [NSString stringWithFormat:@"Non-200/201 HTTP response (%d) making registration request "
+ "to '%@'.",
+ (int)HTTPURLResponse.statusCode,
+ URLRequest.URL];
+ NSError *returnedError = [OIDErrorUtilities errorWithCode:OIDErrorCodeServerError
+ underlyingError:serverError
+ description:errorDescription];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(nil, returnedError);
+ });
+ return;
+ }
+
+ NSError *jsonDeserializationError;
+ NSDictionary *> *json =
+ [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonDeserializationError];
+ if (jsonDeserializationError) {
+ // A problem occurred deserializing the response/JSON.
+ NSString *errorDescription =
+ [NSString stringWithFormat:@"JSON error parsing registration response: %@",
+ jsonDeserializationError.localizedDescription];
+ NSError *returnedError = [OIDErrorUtilities errorWithCode:OIDErrorCodeJSONDeserializationError
+ underlyingError:jsonDeserializationError
+ description:errorDescription];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(nil, returnedError);
+ });
+ return;
+ }
+
+ OIDRegistrationResponse *registrationResponse =
+ [[OIDRegistrationResponse alloc] initWithRequest:request
+ parameters:json];
+ if (!registrationResponse) {
+ // A problem occurred constructing the registration response from the JSON.
+ NSError *returnedError =
+ [OIDErrorUtilities errorWithCode:OIDErrorCodeRegistrationResponseConstructionError
+ underlyingError:nil
+ description:@"Registration response invalid."];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(nil, returnedError);
+ });
+ return;
+ }
+
+ // Success
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(registrationResponse, nil);
+ });
+ }] resume];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDClientMetadataParameters.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDClientMetadataParameters.h
new file mode 100644
index 0000000000..39ea2d6219
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDClientMetadataParameters.h
@@ -0,0 +1,51 @@
+/*! @file OIDClientMetadataParameters.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 The AppAuth for iOS Authors. 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Parameter name for the token endpoint authentication method.
+ */
+extern NSString *const OIDTokenEndpointAuthenticationMethodParam;
+
+/*! @brief Parameter name for the application type.
+ */
+extern NSString *const OIDApplicationTypeParam;
+
+/*! @brief Parameter name for the redirect URI values.
+ */
+extern NSString *const OIDRedirectURIsParam;
+
+/*! @brief Parameter name for the response type values.
+ */
+extern NSString *const OIDResponseTypesParam;
+
+/*! @brief Parameter name for the grant type values.
+ */
+extern NSString *const OIDGrantTypesParam;
+
+/*! @brief Parameter name for the subject type.
+ */
+extern NSString *const OIDSubjectTypeParam;
+
+/*! @brief Application type that indicates this client is a native (not a web) application.
+ */
+extern NSString *const OIDApplicationTypeNative;
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDClientMetadataParameters.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDClientMetadataParameters.m
new file mode 100644
index 0000000000..79ad467651
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDClientMetadataParameters.m
@@ -0,0 +1,33 @@
+/*! @file OIDClientMetadataParameters.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 The AppAuth for iOS Authors. 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 "OIDClientMetadataParameters.h"
+
+NSString *const OIDTokenEndpointAuthenticationMethodParam = @"token_endpoint_auth_method";
+
+NSString *const OIDApplicationTypeParam = @"application_type";
+
+NSString *const OIDRedirectURIsParam = @"redirect_uris";
+
+NSString *const OIDResponseTypesParam = @"response_types";
+
+NSString *const OIDGrantTypesParam = @"grant_types";
+
+NSString *const OIDSubjectTypeParam = @"subject_type";
+
+NSString *const OIDApplicationTypeNative = @"native";
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDDefines.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDDefines.h
new file mode 100644
index 0000000000..8ff4f19bab
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDDefines.h
@@ -0,0 +1,51 @@
+/*! @file OIDDefines.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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.
+ */
+
+/*! @def OIDIsEqualIncludingNil(x, y)
+ @brief Returns YES if x and y are equal by reference or value.
+ @discussion NOTE: parameters may be evaluated multiple times. Be careful if using this check
+ with expressions - especially if the expressions have side effects.
+ @param x An object.
+ @param y An object.
+ */
+#define OIDIsEqualIncludingNil(x, y) (((x) == (y)) || [(x) isEqual:(y)])
+
+/*! @def OID_UNAVAILABLE_USE_INITIALIZER(designatedInitializer)
+ @brief Provides a template implementation for init-family methods which have been marked as
+ NS_UNAVILABLE. Stops the compiler from giving a warning when it's the super class'
+ designated initializer, and gives callers useful feedback telling them what the
+ new designated initializer is.
+ @remarks Takes a SEL as a parameter instead of a string so that we get compiler warnings if the
+ designated intializer's signature changes.
+ @param designatedInitializer A SEL referencing the designated initializer.
+ */
+#define OID_UNAVAILABLE_USE_INITIALIZER(designatedInitializer) { \
+ NSString *reason = [NSString stringWithFormat:@"Called: %@\nDesignated Initializer:%@", \
+ NSStringFromSelector(_cmd), \
+ NSStringFromSelector(designatedInitializer)]; \
+ @throw [NSException exceptionWithName:@"Attempt to call unavailable initializer." \
+ reason:reason \
+ userInfo:nil]; \
+}
+
+#ifdef _APPAUTHTRACE
+# define AppAuthRequestTrace(fmt, ...) NSLog(fmt, ##__VA_ARGS__);
+#else // _APPAUTHTRACE
+# define AppAuthRequestTrace(...)
+#endif // _APPAUTHTRACE
+
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDEndSessionRequest.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDEndSessionRequest.h
new file mode 100644
index 0000000000..4087e9fa9f
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDEndSessionRequest.h
@@ -0,0 +1,107 @@
+/*! @file OIDEndSessionRequest.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2017 The AppAuth Authors. 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
+
+#import "OIDExternalUserAgentRequest.h"
+
+@class OIDServiceConfiguration;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OIDEndSessionRequest : NSObject
+
+
+/*! @brief The service's configuration.
+ @remarks This configuration specifies how to connect to a particular OAuth provider.
+ Configurations may be created manually, or via an OpenID Connect Discovery Document.
+ */
+@property(nonatomic, readonly) OIDServiceConfiguration *configuration;
+
+/*! @brief The client's redirect URI.
+ @remarks post_logout_redirect_uri
+ @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout
+ */
+@property(nonatomic, readonly, nullable) NSURL *postLogoutRedirectURL;
+
+/*! @brief Previously issued ID Token passed to the end session endpoint as a hint about the End-User's current authenticated
+ session with the Client
+ @remarks id_token_hint
+ @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout
+ */
+@property(nonatomic, readonly, nullable) NSString *idTokenHint;
+
+/*! @brief An opaque value used by the client to maintain state between the request and callback.
+ @remarks state
+ @discussion If this value is not explicitly set, this library will automatically add state and
+ perform appropriate validation of the state in the authorization response. It is recommended
+ that the default implementation of this parameter be used wherever possible. Typically used
+ to prevent CSRF attacks, as recommended in RFC6819 Section 5.3.5.
+ @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout
+ */
+@property(nonatomic, readonly, nullable) NSString *state;
+
+/*! @brief The client's additional authorization parameters.
+ @see https://tools.ietf.org/html/rfc6749#section-3.1
+ */
+@property(nonatomic, readonly, nullable) NSDictionary *additionalParameters;
+
+/*! @internal
+ @brief Unavailable. Please use @c initWithConfiguration:clientId:scopes:redirectURL:additionalParameters:.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @brief Creates an authorization request with opinionated defaults (a secure @c state).
+ @param configuration The service's configuration.
+ @param idTokenHint The previously issued ID Token
+ @param postLogoutRedirectURL The client's post-logout redirect URI.
+ callback.
+ @param additionalParameters The client's additional authorization parameters.
+*/
+- (instancetype)
+ initWithConfiguration:(OIDServiceConfiguration *)configuration
+ idTokenHint:(NSString *)idTokenHint
+ postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL
+ additionalParameters:(nullable NSDictionary *)additionalParameters;
+
+/*! @brief Designated initializer.
+ @param configuration The service's configuration.
+ @param idTokenHint The previously issued ID Token
+ @param postLogoutRedirectURL The client's post-logout redirect URI.
+ @param state An opaque value used by the client to maintain state between the request and
+ callback.
+ @param additionalParameters The client's additional authorization parameters.
+ */
+- (instancetype)
+ initWithConfiguration:(OIDServiceConfiguration *)configuration
+ idTokenHint:(NSString *)idTokenHint
+ postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL
+ state:(NSString *)state
+ additionalParameters:(nullable NSDictionary *)additionalParameters
+ NS_DESIGNATED_INITIALIZER;
+
+/*! @brief Constructs the request URI by adding the request parameters to the query component of the
+ authorization endpoint URI using the "application/x-www-form-urlencoded" format.
+ @return A URL representing the authorization request.
+ @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout
+ */
+- (NSURL *)endSessionRequestURL;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDEndSessionRequest.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDEndSessionRequest.m
new file mode 100644
index 0000000000..1e9eb0e228
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDEndSessionRequest.m
@@ -0,0 +1,190 @@
+/*! @file OIDEndSessionRequest.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2017 The AppAuth Authors. 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 "OIDEndSessionRequest.h"
+
+#import "OIDDefines.h"
+#import "OIDTokenUtilities.h"
+#import "OIDServiceConfiguration.h"
+#import "OIDServiceDiscovery.h"
+#import "OIDURLQueryComponent.h"
+
+/*! @brief The key for the @c configuration property for @c NSSecureCoding
+ */
+static NSString *const kConfigurationKey = @"configuration";
+
+/*! @brief Key used to encode the @c state property for @c NSSecureCoding, and on the URL request.
+ */
+static NSString *const kStateKey = @"state";
+
+/*! @brief Key used to encode the @c postLogoutRedirectURL property for @c NSSecureCoding, and on the URL request.
+ */
+static NSString *const kPostLogoutRedirectURLKey = @"post_logout_redirect_uri";
+
+/*! @brief Key used to encode the @c idTokenHint property for @c NSSecureCoding, and on the URL request.
+ */
+static NSString *const kIdTokenHintKey = @"id_token_hint";
+
+/*! @brief Key used to encode the @c additionalParameters property for @c NSSecureCoding
+ */
+static NSString *const kAdditionalParametersKey = @"additionalParameters";
+
+/*! @brief Number of random bytes generated for the @state.
+ */
+static NSUInteger const kStateSizeBytes = 32;
+
+/*! @brief Assertion text for missing end_session_endpoint.
+ */
+static NSString *const OIDMissingEndSessionEndpointMessage =
+@"The service configuration is missing an end_session_endpoint.";
+
+@implementation OIDEndSessionRequest
+
+- (instancetype)init
+ OID_UNAVAILABLE_USE_INITIALIZER(
+ @selector(initWithConfiguration:
+ idTokenHint:
+ postLogoutRedirectURL:
+ additionalParameters:)
+ )
+
+- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
+ idTokenHint:(NSString *)idTokenHint
+ postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL
+ state:(NSString *)state
+ additionalParameters:(NSDictionary *)additionalParameters
+{
+ self = [super init];
+ if (self) {
+ _configuration = [configuration copy];
+ _idTokenHint = [idTokenHint copy];
+ _postLogoutRedirectURL = [postLogoutRedirectURL copy];
+ _state = [state copy];
+ _additionalParameters =
+ [[NSDictionary alloc] initWithDictionary:additionalParameters copyItems:YES];
+ }
+ return self;
+}
+
+- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
+ idTokenHint:(NSString *)idTokenHint
+ postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL
+ additionalParameters:(NSDictionary *)additionalParameters
+{
+ return [self initWithConfiguration:configuration
+ idTokenHint:idTokenHint
+ postLogoutRedirectURL:postLogoutRedirectURL
+ state:[[self class] generateState]
+ additionalParameters:additionalParameters];
+}
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(nullable NSZone *)zone {
+ // The documentation for NSCopying specifically advises us to return a reference to the original
+ // instance in the case where instances are immutable (as ours is):
+ // "Implement NSCopying by retaining the original instead of creating a new copy when the class
+ // and its contents are immutable."
+ return self;
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+ return YES;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+ OIDServiceConfiguration *configuration = [aDecoder decodeObjectOfClass:[OIDServiceConfiguration class] forKey:kConfigurationKey];
+
+ NSString *idTokenHint = [aDecoder decodeObjectOfClass:[NSString class] forKey:kIdTokenHintKey];
+ NSURL *postLogoutRedirectURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kPostLogoutRedirectURLKey];
+ NSString *state = [aDecoder decodeObjectOfClass:[NSString class] forKey:kStateKey];
+ NSSet *additionalParameterCodingClasses = [NSSet setWithArray:@[
+ [NSDictionary class],
+ [NSString class]
+ ]];
+ NSDictionary *additionalParameters = [aDecoder decodeObjectOfClasses:additionalParameterCodingClasses
+ forKey:kAdditionalParametersKey];
+
+ self = [self initWithConfiguration:configuration
+ idTokenHint:idTokenHint
+ postLogoutRedirectURL:postLogoutRedirectURL
+ state:state
+ additionalParameters:additionalParameters];
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+ [aCoder encodeObject:_configuration forKey:kConfigurationKey];
+ [aCoder encodeObject:_idTokenHint forKey:kIdTokenHintKey];
+ [aCoder encodeObject:_postLogoutRedirectURL forKey:kPostLogoutRedirectURLKey];
+ [aCoder encodeObject:_state forKey:kStateKey];
+ [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey];
+}
+
+#pragma mark - NSObject overrides
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@: %p, request: %@>",
+ NSStringFromClass([self class]),
+ (void *)self,
+ self.endSessionRequestURL];
+}
+
++ (nullable NSString *)generateState {
+ return [OIDTokenUtilities randomURLSafeStringWithSize:kStateSizeBytes];
+}
+
+#pragma mark - OIDExternalUserAgentRequest
+
+- (NSURL*)externalUserAgentRequestURL {
+ return [self endSessionRequestURL];
+}
+
+- (NSString *)redirectScheme {
+ return [_postLogoutRedirectURL scheme];
+}
+
+#pragma mark -
+
+- (NSURL *)endSessionRequestURL {
+ OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] init];
+
+ // Add any additional parameters the client has specified.
+ [query addParameters:_additionalParameters];
+
+ // Add optional parameters, as applicable.
+ if (_idTokenHint) {
+ [query addParameter:kIdTokenHintKey value:_idTokenHint];
+ }
+
+ if (_postLogoutRedirectURL) {
+ [query addParameter:kPostLogoutRedirectURLKey value:_postLogoutRedirectURL.absoluteString];
+ }
+
+ if (_state) {
+ [query addParameter:kStateKey value:_state];
+ }
+
+ NSAssert(_configuration.endSessionEndpoint, OIDMissingEndSessionEndpointMessage);
+
+ // Construct the URL
+ return [query URLByReplacingQueryInURL:_configuration.endSessionEndpoint];
+}
+
+@end
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDEndSessionResponse.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDEndSessionResponse.h
new file mode 100644
index 0000000000..ab69b9305b
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDEndSessionResponse.h
@@ -0,0 +1,64 @@
+/*! @file OIDEndSessionResponse.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2017 The AppAuth Authors. 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
+
+@class OIDEndSessionRequest;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Represents the response to an End Session request.
+ @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout
+ */
+
+@interface OIDEndSessionResponse : NSObject
+
+/*! @brief The request which was serviced.
+ */
+@property(nonatomic, readonly) OIDEndSessionRequest *request;
+
+/*! @brief REQUIRED if the "state" parameter was present in the client end-session request. The
+ exact value received from the client.
+ @remarks state
+ */
+@property(nonatomic, readonly, nullable) NSString *state;
+
+/*! @brief Additional parameters returned from the end session endpoint.
+ */
+@property(nonatomic, readonly, nullable)
+ NSDictionary *> *additionalParameters;
+
+/*! @internal
+ @brief Unavailable. Please use initWithParameters:.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @brief Designated initializer.
+ @param request The serviced request.
+ @param parameters The decoded parameters returned from the End Session Endpoint.
+ @remarks Known parameters are extracted from the @c parameters parameter and the normative
+ properties are populated. Non-normative parameters are placed in the
+ @c #additionalParameters dictionary.
+ */
+- (instancetype)initWithRequest:(OIDEndSessionRequest *)request
+ parameters:(NSDictionary *> *)parameters
+ NS_DESIGNATED_INITIALIZER;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDEndSessionResponse.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDEndSessionResponse.m
new file mode 100644
index 0000000000..bedf0cd936
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDEndSessionResponse.m
@@ -0,0 +1,118 @@
+/*! @file OIDEndSessionResponse.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2017 The AppAuth Authors. 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 "OIDEndSessionResponse.h"
+
+#import "OIDDefines.h"
+#import "OIDEndSessionRequest.h"
+#import "OIDFieldMapping.h"
+
+/*! @brief The key for the @c state property in the incoming parameters and for @c NSSecureCoding.
+ */
+static NSString *const kStateKey = @"state";
+
+/*! @brief Key used to encode the @c request property for @c NSSecureCoding
+ */
+static NSString *const kRequestKey = @"request";
+
+/*! @brief Key used to encode the @c additionalParameters property for
+ @c NSSecureCoding
+ */
+static NSString *const kAdditionalParametersKey = @"additionalParameters";
+
+@implementation OIDEndSessionResponse
+
+#pragma mark - Initializers
+
+- (instancetype)init
+ OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithRequest:parameters:))
+
+- (instancetype)initWithRequest:(OIDEndSessionRequest *)request
+ parameters:(NSDictionary *> *)parameters {
+ self = [super init];
+ if (self) {
+ _request = [request copy];
+ NSDictionary *> *additionalParameters =
+ [OIDFieldMapping remainingParametersWithMap:[[self class] fieldMap]
+ parameters:parameters
+ instance:self];
+ _additionalParameters = additionalParameters;
+ }
+ return self;
+}
+
+/*! @brief Returns a mapping of incoming parameters to instance variables.
+ @return A mapping of incoming parameters to instance variables.
+ */
++ (NSDictionary *)fieldMap {
+ static NSMutableDictionary *fieldMap;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ fieldMap = [NSMutableDictionary dictionary];
+ fieldMap[kStateKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_state" type:[NSString class]];
+ });
+ return fieldMap;
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(nullable NSZone *)zone {
+ // The documentation for NSCopying specifically advises us to return a reference to the original
+ // instance in the case where instances are immutable (as ours is):
+ // "Implement NSCopying by retaining the original instead of creating a new copy when the class
+ // and its contents are immutable."
+ return self;
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+ return YES;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+ OIDEndSessionRequest *request =
+ [aDecoder decodeObjectOfClass:[OIDEndSessionRequest class] forKey:kRequestKey];
+ self = [self initWithRequest:request parameters:@{ }];
+ if (self) {
+ [OIDFieldMapping decodeWithCoder:aDecoder map:[[self class] fieldMap] instance:self];
+ _additionalParameters = [aDecoder decodeObjectOfClasses:[OIDFieldMapping JSONTypes]
+ forKey:kAdditionalParametersKey];
+ }
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+ [aCoder encodeObject:_request forKey:kRequestKey];
+ [OIDFieldMapping encodeWithCoder:aCoder map:[[self class] fieldMap] instance:self];
+ [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey];
+}
+
+#pragma mark - NSObject overrides
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@: %p, state: \"%@\", "
+ "additionalParameters: %@, request: %@>",
+ NSStringFromClass([self class]),
+ (void *)self,
+ _state,
+ _additionalParameters,
+ _request];
+}
+@end
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDError.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDError.h
new file mode 100644
index 0000000000..5131f0ad48
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDError.h
@@ -0,0 +1,393 @@
+/*! @file OIDError.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief The error domain for all NSErrors returned from the AppAuth library.
+ */
+extern NSString *const OIDGeneralErrorDomain;
+
+/*! @brief The error domain for OAuth specific errors on the authorization endpoint.
+ @discussion This error domain is used when the server responds to an authorization request
+ with an explicit OAuth error, as defined by RFC6749 Section 4.1.2.1. If the authorization
+ response is invalid and not explicitly an error response, another error domain will be used.
+ The error response parameter dictionary is available in the
+ \NSError_userInfo dictionary using the @c ::OIDOAuthErrorResponseErrorKey key.
+ The \NSError_code will be one of the @c ::OIDErrorCodeOAuthAuthorization enum values.
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+extern NSString *const OIDOAuthAuthorizationErrorDomain;
+
+/*! @brief The error domain for OAuth specific errors on the token endpoint.
+ @discussion This error domain is used when the server responds with HTTP 400 and an OAuth error,
+ as defined RFC6749 Section 5.2. If an HTTP 400 response does not parse as an OAuth error
+ (i.e. no 'error' field is present or the JSON is invalid), another error domain will be
+ used. The entire OAuth error response dictionary is available in the \NSError_userInfo
+ dictionary using the @c ::OIDOAuthErrorResponseErrorKey key. Unlike transient network
+ errors, errors in this domain invalidate the authentication state, and either indicate a
+ client error or require user interaction (i.e. reauthentication) to resolve.
+ The \NSError_code will be one of the @c ::OIDErrorCodeOAuthToken enum values.
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+extern NSString *const OIDOAuthTokenErrorDomain;
+
+/*! @brief The error domain for dynamic client registration errors.
+ @discussion This error domain is used when the server responds with HTTP 400 and an OAuth error,
+ as defined in OpenID Connect Dynamic Client Registration 1.0 Section 3.3. If an HTTP 400
+ response does not parse as an OAuth error (i.e. no 'error' field is present or the JSON is
+ invalid), another error domain will be used. The entire OAuth error response dictionary is
+ available in the \NSError_userInfo dictionary using the @c ::OIDOAuthErrorResponseErrorKey
+ key. Unlike transient network errors, errors in this domain invalidate the authentication
+ state, and indicates a client error.
+ The \NSError_code will be one of the @c ::OIDErrorCodeOAuthToken enum values.
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError
+ */
+extern NSString *const OIDOAuthRegistrationErrorDomain;
+
+/*! @brief The error domain for authorization errors encountered out of band on the resource server.
+ */
+extern NSString *const OIDResourceServerAuthorizationErrorDomain;
+
+/*! @brief An error domain representing received HTTP errors.
+ */
+extern NSString *const OIDHTTPErrorDomain;
+
+/*! @brief An error key for the original OAuth error response (if any).
+ */
+extern NSString *const OIDOAuthErrorResponseErrorKey;
+
+/*! @brief The key of the 'error' response field in a RFC6749 Section 5.2 response.
+ @remark error
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+extern NSString *const OIDOAuthErrorFieldError;
+
+/*! @brief The key of the 'error_description' response field in a RFC6749 Section 5.2 response.
+ @remark error_description
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+extern NSString *const OIDOAuthErrorFieldErrorDescription;
+
+/*! @brief The key of the 'error_uri' response field in a RFC6749 Section 5.2 response.
+ @remark error_uri
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+extern NSString *const OIDOAuthErrorFieldErrorURI;
+
+/*! @brief The various error codes returned from the AppAuth library.
+ */
+typedef NS_ENUM(NSInteger, OIDErrorCode) {
+ /*! @brief Indicates a problem parsing an OpenID Connect Service Discovery document.
+ */
+ OIDErrorCodeInvalidDiscoveryDocument = -2,
+
+ /*! @brief Indicates the user manually canceled the OAuth authorization code flow.
+ */
+ OIDErrorCodeUserCanceledAuthorizationFlow = -3,
+
+ /*! @brief Indicates an OAuth authorization flow was programmatically cancelled.
+ */
+ OIDErrorCodeProgramCanceledAuthorizationFlow = -4,
+
+ /*! @brief Indicates a network error or server error occurred.
+ */
+ OIDErrorCodeNetworkError = -5,
+
+ /*! @brief Indicates a server error occurred.
+ */
+ OIDErrorCodeServerError = -6,
+
+ /*! @brief Indicates a problem occurred deserializing the response/JSON.
+ */
+ OIDErrorCodeJSONDeserializationError = -7,
+
+ /*! @brief Indicates a problem occurred constructing the token response from the JSON.
+ */
+ OIDErrorCodeTokenResponseConstructionError = -8,
+
+ /*! @brief @c UIApplication.openURL: returned NO when attempting to open the authorization
+ request in mobile Safari.
+ */
+ OIDErrorCodeSafariOpenError = -9,
+
+ /*! @brief @c NSWorkspace.openURL returned NO when attempting to open the authorization
+ request in the default browser.
+ */
+ OIDErrorCodeBrowserOpenError = -10,
+
+ /*! @brief Indicates a problem when trying to refresh the tokens.
+ */
+ OIDErrorCodeTokenRefreshError = -11,
+
+ /*! @brief Indicates a problem occurred constructing the registration response from the JSON.
+ */
+ OIDErrorCodeRegistrationResponseConstructionError = -12,
+
+ /*! @brief Indicates a problem occurred deserializing the response/JSON.
+ */
+ OIDErrorCodeJSONSerializationError = -13,
+
+ /*! @brief The ID Token did not parse.
+ */
+ OIDErrorCodeIDTokenParsingError = -14,
+
+ /*! @brief The ID Token did not pass validation (e.g. issuer, audience checks).
+ */
+ OIDErrorCodeIDTokenFailedValidationError = -15,
+};
+
+/*! @brief Enum of all possible OAuth error codes as defined by RFC6749
+ @discussion Used by @c ::OIDErrorCodeOAuthAuthorization and @c ::OIDErrorCodeOAuthToken
+ which define endpoint-specific subsets of OAuth codes. Those enum types are down-castable
+ to this one.
+ @see https://tools.ietf.org/html/rfc6749#section-11.4
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+typedef NS_ENUM(NSInteger, OIDErrorCodeOAuth) {
+
+ /*! @remarks invalid_request
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthInvalidRequest = -2,
+
+ /*! @remarks unauthorized_client
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthUnauthorizedClient = -3,
+
+ /*! @remarks access_denied
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+ OIDErrorCodeOAuthAccessDenied = -4,
+
+ /*! @remarks unsupported_response_type
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+ OIDErrorCodeOAuthUnsupportedResponseType = -5,
+
+ /*! @remarks invalid_scope
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthInvalidScope = -6,
+
+ /*! @remarks server_error
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+ OIDErrorCodeOAuthServerError = -7,
+
+ /*! @remarks temporarily_unavailable
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+ OIDErrorCodeOAuthTemporarilyUnavailable = -8,
+
+ /*! @remarks invalid_client
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthInvalidClient = -9,
+
+ /*! @remarks invalid_grant
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthInvalidGrant = -10,
+
+ /*! @remarks unsupported_grant_type
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthUnsupportedGrantType = -11,
+
+ /*! @remarks invalid_redirect_uri
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError
+ */
+ OIDErrorCodeOAuthInvalidRedirectURI = -12,
+
+ /*! @remarks invalid_client_metadata
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError
+ */
+ OIDErrorCodeOAuthInvalidClientMetadata = -13,
+
+ /*! @brief An authorization error occurring on the client rather than the server. For example,
+ due to a state mismatch or misconfiguration. Should be treated as an unrecoverable
+ authorization error.
+ */
+ OIDErrorCodeOAuthClientError = -0xEFFF,
+
+ /*! @brief An OAuth error not known to this library
+ @discussion Indicates an OAuth error as per RFC6749, but the error code was not in our
+ list. It could be a custom error code, or one from an OAuth extension. See the "error" key
+ of the \NSError_userInfo property. Such errors are assumed to invalidate the
+ authentication state
+ */
+ OIDErrorCodeOAuthOther = -0xF000,
+};
+
+/*! @brief The error codes for the @c ::OIDOAuthAuthorizationErrorDomain error domain
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+typedef NS_ENUM(NSInteger, OIDErrorCodeOAuthAuthorization) {
+ /*! @remarks invalid_request
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+ OIDErrorCodeOAuthAuthorizationInvalidRequest = OIDErrorCodeOAuthInvalidRequest,
+
+ /*! @remarks unauthorized_client
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+ OIDErrorCodeOAuthAuthorizationUnauthorizedClient = OIDErrorCodeOAuthUnauthorizedClient,
+
+ /*! @remarks access_denied
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+ OIDErrorCodeOAuthAuthorizationAccessDenied =
+ OIDErrorCodeOAuthAccessDenied,
+
+ /*! @remarks unsupported_response_type
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+ OIDErrorCodeOAuthAuthorizationUnsupportedResponseType =
+ OIDErrorCodeOAuthUnsupportedResponseType,
+
+ /*! @brief Indicates a network error or server error occurred.
+ @remarks invalid_scope
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+ OIDErrorCodeOAuthAuthorizationAuthorizationInvalidScope = OIDErrorCodeOAuthInvalidScope,
+
+ /*! @brief Indicates a server error occurred.
+ @remarks server_error
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+ OIDErrorCodeOAuthAuthorizationServerError = OIDErrorCodeOAuthServerError,
+
+ /*! @remarks temporarily_unavailable
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+ OIDErrorCodeOAuthAuthorizationTemporarilyUnavailable = OIDErrorCodeOAuthTemporarilyUnavailable,
+
+ /*! @brief An authorization error occurring on the client rather than the server. For example,
+ due to a state mismatch or client misconfiguration. Should be treated as an unrecoverable
+ authorization error.
+ */
+ OIDErrorCodeOAuthAuthorizationClientError = OIDErrorCodeOAuthClientError,
+
+ /*! @brief An authorization OAuth error not known to this library
+ @discussion this indicates an OAuth error as per RFC6749, but the error code was not in our
+ list. It could be a custom error code, or one from an OAuth extension. See the "error" key
+ of the \NSError_userInfo property. We assume such errors are not transient.
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ */
+ OIDErrorCodeOAuthAuthorizationOther = OIDErrorCodeOAuthOther,
+};
+
+
+/*! @brief The error codes for the @c ::OIDOAuthTokenErrorDomain error domain
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+typedef NS_ENUM(NSInteger, OIDErrorCodeOAuthToken) {
+ /*! @remarks invalid_request
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthTokenInvalidRequest = OIDErrorCodeOAuthInvalidRequest,
+
+ /*! @remarks invalid_client
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthTokenInvalidClient = OIDErrorCodeOAuthInvalidClient,
+
+ /*! @remarks invalid_grant
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthTokenInvalidGrant = OIDErrorCodeOAuthInvalidGrant,
+
+ /*! @remarks unauthorized_client
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthTokenUnauthorizedClient = OIDErrorCodeOAuthUnauthorizedClient,
+
+ /*! @remarks unsupported_grant_type
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthTokenUnsupportedGrantType = OIDErrorCodeOAuthUnsupportedGrantType,
+
+ /*! @remarks invalid_scope
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthTokenInvalidScope = OIDErrorCodeOAuthInvalidScope,
+
+ /*! @brief An unrecoverable token error occurring on the client rather than the server.
+ */
+ OIDErrorCodeOAuthTokenClientError = OIDErrorCodeOAuthClientError,
+
+ /*! @brief A token endpoint OAuth error not known to this library
+ @discussion this indicates an OAuth error as per RFC6749, but the error code was not in our
+ list. It could be a custom error code, or one from an OAuth extension. See the "error" key
+ of the \NSError_userInfo property. We assume such errors are not transient.
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthTokenOther = OIDErrorCodeOAuthOther,
+};
+
+/*! @brief The error codes for the @c ::OIDOAuthRegistrationErrorDomain error domain
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError
+ */
+typedef NS_ENUM(NSInteger, OIDErrorCodeOAuthRegistration) {
+ /*! @remarks invalid_request
+ @see http://tools.ietf.org/html/rfc6750#section-3.1
+ */
+ OIDErrorCodeOAuthRegistrationInvalidRequest = OIDErrorCodeOAuthInvalidRequest,
+
+ /*! @remarks invalid_redirect_uri
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError
+ */
+ OIDErrorCodeOAuthRegistrationInvalidRedirectURI = OIDErrorCodeOAuthInvalidRedirectURI,
+
+ /*! @remarks invalid_client_metadata
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError
+ */
+ OIDErrorCodeOAuthRegistrationInvalidClientMetadata = OIDErrorCodeOAuthInvalidClientMetadata,
+
+ /*! @brief An unrecoverable token error occurring on the client rather than the server.
+ */
+ OIDErrorCodeOAuthRegistrationClientError = OIDErrorCodeOAuthClientError,
+
+ /*! @brief A registration endpoint OAuth error not known to this library
+ @discussion this indicates an OAuth error, but the error code was not in our
+ list. It could be a custom error code, or one from an OAuth extension. See the "error" key
+ of the \NSError_userInfo property. We assume such errors are not transient.
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
+ OIDErrorCodeOAuthRegistrationOther = OIDErrorCodeOAuthOther,
+};
+
+
+/*! @brief The exception text for the exception which occurs when a
+ @c OIDExternalUserAgentSession receives a message after it has already completed.
+ */
+extern NSString *const OIDOAuthExceptionInvalidAuthorizationFlow;
+
+/*! @brief The text for the exception which occurs when a Token Request is constructed
+ with a null redirectURL for a grant_type that requires a nonnull Redirect
+ */
+extern NSString *const OIDOAuthExceptionInvalidTokenRequestNullRedirectURL;
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDError.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDError.m
new file mode 100644
index 0000000000..87c8623eef
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDError.m
@@ -0,0 +1,45 @@
+/*! @file OIDError.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDError.h"
+
+NSString *const OIDGeneralErrorDomain = @"org.openid.appauth.general";
+
+NSString *const OIDOAuthTokenErrorDomain = @"org.openid.appauth.oauth_token";
+
+NSString *const OIDOAuthAuthorizationErrorDomain = @"org.openid.appauth.oauth_authorization";
+
+NSString *const OIDOAuthRegistrationErrorDomain = @"org.openid.appauth.oauth_registration";
+
+NSString *const OIDResourceServerAuthorizationErrorDomain = @"org.openid.appauth.resourceserver";
+
+NSString *const OIDHTTPErrorDomain = @"org.openid.appauth.remote-http";
+
+NSString *const OIDOAuthExceptionInvalidAuthorizationFlow = @"An OAuth redirect was sent to a "
+ "OIDExternalUserAgentSession after it already completed.";
+
+NSString *const OIDOAuthExceptionInvalidTokenRequestNullRedirectURL = @"A OIDTokenRequest was "
+ "created with a grant_type that requires a redirectURL, but a null redirectURL was given";
+
+NSString *const OIDOAuthErrorResponseErrorKey = @"OIDOAuthErrorResponseErrorKey";
+
+NSString *const OIDOAuthErrorFieldError = @"error";
+
+NSString *const OIDOAuthErrorFieldErrorDescription = @"error_description";
+
+NSString *const OIDOAuthErrorFieldErrorURI = @"error_uri";
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDErrorUtilities.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDErrorUtilities.h
new file mode 100644
index 0000000000..3380f6fe1f
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDErrorUtilities.h
@@ -0,0 +1,107 @@
+/*! @file OIDErrorUtilities.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+#import "OIDError.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Convenience methods for creating standardized \NSError instances.
+ */
+@interface OIDErrorUtilities : NSObject
+
+/*! @brief Creates a standard \NSError from an @c ::OIDErrorCode and custom user info.
+ Automatically populates the localized error description.
+ @param code The error code.
+ @param underlyingError The underlying error which occurred, if applicable.
+ @param description A custom description, if applicable.
+ @return An \NSError representing the error code.
+ */
++ (NSError *)errorWithCode:(OIDErrorCode)code
+ underlyingError:(nullable NSError *)underlyingError
+ description:(nullable NSString *)description;
+
+/*! @brief Creates a standard \NSError from an @c ::OIDErrorCode and custom user info.
+ Automatically populates the localized error description.
+ @param OAuthErrorDomain The OAuth error domain. Must be @c ::OIDOAuthAuthorizationErrorDomain or
+ @c ::OIDOAuthTokenErrorDomain.
+ @param errorResponse The dictionary from an OAuth error response (as per RFC6749 Section 5.2).
+ @param underlyingError The underlying error which occurred, if applicable.
+ @return An \NSError representing the OAuth error.
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
++ (NSError *)OAuthErrorWithDomain:(NSString *)OAuthErrorDomain
+ OAuthResponse:(NSDictionary *)errorResponse
+ underlyingError:(nullable NSError *)underlyingError;
+
+/*! @brief Creates a \NSError indicating that the resource server responded with an authorization
+ error.
+ @param code Your error code.
+ @param errorResponse The resource server error response, if any.
+ @param underlyingError The underlying error which occurred, if applicable.
+ @return An \NSError representing the authorization error from the resource server.
+ */
++ (NSError *)resourceServerAuthorizationErrorWithCode:(NSInteger)code
+ errorResponse:(nullable NSDictionary *)errorResponse
+ underlyingError:(nullable NSError *)underlyingError;
+
+
+/*! @brief Creates a standard \NSError from an \NSHTTPURLResponse. Automatically
+ populates the localized error description with the response data associated with the
+ \NSHTTPURLResponse, if available.
+ @param HTTPURLResponse The response which indicates an error occurred.
+ @param data The response data associated with the response which should be converted to an
+ @c NSString assuming a UTF-8 encoding, if available.
+ @return An \NSError representing the error.
+ */
++ (NSError *)HTTPErrorWithHTTPResponse:(NSHTTPURLResponse *)HTTPURLResponse
+ data:(nullable NSData *)data;
+
+/*! @brief Raises an exception with the given name as both the name, and the message.
+ @param name The name of the exception.
+ */
++ (void)raiseException:(NSString *)name;
+
+/*! @brief Raises an exception with the given name and message.
+ @param name The name of the exception.
+ @param message The message of the exception.
+ */
++ (void)raiseException:(NSString *)name message:(NSString *)message;
+
+/*! @brief Converts an OAuth error code into an @c ::OIDErrorCodeOAuth error code.
+ @param errorCode The OAuth error code.
+ @discussion Returns @c ::OIDErrorCodeOAuthOther if the string is not in AppAuth's list.
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
++ (OIDErrorCodeOAuth)OAuthErrorCodeFromString:(NSString *)errorCode;
+
+/*! @brief Returns true if the given error domain is an OAuth error domain.
+ @param errorDomain The error domain to test.
+ @discussion An OAuth error domain is used for errors returned per RFC6749 sections 4.1.2.1 and
+ 5.2. Other errors, such as network errors can also occur but they will not have an OAuth
+ error domain.
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1
+ @see https://tools.ietf.org/html/rfc6749#section-5.2
+ */
++ (BOOL)isOAuthErrorDomain:(NSString*)errorDomain;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDErrorUtilities.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDErrorUtilities.m
new file mode 100644
index 0000000000..3b3c060753
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDErrorUtilities.m
@@ -0,0 +1,172 @@
+/*! @file OIDErrorUtilities.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDErrorUtilities.h"
+
+@implementation OIDErrorUtilities
+
++ (NSError *)errorWithCode:(OIDErrorCode)code
+ underlyingError:(NSError *)underlyingError
+ description:(NSString *)description {
+ NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+ if (underlyingError) {
+ userInfo[NSUnderlyingErrorKey] = underlyingError;
+ }
+ if (description) {
+ userInfo[NSLocalizedDescriptionKey] = description;
+ }
+ // TODO: Populate localized description based on code.
+ NSError *error = [NSError errorWithDomain:OIDGeneralErrorDomain
+ code:code
+ userInfo:userInfo];
+ return error;
+}
+
++ (BOOL)isOAuthErrorDomain:(NSString *)errorDomain {
+ return errorDomain == OIDOAuthRegistrationErrorDomain
+ || errorDomain == OIDOAuthAuthorizationErrorDomain
+ || errorDomain == OIDOAuthTokenErrorDomain;
+}
+
++ (NSError *)resourceServerAuthorizationErrorWithCode:(NSInteger)code
+ errorResponse:(nullable NSDictionary *)errorResponse
+ underlyingError:(nullable NSError *)underlyingError {
+ // builds the userInfo dictionary with the full OAuth response and other information
+ NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+ if (errorResponse) {
+ userInfo[OIDOAuthErrorResponseErrorKey] = errorResponse;
+ }
+ if (underlyingError) {
+ userInfo[NSUnderlyingErrorKey] = underlyingError;
+ }
+ NSError *error = [NSError errorWithDomain:OIDResourceServerAuthorizationErrorDomain
+ code:code
+ userInfo:userInfo];
+ return error;
+}
+
++ (NSError *)OAuthErrorWithDomain:(NSString *)oAuthErrorDomain
+ OAuthResponse:(NSDictionary *)errorResponse
+ underlyingError:(NSError *)underlyingError {
+ // not a valid OAuth error
+ if (![self isOAuthErrorDomain:oAuthErrorDomain]
+ || !errorResponse
+ || !errorResponse[OIDOAuthErrorFieldError]
+ || ![errorResponse[OIDOAuthErrorFieldError] isKindOfClass:[NSString class]]) {
+ return [[self class] errorWithCode:OIDErrorCodeNetworkError
+ underlyingError:underlyingError
+ description:underlyingError.localizedDescription];
+ }
+
+ // builds the userInfo dictionary with the full OAuth response and other information
+ NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+ userInfo[OIDOAuthErrorResponseErrorKey] = errorResponse;
+ if (underlyingError) {
+ userInfo[NSUnderlyingErrorKey] = underlyingError;
+ }
+
+ NSString *oauthErrorCodeString = errorResponse[OIDOAuthErrorFieldError];
+ NSString *oauthErrorMessage = nil;
+ if ([errorResponse[OIDOAuthErrorFieldErrorDescription] isKindOfClass:[NSString class]]) {
+ oauthErrorMessage = errorResponse[OIDOAuthErrorFieldErrorDescription];
+ } else {
+ oauthErrorMessage = [errorResponse[OIDOAuthErrorFieldErrorDescription] description];
+ }
+ NSString *oauthErrorURI = nil;
+ if ([errorResponse[OIDOAuthErrorFieldErrorURI] isKindOfClass:[NSString class]]) {
+ oauthErrorURI = errorResponse[OIDOAuthErrorFieldErrorURI];
+ } else {
+ oauthErrorURI = [errorResponse[OIDOAuthErrorFieldErrorURI] description];
+ }
+
+ // builds the error description, using the information supplied by the server if possible
+ NSMutableString *description = [NSMutableString string];
+ [description appendString:oauthErrorCodeString];
+ if (oauthErrorMessage) {
+ [description appendString:@": "];
+ [description appendString:oauthErrorMessage];
+ }
+ if (oauthErrorURI) {
+ if ([description length] > 0) {
+ [description appendString:@" - "];
+ }
+ [description appendString:oauthErrorURI];
+ }
+ if ([description length] == 0) {
+ // backup description
+ [description appendFormat:@"OAuth error: %@ - https://tools.ietf.org/html/rfc6749#section-5.2",
+ oauthErrorCodeString];
+ }
+ userInfo[NSLocalizedDescriptionKey] = description;
+
+ // looks up the error code based on the "error" response param
+ OIDErrorCodeOAuth code = [[self class] OAuthErrorCodeFromString:oauthErrorCodeString];
+
+ NSError *error = [NSError errorWithDomain:oAuthErrorDomain
+ code:code
+ userInfo:userInfo];
+ return error;
+}
+
++ (NSError *)HTTPErrorWithHTTPResponse:(NSHTTPURLResponse *)HTTPURLResponse
+ data:(nullable NSData *)data {
+ NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+ if (data) {
+ NSString *serverResponse =
+ [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+ if (serverResponse) {
+ userInfo[NSLocalizedDescriptionKey] = serverResponse;
+ }
+ }
+ NSError *serverError =
+ [NSError errorWithDomain:OIDHTTPErrorDomain
+ code:HTTPURLResponse.statusCode
+ userInfo:userInfo];
+ return serverError;
+}
+
++ (OIDErrorCodeOAuth)OAuthErrorCodeFromString:(NSString *)errorCode {
+ NSDictionary *errorCodes = @{
+ @"invalid_request": @(OIDErrorCodeOAuthInvalidRequest),
+ @"unauthorized_client": @(OIDErrorCodeOAuthUnauthorizedClient),
+ @"access_denied": @(OIDErrorCodeOAuthAccessDenied),
+ @"unsupported_response_type": @(OIDErrorCodeOAuthUnsupportedResponseType),
+ @"invalid_scope": @(OIDErrorCodeOAuthInvalidScope),
+ @"server_error": @(OIDErrorCodeOAuthServerError),
+ @"temporarily_unavailable": @(OIDErrorCodeOAuthTemporarilyUnavailable),
+ @"invalid_client": @(OIDErrorCodeOAuthInvalidClient),
+ @"invalid_grant": @(OIDErrorCodeOAuthInvalidGrant),
+ @"unsupported_grant_type": @(OIDErrorCodeOAuthUnsupportedGrantType),
+ };
+ NSNumber *code = errorCodes[errorCode];
+ if (code) {
+ return [code integerValue];
+ } else {
+ return OIDErrorCodeOAuthOther;
+ }
+}
+
++ (void)raiseException:(NSString *)name {
+ [[self class] raiseException:name message:name];
+}
+
++ (void)raiseException:(NSString *)name message:(NSString *)message {
+ [NSException raise:name format:@"%@", message];
+}
+
+@end
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDExternalUserAgent.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDExternalUserAgent.h
new file mode 100644
index 0000000000..c4eb0a9087
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDExternalUserAgent.h
@@ -0,0 +1,53 @@
+/*! @file OIDExternalUserAgent.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
+
+@protocol OIDExternalUserAgentSession;
+@protocol OIDExternalUserAgentRequest;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @protocol OIDExternalUserAgent
+ @brief An external user-agent UI that presents displays the request to the user. Clients may
+ provide custom implementations of an external user-agent to customize the way the requests
+ are presented to the end user.
+ */
+@protocol OIDExternalUserAgent
+
+/*! @brief Presents the request in the external user-agent.
+ @param request The request to be presented in the external user-agent.
+ @param session The @c OIDExternalUserAgentSession instance that initiates presenting the UI.
+ Concrete implementations of a @c OIDExternalUserAgent may call
+ resumeExternalUserAgentFlowWithURL or failExternalUserAgentFlowWithError on session to either
+ resume or fail the request.
+ @return YES If the request UI was successfully presented to the user.
+ */
+- (BOOL)presentExternalUserAgentRequest:(id )request
+ session:(id)session;
+
+/*! @brief Dimisses the external user-agent and calls completion when the dismiss operation ends.
+ @param animated Whether or not the dismiss operation should be animated.
+ @remarks Has no effect if no UI is presented.
+ @param completion The block to be called when the dismiss operations ends
+ */
+- (void)dismissExternalUserAgentAnimated:(BOOL)animated completion:(void (^)(void))completion;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDExternalUserAgentRequest.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDExternalUserAgentRequest.h
new file mode 100644
index 0000000000..8ea40cb694
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDExternalUserAgentRequest.h
@@ -0,0 +1,37 @@
+/*! @file OIDExternalUserAgent.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2017 The AppAuth Authors. 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.
+ */
+
+/*! @protocol OIDExternalUserAgent
+ @brief An interface that any external user-agent request may implement to use the
+ @c OIDExternalUserAgent flow.
+ */
+@protocol OIDExternalUserAgentRequest
+
+/*! @brief Method to create and return the complete request URL instance.
+ @return A @c NSURL instance which contains the URL to be opened in an external UI (i.e. browser)
+ */
+- (NSURL*)externalUserAgentRequestURL;
+
+/*! @brief If this external user-agent request has a redirect URL, this should return its scheme.
+ Since some external requests have optional callbacks (such as the end session endpoint), the
+ return value of this method is nullable.
+ @return A @c NSString instance that contains the scheme of a callback url, or nil if there is
+ no callback url for this request.
+ */
+- (NSString*)redirectScheme;
+@end
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDExternalUserAgentSession.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDExternalUserAgentSession.h
new file mode 100644
index 0000000000..3b886a6c38
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDExternalUserAgentSession.h
@@ -0,0 +1,65 @@
+/*! @file OIDExternalUserAgentSession.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2017 The AppAuth Authors. 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.
+ */
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Represents an in-flight external user-agent session.
+ */
+@protocol OIDExternalUserAgentSession
+
+/*! @brief Cancels the code flow session, invoking the request's callback with a cancelled error.
+ @remarks Has no effect if called more than once, or after a
+ @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message was received.
+ Will cause an error with code: @c ::OIDErrorCodeProgramCanceledAuthorizationFlow to be
+ passed to the @c callback block passed to
+ @c OIDAuthorizationService.presentAuthorizationRequest:presentingViewController:callback:
+ */
+- (void)cancel;
+
+/*! @brief Cancels the code flow session, invoking the request's callback with a cancelled error.
+ @remarks Has no effect if called more than once, or after a
+ @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message was received.
+ Will cause an error with code: @c ::OIDErrorCodeProgramCanceledAuthorizationFlow to be
+ passed to the @c callback block passed to
+ @c OIDAuthorizationService.presentAuthorizationRequest:presentingViewController:callback:
+ @param completion The block to be called when the cancel operation ends
+ */
+- (void)cancelWithCompletion:(nullable void (^)(void))completion;
+
+/*! @brief Clients should call this method with the result of the external user-agent code flow if
+ it becomes available.
+ @param URL The redirect URL invoked by the server.
+ @discussion When the URL represented a valid response, implementations should clean up any
+ left-over UI state from the request, for example by closing the
+ \SFSafariViewController or loopback HTTP listener if those were used. The completion block
+ of the pending request should then be invoked.
+ @remarks Has no effect if called more than once, or after a @c cancel message was received.
+ @return YES if the passed URL matches the expected redirect URL and was consumed, NO otherwise.
+ */
+- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL;
+
+/*! @brief @c OIDExternalUserAgent or clients should call this method when the
+ external user-agent flow failed with a non-OAuth error.
+ @param error The error that is the reason for the failure of this external flow.
+ @remarks Has no effect if called more than once, or after a @c cancel message was received.
+ */
+- (void)failExternalUserAgentFlowWithError:(NSError *)error;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDFieldMapping.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDFieldMapping.h
new file mode 100644
index 0000000000..f0a56fef39
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDFieldMapping.h
@@ -0,0 +1,126 @@
+/*! @file OIDFieldMapping.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Represents a function which transforms incoming source values into instance variable
+ values.
+ */
+typedef _Nullable id(^OIDFieldMappingConversionFunction)(NSObject *_Nullable value);
+
+/*! @brief Describes the mapping of a key/value pair to an iVar with an optional conversion
+ function.
+ */
+@interface OIDFieldMapping : NSObject
+
+/*! @brief The name of the instance variable the field should be mapped to.
+ */
+@property(nonatomic, readonly) NSString *name;
+
+/*! @brief The type of the instance variable.
+ */
+@property(nonatomic, readonly) Class expectedType;
+
+/*! @brief An optional conversion function which specifies a transform from the incoming data to the
+ instance variable value.
+ */
+@property(nonatomic, readonly, nullable) OIDFieldMappingConversionFunction conversion;
+
+/*! @internal
+ @brief Unavailable. Please use initWithName:type:conversion:.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @brief The designated initializer.
+ @param name The name of the instance variable the field should be mapped to.
+ @param type The type of the instance variable.
+ @param conversion An optional conversion function which specifies a transform from the incoming
+ data to the instance variable value. Used during the process performed by
+ @c OIDFieldMapping.remainingParametersWithMap:parameters:instance: but not during
+ encoding/decoding, since the encoded and decoded values should already be of the type
+ specified by the @c type parameter.
+ */
+- (instancetype)initWithName:(NSString *)name
+ type:(Class)type
+ conversion:(nullable OIDFieldMappingConversionFunction)conversion
+ NS_DESIGNATED_INITIALIZER;
+
+/*! @brief A convenience initializer.
+ @param name The name of the instance variable the field should be mapped to.
+ @param type The type of the instance variable.
+ */
+- (instancetype)initWithName:(NSString *)name
+ type:(Class)type;
+
+/*! @brief Performs a mapping of key/value pairs in an incoming parameters dictionary to instance
+ variables, returning a dictionary of parameter key/values which didn't map to instance
+ variables.
+ @param map A mapping of incoming keys to instance variables.
+ @param parameters Incoming key value pairs to map to an instance's variables.
+ @param instance The instance whose variables should be set based on the mapping.
+ @return A dictionary of parameter key/values which didn't map to instance variables.
+ */
++ (NSDictionary *> *)remainingParametersWithMap:
+ (NSDictionary *)map
+ parameters:(NSDictionary *> *)parameters
+ instance:(id)instance;
+
+/*! @brief This helper method for @c NSCoding implementations performs a serialization of fields
+ defined in a field mapping.
+ @param aCoder An @c NSCoder instance to serialize instance variable values to.
+ @param map A mapping of keys to instance variables.
+ @param instance The instance whose variables should be serialized based on the mapping.
+ */
++ (void)encodeWithCoder:(NSCoder *)aCoder
+ map:(NSDictionary *)map
+ instance:(id)instance;
+
+/*! @brief This helper method for @c NSCoding implementations performs a deserialization of
+ fields defined in a field mapping.
+ @param aCoder An @c NSCoder instance from which to deserialize instance variable values from.
+ @param map A mapping of keys to instance variables.
+ @param instance The instance whose variables should be deserialized based on the mapping.
+ */
++ (void)decodeWithCoder:(NSCoder *)aCoder
+ map:(NSDictionary *)map
+ instance:(id)instance;
+
+/*! @brief Returns an @c NSSet of classes suitable for deserializing JSON content in an
+ @c NSSecureCoding context.
+ */
++ (NSSet *)JSONTypes;
+
+/*! @brief Returns a function for converting an @c NSString to an @c NSURL.
+ */
++ (OIDFieldMappingConversionFunction)URLConversion;
+
+/*! @brief Returns a function for converting an @c NSNumber number of seconds from now to an
+ @c NSDate.
+ */
++ (OIDFieldMappingConversionFunction)dateSinceNowConversion;
+
+/*! @brief Returns a function for converting an @c NSNumber representing a unix time stamp to an
+ @c NSDate.
+ */
++ (OIDFieldMappingConversionFunction)dateEpochConversion;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDFieldMapping.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDFieldMapping.m
new file mode 100644
index 0000000000..f843656021
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDFieldMapping.m
@@ -0,0 +1,132 @@
+/*! @file OIDFieldMapping.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDFieldMapping.h"
+
+#import "OIDDefines.h"
+
+@implementation OIDFieldMapping
+
+- (nonnull instancetype)init
+ OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithName:type:conversion:))
+
+- (instancetype)initWithName:(NSString *)name
+ type:(Class)type {
+ return [self initWithName:name type:type conversion:nil];
+}
+
+- (instancetype)initWithName:(NSString *)name
+ type:(Class)type
+ conversion:(nullable OIDFieldMappingConversionFunction)conversion {
+ self = [super init];
+ if (self) {
+ _name = [name copy];
+ _expectedType = type;
+ _conversion = conversion;
+ }
+ return self;
+}
+
++ (NSDictionary *> *)remainingParametersWithMap:
+ (NSDictionary *)map
+ parameters:(NSDictionary *> *)parameters
+ instance:(id)instance {
+ NSMutableDictionary *additionalParameters = [NSMutableDictionary dictionary];
+ for (NSString *key in parameters) {
+ NSObject *value = [parameters[key] copy];
+ OIDFieldMapping *mapping = map[key];
+ // If the field doesn't appear in the mapping, we add it to the additional parameters
+ // dictionary.
+ if (!mapping) {
+ additionalParameters[key] = value;
+ continue;
+ }
+ // If the field mapping specifies a conversion function, apply the conversion to the value.
+ if (mapping.conversion) {
+ value = mapping.conversion(value);
+ }
+ // Check the type of the value and make sure it matches the type we expected. If it doesn't we
+ // add the value to the additional parameters dictionary but don't assign the instance variable.
+ if (![value isKindOfClass:mapping.expectedType]) {
+ additionalParameters[key] = value;
+ continue;
+ }
+ // Assign the instance variable.
+ [instance setValue:value forKey:mapping.name];
+ }
+ return additionalParameters;
+}
+
++ (void)encodeWithCoder:(NSCoder *)aCoder
+ map:(NSDictionary *)map
+ instance:(id)instance {
+ for (NSString *key in map) {
+ id value = [instance valueForKey:map[key].name];
+ [aCoder encodeObject:value forKey:key];
+ }
+}
+
++ (void)decodeWithCoder:(NSCoder *)aCoder
+ map:(NSDictionary *)map
+ instance:(id)instance {
+ for (NSString *key in map) {
+ OIDFieldMapping *mapping = map[key];
+ id value = [aCoder decodeObjectOfClass:mapping.expectedType forKey:key];
+ [instance setValue:value forKey:mapping.name];
+ }
+}
+
++ (NSSet *)JSONTypes {
+ return [NSSet setWithArray:@[
+ [NSDictionary class],
+ [NSArray class],
+ [NSString class],
+ [NSNumber class]
+ ]];
+}
+
++ (OIDFieldMappingConversionFunction)URLConversion {
+ return ^id _Nullable(NSObject *_Nullable value) {
+ if ([value isKindOfClass:[NSString class]]) {
+ return [NSURL URLWithString:(NSString *)value];
+ }
+ return value;
+ };
+}
+
++ (OIDFieldMappingConversionFunction)dateSinceNowConversion {
+ return ^id _Nullable(NSObject *_Nullable value) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ return value;
+ }
+ NSNumber *valueAsNumber = (NSNumber *)value;
+ return [NSDate dateWithTimeIntervalSinceNow:[valueAsNumber longLongValue]];
+ };
+}
+
++ (OIDFieldMappingConversionFunction)dateEpochConversion {
+ return ^id _Nullable(NSObject *_Nullable value) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ return value;
+ }
+ NSNumber *valueAsNumber = (NSNumber *) value;
+ return [NSDate dateWithTimeIntervalSince1970:[valueAsNumber longLongValue]];
+ };
+}
+
+@end
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDGrantTypes.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDGrantTypes.h
new file mode 100644
index 0000000000..6e65004731
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDGrantTypes.h
@@ -0,0 +1,40 @@
+/*! @file OIDGrantTypes.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+/*! @brief For exchanging an authorization code for an access token.
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.3
+ */
+extern NSString *const OIDGrantTypeAuthorizationCode;
+
+/*! @brief For refreshing an access token with a refresh token.
+ @see https://tools.ietf.org/html/rfc6749#section-6
+ */
+extern NSString *const OIDGrantTypeRefreshToken;
+
+/*! @brief For obtaining an access token with a username and password.
+ @see https://tools.ietf.org/html/rfc6749#section-4.3.2
+ */
+extern NSString *const OIDGrantTypePassword;
+
+/*! @brief For obtaining an access token from the token endpoint using client credentials.
+ @see https://tools.ietf.org/html/rfc6749#section-3.2.1
+ @see https://tools.ietf.org/html/rfc6749#section-4.4.2
+ */
+extern NSString *const OIDGrantTypeClientCredentials;
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDGrantTypes.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDGrantTypes.m
new file mode 100644
index 0000000000..2b1934370d
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDGrantTypes.m
@@ -0,0 +1,27 @@
+/*! @file OIDGrantTypes.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDGrantTypes.h"
+
+NSString *const OIDGrantTypeAuthorizationCode = @"authorization_code";
+
+NSString *const OIDGrantTypeRefreshToken = @"refresh_token";
+
+NSString *const OIDGrantTypePassword = @"password";
+
+NSString *const OIDGrantTypeClientCredentials = @"client_credentials";
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDIDToken.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDIDToken.h
new file mode 100644
index 0000000000..6fe84d7fe7
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDIDToken.h
@@ -0,0 +1,91 @@
+/*! @file OIDIDToken.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2017 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief A convenience class that parses an ID Token and extracts the claims _but does not_
+ verify its signature. AppAuth only supports the OpenID Code flow, meaning ID Tokens
+ received by AppAuth are sent from the token endpoint on a TLS protected channel,
+ offering some assurances as to the origin of the token. You may wish to additionally
+ verify the ID Token signature using a JWT signature verification library of your
+ choosing.
+ @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken
+ @see https://tools.ietf.org/html/rfc7519
+ @see https://jwt.io/
+ */
+@interface OIDIDToken : NSObject
+
+/*! @internal
+ @brief Unavailable. Please use @c initWithAuthorizationResponse:.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @brief Parses the given ID Token string.
+ @param idToken The ID Token spring.
+ */
+- (nullable instancetype)initWithIDTokenString:(NSString *)idToken;
+
+/*! @brief The header JWT values.
+ */
+@property(nonatomic, readonly) NSDictionary *header;
+
+/*! @brief All ID Token claims.
+ */
+@property(nonatomic, readonly) NSDictionary *claims;
+
+/*! @brief Issuer Identifier for the Issuer of the response.
+ @remarks iss
+ @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken
+ */
+@property(nonatomic, readonly) NSURL *issuer;
+
+/*! @brief Subject Identifier.
+ @remarks sub
+ @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken
+ */
+@property(nonatomic, readonly) NSString *subject;
+
+/*! @brief Audience(s) that this ID Token is intended for.
+ @remarks aud
+ @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken
+ */
+@property(nonatomic, readonly) NSArray *audience;
+
+/*! @brief Expiration time on or after which the ID Token MUST NOT be accepted for processing.
+ @remarks exp
+ @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken
+ */
+@property(nonatomic, readonly) NSDate *expiresAt;
+
+/*! @brief Time at which the JWT was issued.
+ @remarks iat
+ @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken
+ */
+@property(nonatomic, readonly) NSDate *issuedAt;
+
+/*! @brief String value used to associate a Client session with an ID Token, and to mitigate replay
+ attacks.
+ @remarks nonce
+ @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken
+ */
+@property(nonatomic, readonly, nullable) NSString *nonce;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDIDToken.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDIDToken.m
new file mode 100644
index 0000000000..57a7324e80
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDIDToken.m
@@ -0,0 +1,149 @@
+/*! @file OIDIDToken.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2017 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 "OIDIDToken.h"
+
+/*! Field keys associated with an ID Token. */
+static NSString *const kIssKey = @"iss";
+static NSString *const kSubKey = @"sub";
+static NSString *const kAudKey = @"aud";
+static NSString *const kExpKey = @"exp";
+static NSString *const kIatKey = @"iat";
+static NSString *const kNonceKey = @"nonce";
+
+#import "OIDFieldMapping.h"
+
+@implementation OIDIDToken
+
+- (instancetype)initWithIDTokenString:(NSString *)idToken {
+ self = [super init];
+ NSArray *sections = [idToken componentsSeparatedByString:@"."];
+
+ // The header and claims sections are required.
+ if (sections.count <= 1) {
+ return nil;
+ }
+
+ _header = [[self class] parseJWTSection:sections[0]];
+ _claims = [[self class] parseJWTSection:sections[1]];
+ if (!_header || !_claims) {
+ return nil;
+ }
+
+ [OIDFieldMapping remainingParametersWithMap:[[self class] fieldMap]
+ parameters:_claims
+ instance:self];
+
+ // Required fields.
+ if (!_issuer || !_audience || !_subject || !_expiresAt || !_issuedAt) {
+ return nil;
+ }
+
+ return self;
+}
+
+/*! @brief Returns a mapping of incoming parameters to instance variables.
+ @return A mapping of incoming parameters to instance variables.
+ */
++ (NSDictionary *)fieldMap {
+ static NSMutableDictionary *fieldMap;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ fieldMap = [NSMutableDictionary dictionary];
+
+ fieldMap[kIssKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_issuer"
+ type:[NSURL class]
+ conversion:[OIDFieldMapping URLConversion]];
+ fieldMap[kSubKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_subject" type:[NSString class]];
+ fieldMap[kAudKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_audience"
+ type:[NSArray class]
+ conversion:^id _Nullable(NSObject *_Nullable value) {
+ if ([value isKindOfClass:[NSArray class]]) {
+ return value;
+ }
+ if ([value isKindOfClass:[NSString class]]) {
+ return @[value];
+ }
+ return nil;
+ }];
+ fieldMap[kExpKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_expiresAt"
+ type:[NSDate class]
+ conversion:^id _Nullable(NSObject *_Nullable value) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ return value;
+ }
+ NSNumber *valueAsNumber = (NSNumber *)value;
+ return [NSDate dateWithTimeIntervalSince1970:valueAsNumber.longLongValue];
+ }];
+ fieldMap[kIatKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_issuedAt"
+ type:[NSDate class]
+ conversion:^id _Nullable(NSObject *_Nullable value) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ return value;
+ }
+ NSNumber *valueAsNumber = (NSNumber *)value;
+ return [NSDate dateWithTimeIntervalSince1970:valueAsNumber.longLongValue];
+ }];
+ fieldMap[kNonceKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_nonce" type:[NSString class]];
+ });
+ return fieldMap;
+}
+
++ (NSDictionary *)parseJWTSection:(NSString *)sectionString {
+ NSData *decodedData = [[self class] base64urlNoPaddingDecode:sectionString];
+
+ // Parses JSON.
+ NSError *error;
+ id object = [NSJSONSerialization JSONObjectWithData:decodedData options:0 error:&error];
+ if (error) {
+ NSLog(@"Error %@ parsing token payload %@", error, sectionString);
+ }
+ if ([object isKindOfClass:[NSDictionary class]]) {
+ return (NSDictionary *)object;
+ }
+
+ return nil;
+}
+
++ (NSData *)base64urlNoPaddingDecode:(NSString *)base64urlNoPaddingString {
+ NSMutableString *body = [base64urlNoPaddingString mutableCopy];
+
+ // Converts base64url to base64.
+ NSRange range = NSMakeRange(0, base64urlNoPaddingString.length);
+ [body replaceOccurrencesOfString:@"-" withString:@"+" options:NSLiteralSearch range:range];
+ [body replaceOccurrencesOfString:@"_" withString:@"/" options:NSLiteralSearch range:range];
+
+ // Converts base64 no padding to base64 with padding
+ while (body.length % 4 != 0) {
+ [body appendString:@"="];
+ }
+
+ // Decodes base64 string.
+ NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:body options:0];
+ return decodedData;
+}
+
+@end
+
+
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDRegistrationRequest.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDRegistrationRequest.h
new file mode 100644
index 0000000000..e509c60a21
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDRegistrationRequest.h
@@ -0,0 +1,141 @@
+/*! @file OIDRegistrationRequest.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 The AppAuth for iOS Authors. 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
+
+@class OIDAuthorizationResponse;
+@class OIDServiceConfiguration;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Represents a registration request.
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationRequest
+ */
+@interface OIDRegistrationRequest : NSObject
+
+/*! @brief The service's configuration.
+ @remarks This configuration specifies how to connect to a particular OAuth provider.
+ Configurations may be created manually, or via an OpenID Connect Discovery Document.
+ */
+@property(nonatomic, readonly) OIDServiceConfiguration *configuration;
+
+/*! @brief The initial access token to access the Client Registration Endpoint
+ (if required by the OpenID Provider).
+ @remarks OAuth 2.0 Access Token optionally issued by an Authorization Server granting
+ access to its Client Registration Endpoint. This token (if required) is
+ provisioned out of band.
+ @see Section 3 of OpenID Connect Dynamic Client Registration 1.0
+ https://openid.net/specs/openid-connect-registration-1_0.html#ClientRegistration
+ */
+@property(nonatomic, readonly) NSString *initialAccessToken;
+
+/*! @brief The application type to register, will always be 'native'.
+ @remarks application_type
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata
+ */
+@property(nonatomic, readonly) NSString *applicationType;
+
+/*! @brief The client's redirect URI's.
+ @remarks redirect_uris
+ @see https://tools.ietf.org/html/rfc6749#section-3.1.2
+ */
+@property(nonatomic, readonly) NSArray *redirectURIs;
+
+/*! @brief The response types to register for usage by this client.
+ @remarks response_types
+ @see http://openid.net/specs/openid-connect-core-1_0.html#Authentication
+ */
+@property(nonatomic, readonly, nullable) NSArray *responseTypes;
+
+/*! @brief The grant types to register for usage by this client.
+ @remarks grant_types
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata
+ */
+@property(nonatomic, readonly, nullable) NSArray *grantTypes;
+
+/*! @brief The subject type to to request.
+ @remarks subject_type
+ @see http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
+ */
+@property(nonatomic, readonly, nullable) NSString *subjectType;
+
+/*! @brief The client authentication method to use at the token endpoint.
+ @remarks token_endpoint_auth_method
+ @see http://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication
+ */
+@property(nonatomic, readonly, nullable) NSString *tokenEndpointAuthenticationMethod;
+
+/*! @brief The client's additional token request parameters.
+ */
+@property(nonatomic, readonly, nullable) NSDictionary *additionalParameters;
+
+/*! @internal
+ @brief Unavailable. Please use initWithConfiguration
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @brief Create a Client Registration Request to an OpenID Provider that supports open Dynamic
+ Registration.
+ @param configuration The service's configuration.
+ @param redirectURIs The redirect URIs to register for the client.
+ @param responseTypes The response types to register for the client.
+ @param grantTypes The grant types to register for the client.
+ @param subjectType The subject type to register for the client.
+ @param tokenEndpointAuthMethod The token endpoint authentication method to register for the
+ client.
+ @param additionalParameters The client's additional registration request parameters.
+ */
+- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
+ redirectURIs:(NSArray *)redirectURIs
+ responseTypes:(nullable NSArray *)responseTypes
+ grantTypes:(nullable NSArray *)grantTypes
+ subjectType:(nullable NSString *)subjectType
+ tokenEndpointAuthMethod:(nullable NSString *)tokenEndpointAuthMethod
+ additionalParameters:(nullable NSDictionary *)additionalParameters;
+
+/*! @brief Designated initializer.
+ @param configuration The service's configuration.
+ @param redirectURIs The redirect URIs to register for the client.
+ @param responseTypes The response types to register for the client.
+ @param grantTypes The grant types to register for the client.
+ @param subjectType The subject type to register for the client.
+ @param tokenEndpointAuthMethod The token endpoint authentication method to register for the
+ client.
+ @param initialAccessToken The initial access token to access the Client Registration Endpoint
+ (if required by the OpenID Provider).
+ @param additionalParameters The client's additional registration request parameters.
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#ClientRegistration
+ */
+- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
+ redirectURIs:(NSArray *)redirectURIs
+ responseTypes:(nullable NSArray *)responseTypes
+ grantTypes:(nullable NSArray *)grantTypes
+ subjectType:(nullable NSString *)subjectType
+ tokenEndpointAuthMethod:(nullable NSString *)tokenEndpointAuthMethod
+ initialAccessToken:(nullable NSString *)initialAccessToken
+ additionalParameters:(nullable NSDictionary *)additionalParameters
+ NS_DESIGNATED_INITIALIZER;
+
+/*! @brief Constructs an @c NSURLRequest representing the registration request.
+ @return An @c NSURLRequest representing the registration request.
+ */
+- (NSURLRequest *)URLRequest;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDRegistrationRequest.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDRegistrationRequest.m
new file mode 100644
index 0000000000..9efd18fddb
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDRegistrationRequest.m
@@ -0,0 +1,248 @@
+/*! @file OIDRegistrationRequest.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 The AppAuth for iOS Authors. 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 "OIDRegistrationRequest.h"
+
+#import "OIDClientMetadataParameters.h"
+#import "OIDDefines.h"
+#import "OIDServiceConfiguration.h"
+
+/*! @brief The key for the @c configuration property for @c NSSecureCoding
+ */
+static NSString *const kConfigurationKey = @"configuration";
+
+/*! @brief The key for the @c initialAccessToken property for @c NSSecureCoding
+ */
+static NSString *const kInitialAccessToken = @"initial_access_token";
+
+/*! @brief Key used to encode the @c redirectURIs property for @c NSSecureCoding
+ */
+static NSString *const kRedirectURIsKey = @"redirect_uris";
+
+/*! @brief The key for the @c responseTypes property for @c NSSecureCoding.
+ */
+static NSString *const kResponseTypesKey = @"response_types";
+
+/*! @brief Key used to encode the @c grantType property for @c NSSecureCoding
+ */
+static NSString *const kGrantTypesKey = @"grant_types";
+
+/*! @brief Key used to encode the @c subjectType property for @c NSSecureCoding
+ */
+static NSString *const kSubjectTypeKey = @"subject_type";
+
+/*! @brief Key used to encode the @c additionalParameters property for
+ @c NSSecureCoding
+ */
+static NSString *const kAdditionalParametersKey = @"additionalParameters";
+
+@implementation OIDRegistrationRequest
+
+#pragma mark - Initializers
+
+- (instancetype)init
+ OID_UNAVAILABLE_USE_INITIALIZER(
+ @selector(initWithConfiguration:
+ redirectURIs:
+ responseTypes:
+ grantTypes:
+ subjectType:
+ tokenEndpointAuthMethod:
+ additionalParameters:)
+ )
+
+- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
+ redirectURIs:(NSArray *)redirectURIs
+ responseTypes:(nullable NSArray *)responseTypes
+ grantTypes:(nullable NSArray *)grantTypes
+ subjectType:(nullable NSString *)subjectType
+ tokenEndpointAuthMethod:(nullable NSString *)tokenEndpointAuthenticationMethod
+ additionalParameters:(nullable NSDictionary *)additionalParameters {
+ return [self initWithConfiguration:configuration
+ redirectURIs:redirectURIs
+ responseTypes:responseTypes
+ grantTypes:grantTypes
+ subjectType:subjectType
+ tokenEndpointAuthMethod:tokenEndpointAuthenticationMethod
+ initialAccessToken:nil
+ additionalParameters:additionalParameters];
+}
+
+- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
+ redirectURIs:(NSArray *)redirectURIs
+ responseTypes:(nullable NSArray *)responseTypes
+ grantTypes:(nullable NSArray *)grantTypes
+ subjectType:(nullable NSString *)subjectType
+ tokenEndpointAuthMethod:(nullable NSString *)tokenEndpointAuthenticationMethod
+ initialAccessToken:(nullable NSString *)initialAccessToken
+ additionalParameters:(nullable NSDictionary *)additionalParameters {
+ self = [super init];
+ if (self) {
+ _configuration = [configuration copy];
+ _initialAccessToken = [initialAccessToken copy];
+ _redirectURIs = [redirectURIs copy];
+ _responseTypes = [responseTypes copy];
+ _grantTypes = [grantTypes copy];
+ _subjectType = [subjectType copy];
+ _tokenEndpointAuthenticationMethod = [tokenEndpointAuthenticationMethod copy];
+ _additionalParameters =
+ [[NSDictionary alloc] initWithDictionary:additionalParameters copyItems:YES];
+
+ _applicationType = OIDApplicationTypeNative;
+ }
+ return self;
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(nullable NSZone *)zone {
+ // The documentation for NSCopying specifically advises us to return a reference to the original
+ // instance in the case where instances are immutable (as ours is):
+ // "Implement NSCopying by retaining the original instead of creating a new copy when the class
+ // and its contents are immutable."
+ return self;
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+ return YES;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+ OIDServiceConfiguration *configuration =
+ [aDecoder decodeObjectOfClass:[OIDServiceConfiguration class]
+ forKey:kConfigurationKey];
+ NSString *initialAccessToken = [aDecoder decodeObjectOfClass:[NSString class]
+ forKey:kInitialAccessToken];
+ NSArray *redirectURIs = [aDecoder decodeObjectOfClass:[NSArray class]
+ forKey:kRedirectURIsKey];
+ NSArray *responseTypes = [aDecoder decodeObjectOfClass:[NSArray class]
+ forKey:kResponseTypesKey];
+ NSArray *grantTypes = [aDecoder decodeObjectOfClass:[NSArray class]
+ forKey:kGrantTypesKey];
+ NSString *subjectType = [aDecoder decodeObjectOfClass:[NSString class]
+ forKey:kSubjectTypeKey];
+ NSString *tokenEndpointAuthenticationMethod =
+ [aDecoder decodeObjectOfClass:[NSString class]
+ forKey:OIDTokenEndpointAuthenticationMethodParam];
+ NSSet *additionalParameterCodingClasses = [NSSet setWithArray:@[ [NSDictionary class],
+ [NSString class] ]];
+ NSDictionary *additionalParameters =
+ [aDecoder decodeObjectOfClasses:additionalParameterCodingClasses
+ forKey:kAdditionalParametersKey];
+ self = [self initWithConfiguration:configuration
+ redirectURIs:redirectURIs
+ responseTypes:responseTypes
+ grantTypes:grantTypes
+ subjectType:subjectType
+ tokenEndpointAuthMethod:tokenEndpointAuthenticationMethod
+ initialAccessToken:initialAccessToken
+ additionalParameters:additionalParameters];
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+ [aCoder encodeObject:_configuration forKey:kConfigurationKey];
+ [aCoder encodeObject:_initialAccessToken forKey:kInitialAccessToken];
+ [aCoder encodeObject:_redirectURIs forKey:kRedirectURIsKey];
+ [aCoder encodeObject:_responseTypes forKey:kResponseTypesKey];
+ [aCoder encodeObject:_grantTypes forKey:kGrantTypesKey];
+ [aCoder encodeObject:_subjectType forKey:kSubjectTypeKey];
+ [aCoder encodeObject:_tokenEndpointAuthenticationMethod
+ forKey:OIDTokenEndpointAuthenticationMethodParam];
+ [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey];
+}
+
+#pragma mark - NSObject overrides
+
+- (NSString *)description {
+ NSURLRequest *request = [self URLRequest];
+ NSString *requestBody = [[NSString alloc] initWithData:request.HTTPBody
+ encoding:NSUTF8StringEncoding];
+ return [NSString stringWithFormat:@"<%@: %p, request: >",
+ NSStringFromClass([self class]),
+ (void *)self,
+ request.URL,
+ requestBody];
+}
+
+- (NSURLRequest *)URLRequest {
+ static NSString *const kHTTPPost = @"POST";
+ static NSString *const kBearer = @"Bearer";
+ static NSString *const kHTTPContentTypeHeaderKey = @"Content-Type";
+ static NSString *const kHTTPContentTypeHeaderValue = @"application/json";
+ static NSString *const kHTTPAuthorizationHeaderKey = @"Authorization";
+
+ NSData *postBody = [self JSONString];
+ if (!postBody) {
+ return nil;
+ }
+
+ NSURL *registrationRequestURL = _configuration.registrationEndpoint;
+ NSMutableURLRequest *URLRequest =
+ [[NSURLRequest requestWithURL:registrationRequestURL] mutableCopy];
+ URLRequest.HTTPMethod = kHTTPPost;
+ [URLRequest setValue:kHTTPContentTypeHeaderValue forHTTPHeaderField:kHTTPContentTypeHeaderKey];
+ if (_initialAccessToken) {
+ NSString *value = [NSString stringWithFormat:@"%@ %@", kBearer, _initialAccessToken];
+ [URLRequest setValue:value forHTTPHeaderField:kHTTPAuthorizationHeaderKey];
+ }
+ URLRequest.HTTPBody = postBody;
+ return URLRequest;
+}
+
+- (NSData *)JSONString {
+ // Dictionary with several kay/value pairs and the above array of arrays
+ NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
+ NSMutableArray *redirectURIStrings =
+ [NSMutableArray arrayWithCapacity:[_redirectURIs count]];
+ for (id obj in _redirectURIs) {
+ [redirectURIStrings addObject:[obj absoluteString]];
+ }
+ dict[OIDRedirectURIsParam] = redirectURIStrings;
+ dict[OIDApplicationTypeParam] = _applicationType;
+
+ if (_additionalParameters) {
+ // Add any additional parameters first to allow them
+ // to be overwritten by instance values
+ [dict addEntriesFromDictionary:_additionalParameters];
+ }
+ if (_responseTypes) {
+ dict[OIDResponseTypesParam] = _responseTypes;
+ }
+ if (_grantTypes) {
+ dict[OIDGrantTypesParam] = _grantTypes;
+ }
+ if (_subjectType) {
+ dict[OIDSubjectTypeParam] = _subjectType;
+ }
+ if (_tokenEndpointAuthenticationMethod) {
+ dict[OIDTokenEndpointAuthenticationMethodParam] = _tokenEndpointAuthenticationMethod;
+ }
+
+ NSError *error;
+ NSData *json = [NSJSONSerialization dataWithJSONObject:dict options:kNilOptions error:&error];
+ if (json == nil || error != nil) {
+ return nil;
+ }
+
+ return json;
+}
+
+@end
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDRegistrationResponse.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDRegistrationResponse.h
new file mode 100644
index 0000000000..df62390640
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDRegistrationResponse.h
@@ -0,0 +1,126 @@
+/*! @file OIDRegistrationResponse.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 The AppAuth for iOS Authors. 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
+
+@class OIDRegistrationRequest;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Parameter name for the client id.
+ */
+extern NSString *const OIDClientIDParam;
+
+/*! @brief Parameter name for the client id issuance timestamp.
+ */
+extern NSString *const OIDClientIDIssuedAtParam;
+
+/*! @brief Parameter name for the client secret.
+ */
+extern NSString *const OIDClientSecretParam;
+
+/*! @brief Parameter name for the client secret expiration time.
+ */
+extern NSString *const OIDClientSecretExpirestAtParam;
+
+/*! @brief Parameter name for the registration access token.
+ */
+extern NSString *const OIDRegistrationAccessTokenParam;
+
+/*! @brief Parameter name for the client configuration URI.
+ */
+extern NSString *const OIDRegistrationClientURIParam;
+
+/*! @brief Represents a registration response.
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse
+ */
+@interface OIDRegistrationResponse : NSObject
+
+/*! @brief The request which was serviced.
+ */
+@property(nonatomic, readonly) OIDRegistrationRequest *request;
+
+/*! @brief The registered client identifier.
+ @remarks client_id
+ @see https://tools.ietf.org/html/rfc6749#section-4
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.1
+ */
+@property(nonatomic, readonly) NSString *clientID;
+
+/*! @brief Timestamp of when the client identifier was issued, if provided.
+ @remarks client_id_issued_at
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse
+ */
+@property(nonatomic, readonly, nullable) NSDate *clientIDIssuedAt;
+
+/*! @brief TThe client secret, which is part of the client credentials, if provided.
+ @remarks client_secret
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse
+ */
+@property(nonatomic, readonly, nullable) NSString *clientSecret;
+
+/*! @brief Timestamp of when the client credentials expires, if provided.
+ @remarks client_secret_expires_at
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse
+ */
+@property(nonatomic, readonly, nullable) NSDate *clientSecretExpiresAt;
+
+/*! @brief Client registration access token that can be used for subsequent operations upon the
+ client registration.
+ @remarks registration_access_token
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse
+ */
+@property(nonatomic, readonly, nullable) NSString *registrationAccessToken;
+
+/*! @brief Location of the client configuration endpoint, if provided.
+ @remarks registration_client_uri
+ @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse
+ */
+@property(nonatomic, readonly, nullable) NSURL *registrationClientURI;
+
+/*! @brief Client authentication method to use at the token endpoint, if provided.
+ @remarks token_endpoint_auth_method
+ @see http://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication
+ */
+@property(nonatomic, readonly, nullable) NSString *tokenEndpointAuthenticationMethod;
+
+/*! @brief Additional parameters returned from the token server.
+ */
+@property(nonatomic, readonly, nullable) NSDictionary *>
+ *additionalParameters;
+
+/*! @internal
+ @brief Unavailable. Please use initWithRequest
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @brief Designated initializer.
+ @param request The serviced request.
+ @param parameters The decoded parameters returned from the Authorization Server.
+ @remarks Known parameters are extracted from the @c parameters parameter and the normative
+ properties are populated. Non-normative parameters are placed in the
+ @c #additionalParameters dictionary.
+ */
+- (instancetype)initWithRequest:(OIDRegistrationRequest *)request
+ parameters:(NSDictionary *> *)parameters
+ NS_DESIGNATED_INITIALIZER;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDRegistrationResponse.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDRegistrationResponse.m
new file mode 100644
index 0000000000..ec0411b798
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDRegistrationResponse.m
@@ -0,0 +1,164 @@
+/*! @file OIDRegistrationResponse.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2016 The AppAuth for iOS Authors. 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 "OIDRegistrationResponse.h"
+
+#import "OIDClientMetadataParameters.h"
+#import "OIDDefines.h"
+#import "OIDFieldMapping.h"
+#import "OIDRegistrationRequest.h"
+#import "OIDTokenUtilities.h"
+
+NSString *const OIDClientIDParam = @"client_id";
+NSString *const OIDClientIDIssuedAtParam = @"client_id_issued_at";
+NSString *const OIDClientSecretParam = @"client_secret";
+NSString *const OIDClientSecretExpirestAtParam = @"client_secret_expires_at";
+NSString *const OIDRegistrationAccessTokenParam = @"registration_access_token";
+NSString *const OIDRegistrationClientURIParam = @"registration_client_uri";
+
+/*! @brief Key used to encode the @c request property for @c NSSecureCoding
+ */
+static NSString *const kRequestKey = @"request";
+
+/*! @brief Key used to encode the @c additionalParameters property for @c NSSecureCoding
+ */
+static NSString *const kAdditionalParametersKey = @"additionalParameters";
+
+@implementation OIDRegistrationResponse
+
+/*! @brief Returns a mapping of incoming parameters to instance variables.
+ @return A mapping of incoming parameters to instance variables.
+ */
++ (NSDictionary *)fieldMap {
+ static NSMutableDictionary *fieldMap;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ fieldMap = [NSMutableDictionary dictionary];
+ fieldMap[OIDClientIDParam] = [[OIDFieldMapping alloc] initWithName:@"_clientID"
+ type:[NSString class]];
+ fieldMap[OIDClientIDIssuedAtParam] =
+ [[OIDFieldMapping alloc] initWithName:@"_clientIDIssuedAt"
+ type:[NSDate class]
+ conversion:[OIDFieldMapping dateEpochConversion]];
+ fieldMap[OIDClientSecretParam] =
+ [[OIDFieldMapping alloc] initWithName:@"_clientSecret"
+ type:[NSString class]];
+ fieldMap[OIDClientSecretExpirestAtParam] =
+ [[OIDFieldMapping alloc] initWithName:@"_clientSecretExpiresAt"
+ type:[NSDate class]
+ conversion:[OIDFieldMapping dateEpochConversion]];
+ fieldMap[OIDRegistrationAccessTokenParam] =
+ [[OIDFieldMapping alloc] initWithName:@"_registrationAccessToken"
+ type:[NSString class]];
+ fieldMap[OIDRegistrationClientURIParam] =
+ [[OIDFieldMapping alloc] initWithName:@"_registrationClientURI"
+ type:[NSURL class]
+ conversion:[OIDFieldMapping URLConversion]];
+ fieldMap[OIDTokenEndpointAuthenticationMethodParam] =
+ [[OIDFieldMapping alloc] initWithName:@"_tokenEndpointAuthenticationMethod"
+ type:[NSString class]];
+ });
+ return fieldMap;
+}
+
+
+#pragma mark - Initializers
+
+- (nonnull instancetype)init
+ OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithRequest:parameters:))
+
+- (instancetype)initWithRequest:(OIDRegistrationRequest *)request
+ parameters:(NSDictionary *> *)parameters {
+ self = [super init];
+ if (self) {
+ _request = [request copy];
+ NSDictionary *> *additionalParameters =
+ [OIDFieldMapping remainingParametersWithMap:[[self class] fieldMap]
+ parameters:parameters
+ instance:self];
+ _additionalParameters = additionalParameters;
+
+ if ((_clientSecret && !_clientSecretExpiresAt)
+ || (!!_registrationClientURI != !!_registrationAccessToken)) {
+ // If client_secret is issued, client_secret_expires_at is REQUIRED,
+ // and the response MUST contain "[...] both a Client Configuration Endpoint
+ // and a Registration Access Token or neither of them"
+ return nil;
+ }
+ }
+ return self;
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(nullable NSZone *)zone {
+ // The documentation for NSCopying specifically advises us to return a reference to the original
+ // instance in the case where instances are immutable (as ours is):
+ // "Implement NSCopying by retaining the original instead of creating a new copy when the class
+ // and its contents are immutable."
+ return self;
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+ return YES;
+}
+
+- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
+ OIDRegistrationRequest *request = [aDecoder decodeObjectOfClass:[OIDRegistrationRequest class]
+ forKey:kRequestKey];
+ self = [self initWithRequest:request
+ parameters:@{}];
+ if (self) {
+ [OIDFieldMapping decodeWithCoder:aDecoder
+ map:[[self class] fieldMap]
+ instance:self];
+ _additionalParameters = [aDecoder decodeObjectOfClasses:[OIDFieldMapping JSONTypes]
+ forKey:kAdditionalParametersKey];
+ }
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+ [OIDFieldMapping encodeWithCoder:aCoder map:[[self class] fieldMap] instance:self];
+ [aCoder encodeObject:_request forKey:kRequestKey];
+ [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey];
+}
+
+#pragma mark - NSObject overrides
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@: %p, clientID: \"%@\", clientIDIssuedAt: %@, "
+ "clientSecret: %@, clientSecretExpiresAt: \"%@\", "
+ "registrationAccessToken: \"%@\", "
+ "registrationClientURI: \"%@\", "
+ "additionalParameters: %@, request: %@>",
+ NSStringFromClass([self class]),
+ (void *)self,
+ _clientID,
+ _clientIDIssuedAt,
+ [OIDTokenUtilities redact:_clientSecret],
+ _clientSecretExpiresAt,
+ [OIDTokenUtilities redact:_registrationAccessToken],
+ _registrationClientURI,
+ _additionalParameters,
+ _request];
+}
+
+@end
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDResponseTypes.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDResponseTypes.h
new file mode 100644
index 0000000000..405ef9381d
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDResponseTypes.h
@@ -0,0 +1,31 @@
+/*! @file OIDResponseTypes.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+/*! @brief A constant for the standard OAuth2 Response Type of 'code'.
+ */
+extern NSString *const OIDResponseTypeCode;
+
+/*! @brief A constant for the standard OAuth2 Response Type of 'token'.
+ */
+extern NSString *const OIDResponseTypeToken;
+
+/*! @brief A constant for the standard OAuth2 Response Type of 'id_token'.
+ */
+extern NSString *const OIDResponseTypeIDToken;
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDResponseTypes.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDResponseTypes.m
new file mode 100644
index 0000000000..78eaf187e1
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDResponseTypes.m
@@ -0,0 +1,25 @@
+/*! @file OIDResponseTypes.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDResponseTypes.h"
+
+NSString *const OIDResponseTypeCode = @"code";
+
+NSString *const OIDResponseTypeToken = @"token";
+
+NSString *const OIDResponseTypeIDToken = @"id_token";
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDScopeUtilities.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDScopeUtilities.h
new file mode 100644
index 0000000000..c0a5190cb0
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDScopeUtilities.h
@@ -0,0 +1,48 @@
+/*! @file OIDScopeUtilities.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Provides convenience methods for dealing with scope strings.
+ */
+@interface OIDScopeUtilities : NSObject
+
+/*! @internal
+ @brief Unavailable. This class should not be initialized.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @brief Converts an array of scope strings to a single scope string per the OAuth 2 spec.
+ @param scopes An array of scope strings.
+ @return A space-delimited string of scopes.
+ @see https://tools.ietf.org/html/rfc6749#section-3.3
+ */
++ (NSString *)scopesWithArray:(NSArray *)scopes;
+
+/*! @brief Converts an OAuth 2 spec-compliant scope string to an array of scopes.
+ @param scopes An OAuth 2 spec-compliant scope string.
+ @return An array of scope strings.
+ @see https://tools.ietf.org/html/rfc6749#section-3.3
+ */
++ (NSArray *)scopesArrayWithString:(NSString *)scopes;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDScopeUtilities.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDScopeUtilities.m
new file mode 100644
index 0000000000..a0bcb8c85d
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDScopeUtilities.m
@@ -0,0 +1,58 @@
+/*! @file OIDScopeUtilities.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDScopeUtilities.h"
+
+@implementation OIDScopeUtilities
+
+/*! @brief A character set with the characters NOT allowed in a scope name.
+ @see https://tools.ietf.org/html/rfc6749#section-3.3
+ */
++ (NSCharacterSet *)disallowedScopeCharacters {
+ static NSCharacterSet *disallowedCharacters;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ NSMutableCharacterSet *allowedCharacters;
+ allowedCharacters =
+ [NSMutableCharacterSet characterSetWithRange:NSMakeRange(0x23, 0x5B - 0x23 + 1)];
+ [allowedCharacters addCharactersInRange:NSMakeRange(0x5D, 0x7E - 0x5D + 1)];
+ [allowedCharacters addCharactersInString:@"\x21"];
+ disallowedCharacters = [allowedCharacters invertedSet];
+ });
+ return disallowedCharacters;
+}
+
++ (NSString *)scopesWithArray:(NSArray *)scopes {
+#if !defined(NS_BLOCK_ASSERTIONS)
+ NSCharacterSet *disallowedCharacters = [self disallowedScopeCharacters];
+ for (NSString *scope in scopes) {
+ NSAssert(scope.length, @"Found illegal empty scope string.");
+ NSAssert([scope rangeOfCharacterFromSet:disallowedCharacters].location == NSNotFound,
+ @"Found illegal character in scope string.");
+ }
+#endif // !defined(NS_BLOCK_ASSERTIONS)
+
+ NSString *scopeString = [scopes componentsJoinedByString:@" "];
+ return scopeString;
+}
+
++ (NSArray *)scopesArrayWithString:(NSString *)scopes {
+ return [scopes componentsSeparatedByString:@" "];
+}
+
+@end
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDScopes.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDScopes.h
new file mode 100644
index 0000000000..da8bb189f1
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDScopes.h
@@ -0,0 +1,46 @@
+/*! @file OIDScopes.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+/*! @brief Scope that indicates this request is an OpenID Connect request.
+ @see http://openid.net/specs/openid-connect-core-1_0.html#AuthRequestValidation
+ */
+extern NSString *const OIDScopeOpenID;
+
+/*! @brief This scope value requests access to the End-User's default profile Claims, which are:
+ name, family_name, given_name, middle_name, nickname, preferred_username, profile, picture,
+ website, gender, birthdate, zoneinfo, locale, and updated_at.
+ @see http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims
+ */
+extern NSString *const OIDScopeProfile;
+
+/*! @brief This scope value requests access to the email and email_verified Claims.
+ @see http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims
+ */
+extern NSString *const OIDScopeEmail;
+
+/*! @brief This scope value requests access to the address Claim.
+ @see http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims
+ */
+extern NSString *const OIDScopeAddress;
+
+/*! @brief This scope value requests access to the phone_number and phone_number_verified Claims.
+ @see http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims
+ */
+extern NSString *const OIDScopePhone;
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDScopes.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDScopes.m
new file mode 100644
index 0000000000..62dd707ec0
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDScopes.m
@@ -0,0 +1,29 @@
+/*! @file OIDScopes.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDScopes.h"
+
+NSString *const OIDScopeOpenID = @"openid";
+
+NSString *const OIDScopeProfile = @"profile";
+
+NSString *const OIDScopeEmail = @"email";
+
+NSString *const OIDScopeAddress = @"address";
+
+NSString *const OIDScopePhone = @"phone";
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDServiceConfiguration.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDServiceConfiguration.h
new file mode 100644
index 0000000000..a072a478f9
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDServiceConfiguration.h
@@ -0,0 +1,118 @@
+/*! @file OIDServiceConfiguration.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+@class OIDServiceConfiguration;
+@class OIDServiceDiscovery;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief The type of block called when a @c OIDServiceConfiguration has been created
+ by loading a @c OIDServiceDiscovery from an @c NSURL.
+ */
+typedef void (^OIDServiceConfigurationCreated)
+ (OIDServiceConfiguration *_Nullable serviceConfiguration,
+ NSError *_Nullable error);
+
+/*! @brief Represents the information needed to construct a @c OIDAuthorizationService.
+ */
+@interface OIDServiceConfiguration : NSObject
+
+/*! @brief The authorization endpoint URI.
+ */
+@property(nonatomic, readonly) NSURL *authorizationEndpoint;
+
+/*! @brief The token exchange and refresh endpoint URI.
+ */
+@property(nonatomic, readonly) NSURL *tokenEndpoint;
+
+/*! @brief The OpenID Connect issuer.
+ */
+@property(nonatomic, readonly, nullable) NSURL *issuer;
+
+/*! @brief The dynamic client registration endpoint URI.
+ */
+@property(nonatomic, readonly, nullable) NSURL *registrationEndpoint;
+
+/*! @brief The end session logout endpoint URI.
+ */
+@property(nonatomic, readonly, nullable) NSURL *endSessionEndpoint;
+
+/*! @brief The discovery document.
+ */
+@property(nonatomic, readonly, nullable) OIDServiceDiscovery *discoveryDocument;
+
+/*! @internal
+ @brief Unavailable. Please use @c initWithAuthorizationEndpoint:tokenEndpoint: or
+ @c initWithDiscoveryDocument:.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @param authorizationEndpoint The authorization endpoint URI.
+ @param tokenEndpoint The token exchange and refresh endpoint URI.
+ */
+- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint
+ tokenEndpoint:(NSURL *)tokenEndpoint;
+
+/*! @param authorizationEndpoint The authorization endpoint URI.
+ @param tokenEndpoint The token exchange and refresh endpoint URI.
+ @param registrationEndpoint The dynamic client registration endpoint URI.
+ */
+- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint
+ tokenEndpoint:(NSURL *)tokenEndpoint
+ registrationEndpoint:(nullable NSURL *)registrationEndpoint;
+
+/*! @param authorizationEndpoint The authorization endpoint URI.
+ @param tokenEndpoint The token exchange and refresh endpoint URI.
+ @param issuer The OpenID Connect issuer.
+ */
+- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint
+ tokenEndpoint:(NSURL *)tokenEndpoint
+ issuer:(nullable NSURL *)issuer;
+
+/*! @param authorizationEndpoint The authorization endpoint URI.
+ @param tokenEndpoint The token exchange and refresh endpoint URI.
+ @param issuer The OpenID Connect issuer.
+ @param registrationEndpoint The dynamic client registration endpoint URI.
+ */
+- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint
+ tokenEndpoint:(NSURL *)tokenEndpoint
+ issuer:(nullable NSURL *)issuer
+ registrationEndpoint:(nullable NSURL *)registrationEndpoint;
+
+/*! @param authorizationEndpoint The authorization endpoint URI.
+ @param tokenEndpoint The token exchange and refresh endpoint URI.
+ @param issuer The OpenID Connect issuer.
+ @param registrationEndpoint The dynamic client registration endpoint URI.
+ @param endSessionEndpoint The end session endpoint (logout) URI.
+ */
+- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint
+ tokenEndpoint:(NSURL *)tokenEndpoint
+ issuer:(nullable NSURL *)issuer
+ registrationEndpoint:(nullable NSURL *)registrationEndpoint
+ endSessionEndpoint:(nullable NSURL *)endSessionEndpoint;
+
+/*! @param discoveryDocument The discovery document from which to extract the required OAuth
+ configuration.
+ */
+- (instancetype)initWithDiscoveryDocument:(OIDServiceDiscovery *)discoveryDocument;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDServiceConfiguration.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDServiceConfiguration.m
new file mode 100644
index 0000000000..ca48a8c332
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDServiceConfiguration.m
@@ -0,0 +1,223 @@
+/*! @file OIDServiceConfiguration.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDServiceConfiguration.h"
+
+#import "OIDDefines.h"
+#import "OIDErrorUtilities.h"
+#import "OIDServiceDiscovery.h"
+
+/*! @brief The key for the @c authorizationEndpoint property.
+ */
+static NSString *const kAuthorizationEndpointKey = @"authorizationEndpoint";
+
+/*! @brief The key for the @c tokenEndpoint property.
+ */
+static NSString *const kTokenEndpointKey = @"tokenEndpoint";
+
+/*! @brief The key for the @c issuer property.
+ */
+static NSString *const kIssuerKey = @"issuer";
+
+/*! @brief The key for the @c registrationEndpoint property.
+ */
+static NSString *const kRegistrationEndpointKey = @"registrationEndpoint";
+
+/*! @brief The key for the @c endSessionEndpoint property.
+ */
+static NSString *const kEndSessionEndpointKey = @"endSessionEndpoint";
+
+/*! @brief The key for the @c discoveryDocument property.
+ */
+static NSString *const kDiscoveryDocumentKey = @"discoveryDocument";
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OIDServiceConfiguration ()
+
+- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint
+ tokenEndpoint:(NSURL *)tokenEndpoint
+ issuer:(nullable NSURL *)issuer
+ registrationEndpoint:(nullable NSURL *)registrationEndpoint
+ endSessionEndpoint:(nullable NSURL *)endSessionEndpoint
+ discoveryDocument:(nullable OIDServiceDiscovery *)discoveryDocument
+ NS_DESIGNATED_INITIALIZER;
+
+@end
+
+@implementation OIDServiceConfiguration
+
+- (instancetype)init
+ OID_UNAVAILABLE_USE_INITIALIZER(@selector(
+ initWithAuthorizationEndpoint:
+ tokenEndpoint:)
+ )
+
+- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint
+ tokenEndpoint:(NSURL *)tokenEndpoint
+ issuer:(nullable NSURL *)issuer
+ registrationEndpoint:(nullable NSURL *)registrationEndpoint
+ endSessionEndpoint:(nullable OIDServiceDiscovery *)endSessionEndpoint
+ discoveryDocument:(nullable OIDServiceDiscovery *)discoveryDocument {
+
+ self = [super init];
+ if (self) {
+ _authorizationEndpoint = [authorizationEndpoint copy];
+ _tokenEndpoint = [tokenEndpoint copy];
+ _issuer = [issuer copy];
+ _registrationEndpoint = [registrationEndpoint copy];
+ _endSessionEndpoint = [endSessionEndpoint copy];
+ _discoveryDocument = [discoveryDocument copy];
+ }
+ return self;
+}
+
+- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint
+ tokenEndpoint:(NSURL *)tokenEndpoint {
+ return [self initWithAuthorizationEndpoint:authorizationEndpoint
+ tokenEndpoint:tokenEndpoint
+ issuer:nil
+ registrationEndpoint:nil
+ endSessionEndpoint:nil
+ discoveryDocument:nil];
+}
+
+- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint
+ tokenEndpoint:(NSURL *)tokenEndpoint
+ registrationEndpoint:(nullable NSURL *)registrationEndpoint {
+ return [self initWithAuthorizationEndpoint:authorizationEndpoint
+ tokenEndpoint:tokenEndpoint
+ issuer:nil
+ registrationEndpoint:registrationEndpoint
+ endSessionEndpoint:nil
+ discoveryDocument:nil];
+}
+
+- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint
+ tokenEndpoint:(NSURL *)tokenEndpoint
+ issuer:(nullable NSURL *)issuer {
+ return [self initWithAuthorizationEndpoint:authorizationEndpoint
+ tokenEndpoint:tokenEndpoint
+ issuer:issuer
+ registrationEndpoint:nil
+ endSessionEndpoint:nil
+ discoveryDocument:nil];
+}
+
+- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint
+ tokenEndpoint:(NSURL *)tokenEndpoint
+ issuer:(nullable NSURL *)issuer
+ registrationEndpoint:(nullable NSURL *)registrationEndpoint {
+ return [self initWithAuthorizationEndpoint:authorizationEndpoint
+ tokenEndpoint:tokenEndpoint
+ issuer:issuer
+ registrationEndpoint:registrationEndpoint
+ endSessionEndpoint:nil
+ discoveryDocument:nil];
+}
+
+- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint
+ tokenEndpoint:(NSURL *)tokenEndpoint
+ issuer:(nullable NSURL *)issuer
+ registrationEndpoint:(nullable NSURL *)registrationEndpoint
+ endSessionEndpoint:(nullable NSURL *)endSessionEndpoint {
+ return [self initWithAuthorizationEndpoint:authorizationEndpoint
+ tokenEndpoint:tokenEndpoint
+ issuer:issuer
+ registrationEndpoint:registrationEndpoint
+ endSessionEndpoint:endSessionEndpoint
+ discoveryDocument:nil];
+}
+
+- (instancetype)initWithDiscoveryDocument:(OIDServiceDiscovery *) discoveryDocument {
+ return [self initWithAuthorizationEndpoint:discoveryDocument.authorizationEndpoint
+ tokenEndpoint:discoveryDocument.tokenEndpoint
+ issuer:discoveryDocument.issuer
+ registrationEndpoint:discoveryDocument.registrationEndpoint
+ endSessionEndpoint:discoveryDocument.endSessionEndpoint
+ discoveryDocument:discoveryDocument];
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(nullable NSZone *)zone {
+ // The documentation for NSCopying specifically advises us to return a reference to the original
+ // instance in the case where instances are immutable (as ours is):
+ // "Implement NSCopying by retaining the original instead of creating a new copy when the class
+ // and its contents are immutable."
+ return self;
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+ return YES;
+}
+
+- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
+ NSURL *authorizationEndpoint = [aDecoder decodeObjectOfClass:[NSURL class]
+ forKey:kAuthorizationEndpointKey];
+ NSURL *tokenEndpoint = [aDecoder decodeObjectOfClass:[NSURL class]
+ forKey:kTokenEndpointKey];
+ NSURL *issuer = [aDecoder decodeObjectOfClass:[NSURL class]
+ forKey:kIssuerKey];
+ NSURL *registrationEndpoint = [aDecoder decodeObjectOfClass:[NSURL class]
+ forKey:kRegistrationEndpointKey];
+ NSURL *endSessionEndpoint = [aDecoder decodeObjectOfClass:[NSURL class]
+ forKey:kEndSessionEndpointKey];
+ // We don't accept nil authorizationEndpoints or tokenEndpoints.
+ if (!authorizationEndpoint || !tokenEndpoint) {
+ return nil;
+ }
+
+ OIDServiceDiscovery *discoveryDocument = [aDecoder decodeObjectOfClass:[OIDServiceDiscovery class]
+ forKey:kDiscoveryDocumentKey];
+
+ return [self initWithAuthorizationEndpoint:authorizationEndpoint
+ tokenEndpoint:tokenEndpoint
+ issuer:issuer
+ registrationEndpoint:registrationEndpoint
+ endSessionEndpoint:endSessionEndpoint
+ discoveryDocument:discoveryDocument];
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+ [aCoder encodeObject:_authorizationEndpoint forKey:kAuthorizationEndpointKey];
+ [aCoder encodeObject:_tokenEndpoint forKey:kTokenEndpointKey];
+ [aCoder encodeObject:_issuer forKey:kIssuerKey];
+ [aCoder encodeObject:_registrationEndpoint forKey:kRegistrationEndpointKey];
+ [aCoder encodeObject:_discoveryDocument forKey:kDiscoveryDocumentKey];
+ [aCoder encodeObject:_endSessionEndpoint forKey:kEndSessionEndpointKey];
+}
+
+#pragma mark - description
+
+- (NSString *)description {
+ return [NSString stringWithFormat:
+ @"OIDServiceConfiguration authorizationEndpoint: %@, tokenEndpoint: %@, "
+ "registrationEndpoint: %@, endSessionEndpoint: %@, discoveryDocument: [%@]",
+ _authorizationEndpoint,
+ _tokenEndpoint,
+ _registrationEndpoint,
+ _endSessionEndpoint,
+ _discoveryDocument];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDServiceDiscovery.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDServiceDiscovery.h
new file mode 100644
index 0000000000..577700834f
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDServiceDiscovery.h
@@ -0,0 +1,358 @@
+/*! @file OIDServiceDiscovery.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Represents an OpenID Connect 1.0 Discovery Document
+ @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
+ */
+@interface OIDServiceDiscovery : NSObject
+
+/*! @brief The decoded OpenID Connect 1.0 Discovery Document as a dictionary.
+ */
+@property(nonatomic, readonly) NSDictionary *discoveryDictionary;
+
+/*! @brief REQUIRED. URL using the @c https scheme with no query or fragment component that the OP
+ asserts as its Issuer Identifier. If Issuer discovery is supported, this value MUST be
+ identical to the issuer value returned by WebFinger. This also MUST be identical to the
+ @c iss Claim value in ID Tokens issued from this Issuer.
+ @remarks issuer
+ @seealso https://openid.net/specs/openid-connect-discovery-1_0.html#IssuerDiscovery
+ */
+@property(nonatomic, readonly) NSURL *issuer;
+
+/*! @brief REQUIRED. URL of the OP's OAuth 2.0 Authorization Endpoint.
+ @remarks authorization_endpoint
+ @seealso http://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint
+ */
+@property(nonatomic, readonly) NSURL *authorizationEndpoint;
+
+/*! @brief URL of the OP's OAuth 2.0 Token Endpoint. This is REQUIRED unless only the Implicit Flow
+ is used.
+ @remarks token_endpoint
+ @seealso http://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
+ */
+@property(nonatomic, readonly) NSURL *tokenEndpoint;
+
+/*! @brief RECOMMENDED. URL of the OP's UserInfo Endpoint. This URL MUST use the https scheme and
+ MAY contain port, path, and query parameter components.
+ @remarks userinfo_endpoint
+ @seealso http://openid.net/specs/openid-connect-core-1_0.html#UserInfo
+ */
+@property(nonatomic, readonly, nullable) NSURL *userinfoEndpoint;
+
+/*! @brief REQUIRED. URL of the OP's JSON Web Key Set document. This contains the signing key(s) the
+ RP uses to validate signatures from the OP. The JWK Set MAY also contain the Server's
+ encryption key(s), which are used by RPs to encrypt requests to the Server. When both
+ signing and encryption keys are made available, a use (Key Use) parameter value is REQUIRED
+ for all keys in the referenced JWK Set to indicate each key's intended usage. Although some
+ algorithms allow the same key to be used for both signatures and encryption, doing so is NOT
+ RECOMMENDED, as it is less secure. The JWK x5c parameter MAY be used to provide X.509
+ representations of keys provided. When used, the bare key values MUST still be present and
+ MUST match those in the certificate.
+ @remarks jwks_uri
+ @seealso http://tools.ietf.org/html/rfc7517
+ */
+@property(nonatomic, readonly) NSURL *jwksURL;
+
+/*! @brief RECOMMENDED. URL of the OP's Dynamic Client Registration Endpoint.
+ @remarks registration_endpoint
+ @seealso http://openid.net/specs/openid-connect-registration-1_0.html
+ */
+@property(nonatomic, readonly, nullable) NSURL *registrationEndpoint;
+
+/* @brief OPTIONAL. URL of the OP's RP-Initiated Logout endpoint.
+ @remarks end_session_endpoint
+ @seealso http://openid.net/specs/openid-connect-session-1_0.html#OPMetadata
+ */
+@property(nonatomic, readonly, nullable) NSURL *endSessionEndpoint;
+
+/*! @brief RECOMMENDED. JSON array containing a list of the OAuth 2.0 [RFC6749] scope values that
+ this server supports. The server MUST support the openid scope value. Servers MAY choose not
+ to advertise some supported scope values even when this parameter is used, although those
+ defined in [OpenID.Core] SHOULD be listed, if supported.
+ @remarks scopes_supported
+ @seealso http://tools.ietf.org/html/rfc6749#section-3.3
+ */
+@property(nonatomic, readonly, nullable) NSArray *scopesSupported;
+
+/*! @brief REQUIRED. JSON array containing a list of the OAuth 2.0 @c response_type values that this
+ OP supports. Dynamic OpenID Providers MUST support the @c code, @c id_token, and the token
+ @c id_token Response Type values.
+ @remarks response_types_supported
+ */
+@property(nonatomic, readonly) NSArray *responseTypesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the OAuth 2.0 @c response_mode values that this
+ OP supports, as specified in OAuth 2.0 Multiple Response Type Encoding Practices. If
+ omitted, the default for Dynamic OpenID Providers is @c ["query", "fragment"].
+ @remarks response_modes_supported
+ @seealso http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html
+ */
+@property(nonatomic, readonly, nullable) NSArray *responseModesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the OAuth 2.0 Grant Type values that this OP
+ supports. Dynamic OpenID Providers MUST support the @c authorization_code and @c implicit
+ Grant Type values and MAY support other Grant Types. If omitted, the default value is
+ @c ["authorization_code", "implicit"].
+ @remarks grant_types_supported
+ */
+@property(nonatomic, readonly, nullable) NSArray *grantTypesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the Authentication Context Class References
+ that this OP supports.
+ @remarks acr_values_supported
+ */
+@property(nonatomic, readonly, nullable) NSArray *acrValuesSupported;
+
+/*! @brief REQUIRED. JSON array containing a list of the Subject Identifier types that this OP
+ supports. Valid types include @c pairwise and @c public.
+ @remarks subject_types_supported
+ */
+@property(nonatomic, readonly) NSArray *subjectTypesSupported;
+
+/*! @brief REQUIRED. JSON array containing a list of the JWS signing algorithms (@c alg values)
+ supported by the OP for the ID Token to encode the Claims in a JWT. The algorithm @c RS256
+ MUST be included. The value @c none MAY be supported, but MUST NOT be used unless the
+ Response Type used returns no ID Token from the Authorization Endpoint (such as when using
+ the Authorization Code Flow).
+ @remarks id_token_signing_alg_values_supported
+ @seealso https://tools.ietf.org/html/rfc7519
+ */
+@property(nonatomic, readonly) NSArray *IDTokenSigningAlgorithmValuesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the JWE encryption algorithms (@c alg values)
+ supported by the OP for the ID Token to encode the Claims in a JWT.
+ @remarks id_token_encryption_alg_values_supported
+ @seealso https://tools.ietf.org/html/rfc7519
+ */
+@property(nonatomic, readonly, nullable)
+ NSArray *IDTokenEncryptionAlgorithmValuesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the JWE encryption algorithms (@c enc values)
+ supported by the OP for the ID Token to encode the Claims in a JWT.
+ @remarks id_token_encryption_enc_values_supported
+ @seealso https://tools.ietf.org/html/rfc7519
+ */
+@property(nonatomic, readonly, nullable)
+ NSArray *IDTokenEncryptionEncodingValuesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the JWS signing algorithms (@c alg values)
+ supported by the UserInfo Endpoint to encode the Claims in a JWT. The value none MAY be
+ included.
+ @remarks userinfo_signing_alg_values_supported
+ @seealso https://tools.ietf.org/html/rfc7515
+ @seealso https://tools.ietf.org/html/rfc7518
+ @seealso https://tools.ietf.org/html/rfc7519
+ */
+@property(nonatomic, readonly, nullable)
+ NSArray *userinfoSigningAlgorithmValuesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the JWE encryption algorithms (alg values)
+ supported by the UserInfo Endpoint to encode the Claims in a JWT.
+ @remarks userinfo_encryption_alg_values_supported
+ @seealso https://tools.ietf.org/html/rfc7516
+ @seealso https://tools.ietf.org/html/rfc7518
+ @seealso https://tools.ietf.org/html/rfc7519
+ */
+@property(nonatomic, readonly, nullable)
+ NSArray *userinfoEncryptionAlgorithmValuesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the JWE encryption algorithms (@c enc values)
+ supported by the UserInfo Endpoint to encode the Claims in a JWT.
+ @remarks userinfo_encryption_enc_values_supported
+ @seealso https://tools.ietf.org/html/rfc7519
+ */
+@property(nonatomic, readonly, nullable)
+ NSArray *userinfoEncryptionEncodingValuesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the JWS signing algorithms (@c alg values)
+ supported by the OP for Request Objects, which are described in Section 6.1 of OpenID
+ Connect Core 1.0. These algorithms are used both when the Request Object is passed by value
+ (using the request parameter) and when it is passed by reference (using the @c request_uri
+ parameter). Servers SHOULD support @c none and @c RS256.
+ @remarks request_object_signing_alg_values_supported
+ @seealso http://openid.net/specs/openid-connect-core-1_0.html
+ */
+@property(nonatomic, readonly, nullable)
+ NSArray *requestObjectSigningAlgorithmValuesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the JWE encryption algorithms (@c alg values)
+ supported by the OP for Request Objects. These algorithms are used both when the Request
+ Object is passed by value and when it is passed by reference.
+ @remarks request_object_encryption_alg_values_supported
+ */
+@property(nonatomic, readonly, nullable)
+ NSArray *requestObjectEncryptionAlgorithmValuesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the JWE encryption algorithms (@c enc values)
+ supported by the OP for Request Objects. These algorithms are used both when the Request
+ Object is passed by value and when it is passed by reference.
+ @remarks request_object_encryption_enc_values_supported
+ */
+@property(nonatomic, readonly, nullable)
+ NSArray *requestObjectEncryptionEncodingValuesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of Client Authentication methods supported by this
+ Token Endpoint. The options are @c client_secret_post, @c client_secret_basic,
+ @c client_secret_jwt, and @c private_key_jwt, as described in Section 9 of OpenID Connect
+ Core 1.0. Other authentication methods MAY be defined by extensions. If omitted, the default
+ is @c client_secret_basic -- the HTTP Basic Authentication Scheme specified in Section 2.3.1
+ of OAuth 2.0.
+ @remarks token_endpoint_auth_methods_supported
+ @seealso http://openid.net/specs/openid-connect-core-1_0.html
+ @seealso http://tools.ietf.org/html/rfc6749#section-2.3.1
+ */
+@property(nonatomic, readonly, nullable) NSArray *tokenEndpointAuthMethodsSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the JWS signing algorithms (@c alg values)
+ supported by the Token Endpoint for the signature on the JWT used to authenticate the Client
+ at the Token Endpoint for the @c private_key_jwt and @c client_secret_jwt authentication
+ methods. Servers SHOULD support @c RS256. The value @c none MUST NOT be used.
+ @remarks token_endpoint_auth_signing_alg_values_supported
+ @seealso https://tools.ietf.org/html/rfc7519
+ */
+@property(nonatomic, readonly, nullable)
+ NSArray *tokenEndpointAuthSigningAlgorithmValuesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the @c display parameter values that the OpenID
+ Provider supports. These values are described in Section 3.1.2.1 of OpenID Connect Core 1.0.
+ @remarks display_values_supported
+ @seealso http://openid.net/specs/openid-connect-core-1_0.html
+ */
+@property(nonatomic, readonly, nullable) NSArray *displayValuesSupported;
+
+/*! @brief OPTIONAL. JSON array containing a list of the Claim Types that the OpenID Provider
+ supports. These Claim Types are described in Section 5.6 of OpenID Connect Core 1.0. Values
+ defined by this specification are @c normal, @c aggregated, and @c distributed. If omitted,
+ the implementation supports only @c normal Claims.
+ @remarks claim_types_supported
+ @seealso http://openid.net/specs/openid-connect-core-1_0.html
+ */
+@property(nonatomic, readonly, nullable) NSArray *claimTypesSupported;
+
+/*! @brief RECOMMENDED. JSON array containing a list of the Claim Names of the Claims that the
+ OpenID Provider MAY be able to supply values for. Note that for privacy or other reasons,
+ this might not be an exhaustive list.
+ @remarks claims_supported
+ */
+@property(nonatomic, readonly, nullable) NSArray *claimsSupported;
+
+/*! @brief OPTIONAL. URL of a page containing human-readable information that developers might want
+ or need to know when using the OpenID Provider. In particular, if the OpenID Provider does
+ not support Dynamic Client Registration, then information on how to register Clients needs
+ to be provided in this documentation.
+ @remarks service_documentation
+ */
+@property(nonatomic, readonly, nullable) NSURL *serviceDocumentation;
+
+/*! @brief OPTIONAL. Languages and scripts supported for values in Claims being returned,
+ represented as a JSON array of BCP47 language tag values. Not all languages and scripts are
+ necessarily supported for all Claim values.
+ @remarks claims_locales_supported
+ @seealso http://tools.ietf.org/html/rfc5646
+ */
+@property(nonatomic, readonly, nullable) NSArray *claimsLocalesSupported;
+
+/*! @brief OPTIONAL. Languages and scripts supported for the user interface, represented as a JSON
+ array of BCP47 language tag values.
+ @remarks ui_locales_supported
+ @seealso http://tools.ietf.org/html/rfc5646
+ */
+@property(nonatomic, readonly, nullable) NSArray *UILocalesSupported;
+
+/*! @brief OPTIONAL. Boolean value specifying whether the OP supports use of the claims parameter,
+ with @c true indicating support. If omitted, the default value is @c false.
+ @remarks claims_parameter_supported
+ */
+@property(nonatomic, readonly) BOOL claimsParameterSupported;
+
+/*! @brief OPTIONAL. Boolean value specifying whether the OP supports use of the request parameter,
+ with @c true indicating support. If omitted, the default value is @c false.
+ @remarks request_parameter_supported
+ */
+@property(nonatomic, readonly) BOOL requestParameterSupported;
+
+/*! @brief OPTIONAL. Boolean value specifying whether the OP supports use of the @c request_uri
+ parameter, with true indicating support. If omitted, the default value is @c true.
+ @remarks request_uri_parameter_supported
+ */
+@property(nonatomic, readonly) BOOL requestURIParameterSupported;
+
+/*! @brief OPTIONAL. Boolean value specifying whether the OP requires any @c request_uri values used
+ to be pre-registered using the @c request_uris registration parameter. Pre-registration is
+ REQUIRED when the value is @c true. If omitted, the default value is @c false.
+ @remarks require_request_uri_registration
+ */
+@property(nonatomic, readonly) BOOL requireRequestURIRegistration;
+
+/*! @brief OPTIONAL. URL that the OpenID Provider provides to the person registering the Client to
+ read about the OP's requirements on how the Relying Party can use the data provided by the
+ OP. The registration process SHOULD display this URL to the person registering the Client if
+ it is given.
+ @remarks op_policy_uri
+ */
+@property(nonatomic, readonly, nullable) NSURL *OPPolicyURI;
+
+/*! @brief OPTIONAL. URL that the OpenID Provider provides to the person registering the Client to
+ read about OpenID Provider's terms of service. The registration process SHOULD display this
+ URL to the person registering the Client if it is given.
+ @remarks op_tos_uri
+ */
+@property(nonatomic, readonly, nullable) NSURL *OPTosURI;
+
+/*! @internal
+ @brief Unavailable. Please use @c initWithDictionary:error:, @c initWithJSON:error, or the
+ @c serviceDiscoveryWithURL:callback: factory method.
+ */
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/*! @brief Decodes a OpenID Connect Discovery 1.0 JSON document.
+ @param serviceDiscoveryJSON An OpenID Connect Service Discovery document.
+ @param error If a required field is missing from the dictionary, an error with domain
+ @c ::OIDGeneralErrorDomain and code @c ::OIDErrorCodeInvalidDiscoveryDocument will be
+ returned.
+ */
+- (nullable instancetype)initWithJSON:(NSString *)serviceDiscoveryJSON
+ error:(NSError **_Nullable)error;
+
+/*! @brief Decodes a OpenID Connect Discovery 1.0 JSON document.
+ @param serviceDiscoveryJSONData An OpenID Connect Service Discovery document.
+ @param error If a required field is missing from the dictionary, an error with domain
+ @c ::OIDGeneralErrorDomain and code @c ::OIDErrorCodeInvalidDiscoveryDocument will be
+ returned.
+ */
+- (nullable instancetype)initWithJSONData:(NSData *)serviceDiscoveryJSONData
+ error:(NSError **_Nullable)error;
+
+/*! @brief Designated initializer. The dictionary keys should match the keys defined in the OpenID
+ Connect Discovery 1.0 standard for OpenID Provider Metadata.
+ @param serviceDiscoveryDictionary A dictionary representing an OpenID Connect Service Discovery
+ document.
+ @param error If a required field is missing from the dictionary, an error with domain
+ @c ::OIDGeneralErrorDomain and code @c ::OIDErrorCodeInvalidDiscoveryDocument will be
+ returned.
+ */
+- (nullable instancetype)initWithDictionary:(NSDictionary *)serviceDiscoveryDictionary
+ error:(NSError **_Nullable)error NS_DESIGNATED_INITIALIZER;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDServiceDiscovery.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDServiceDiscovery.m
new file mode 100644
index 0000000000..ca81108a82
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDServiceDiscovery.m
@@ -0,0 +1,362 @@
+/*! @file OIDServiceDiscovery.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDServiceDiscovery.h"
+
+#import "OIDDefines.h"
+#import "OIDErrorUtilities.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! Field keys associated with an OpenID Connect Discovery Document. */
+static NSString *const kIssuerKey = @"issuer";
+static NSString *const kAuthorizationEndpointKey = @"authorization_endpoint";
+static NSString *const kTokenEndpointKey = @"token_endpoint";
+static NSString *const kUserinfoEndpointKey = @"userinfo_endpoint";
+static NSString *const kJWKSURLKey = @"jwks_uri";
+static NSString *const kRegistrationEndpointKey = @"registration_endpoint";
+static NSString *const kEndSessionEndpointKey = @"end_session_endpoint";
+static NSString *const kScopesSupportedKey = @"scopes_supported";
+static NSString *const kResponseTypesSupportedKey = @"response_types_supported";
+static NSString *const kResponseModesSupportedKey = @"response_modes_supported";
+static NSString *const kGrantTypesSupportedKey = @"grant_types_supported";
+static NSString *const kACRValuesSupportedKey = @"acr_values_supported";
+static NSString *const kSubjectTypesSupportedKey = @"subject_types_supported";
+static NSString *const kIDTokenSigningAlgorithmValuesSupportedKey =
+ @"id_token_signing_alg_values_supported";
+static NSString *const kIDTokenEncryptionAlgorithmValuesSupportedKey =
+ @"id_token_encryption_alg_values_supported";
+static NSString *const kIDTokenEncryptionEncodingValuesSupportedKey =
+ @"id_token_encryption_enc_values_supported";
+static NSString *const kUserinfoSigningAlgorithmValuesSupportedKey =
+ @"userinfo_signing_alg_values_supported";
+static NSString *const kUserinfoEncryptionAlgorithmValuesSupportedKey =
+ @"userinfo_encryption_alg_values_supported";
+static NSString *const kUserinfoEncryptionEncodingValuesSupportedKey =
+ @"userinfo_encryption_enc_values_supported";
+static NSString *const kRequestObjectSigningAlgorithmValuesSupportedKey =
+ @"request_object_signing_alg_values_supported";
+static NSString *const kRequestObjectEncryptionAlgorithmValuesSupportedKey =
+ @"request_object_encryption_alg_values_supported";
+static NSString *const kRequestObjectEncryptionEncodingValuesSupported =
+ @"request_object_encryption_enc_values_supported";
+static NSString *const kTokenEndpointAuthMethodsSupportedKey =
+ @"token_endpoint_auth_methods_supported";
+static NSString *const kTokenEndpointAuthSigningAlgorithmValuesSupportedKey =
+ @"token_endpoint_auth_signing_alg_values_supported";
+static NSString *const kDisplayValuesSupportedKey = @"display_values_supported";
+static NSString *const kClaimTypesSupportedKey = @"claim_types_supported";
+static NSString *const kClaimsSupportedKey = @"claims_supported";
+static NSString *const kServiceDocumentationKey = @"service_documentation";
+static NSString *const kClaimsLocalesSupportedKey = @"claims_locales_supported";
+static NSString *const kUILocalesSupportedKey = @"ui_locales_supported";
+static NSString *const kClaimsParameterSupportedKey = @"claims_parameter_supported";
+static NSString *const kRequestParameterSupportedKey = @"request_parameter_supported";
+static NSString *const kRequestURIParameterSupportedKey = @"request_uri_parameter_supported";
+static NSString *const kRequireRequestURIRegistrationKey = @"require_request_uri_registration";
+static NSString *const kOPPolicyURIKey = @"op_policy_uri";
+static NSString *const kOPTosURIKey = @"op_tos_uri";
+
+@implementation OIDServiceDiscovery {
+ NSDictionary *_discoveryDictionary;
+}
+
+- (nonnull instancetype)init OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithDictionary:error:))
+
+- (nullable instancetype)initWithJSON:(NSString *)serviceDiscoveryJSON error:(NSError **)error {
+ NSData *jsonData = [serviceDiscoveryJSON dataUsingEncoding:NSUTF8StringEncoding];
+ return [self initWithJSONData:jsonData error:error];
+}
+
+- (nullable instancetype)initWithJSONData:(NSData *)serviceDiscoveryJSONData
+ error:(NSError **_Nullable)error {
+ NSError *jsonError;
+ NSDictionary *json =
+ [NSJSONSerialization JSONObjectWithData:serviceDiscoveryJSONData options:0 error:&jsonError];
+ if (!json || jsonError) {
+ *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeJSONDeserializationError
+ underlyingError:jsonError
+ description:jsonError.localizedDescription];
+ return nil;
+ }
+ if (![json isKindOfClass:[NSDictionary class]]) {
+ *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeInvalidDiscoveryDocument
+ underlyingError:nil
+ description:@"Discovery document isn't a dictionary"];
+ return nil;
+ }
+
+ return [self initWithDictionary:json error:error];
+}
+
+- (nullable instancetype)initWithDictionary:(NSDictionary *)serviceDiscoveryDictionary
+ error:(NSError **_Nullable)error {
+ if (![[self class] dictionaryHasRequiredFields:serviceDiscoveryDictionary error:error]) {
+ return nil;
+ }
+ self = [super init];
+ if (self) {
+ _discoveryDictionary = [serviceDiscoveryDictionary copy];
+ }
+ return self;
+}
+
+#pragma mark -
+
+/*! @brief Checks to see if the specified dictionary contains the required fields.
+ @discussion This test is not meant to provide semantic analysis of the document (eg. fields
+ where the value @c none is not an allowed option would not cause this method to fail if
+ their value was @c none.) We are just testing to make sure we can meet the nullability
+ contract we promised in the header.
+ */
++ (BOOL)dictionaryHasRequiredFields:(NSDictionary *)dictionary
+ error:(NSError **_Nullable)error {
+ static NSString *const kMissingFieldErrorText = @"Missing field: %@";
+ static NSString *const kInvalidURLFieldErrorText = @"Invalid URL: %@";
+
+ NSArray *requiredFields = @[
+ kIssuerKey,
+ kAuthorizationEndpointKey,
+ kTokenEndpointKey,
+ kJWKSURLKey,
+ kResponseTypesSupportedKey,
+ kSubjectTypesSupportedKey,
+ kIDTokenSigningAlgorithmValuesSupportedKey
+ ];
+
+ for (NSString *field in requiredFields) {
+ if (!dictionary[field]) {
+ if (error) {
+ NSString *errorText = [NSString stringWithFormat:kMissingFieldErrorText, field];
+ *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeInvalidDiscoveryDocument
+ underlyingError:nil
+ description:errorText];
+ }
+ return NO;
+ }
+ }
+
+ // Check required URL fields are valid URLs.
+ NSArray *requiredURLFields = @[
+ kIssuerKey,
+ kTokenEndpointKey,
+ kJWKSURLKey
+ ];
+
+ for (NSString *field in requiredURLFields) {
+ if (![NSURL URLWithString:dictionary[field]]) {
+ if (error) {
+ NSString *errorText = [NSString stringWithFormat:kInvalidURLFieldErrorText, field];
+ *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeInvalidDiscoveryDocument
+ underlyingError:nil
+ description:errorText];
+ }
+ return NO;
+ }
+ }
+
+ return YES;
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(nullable NSZone *)zone {
+ // The documentation for NSCopying specifically advises us to return a reference to the original
+ // instance in the case where instances are immutable (as ours is):
+ // "Implement NSCopying by retaining the original instead of creating a new copy when the class
+ // and its contents are immutable."
+ return self;
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+ return YES;
+}
+
+- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
+ NSError *error;
+ NSDictionary *dictionary = [[NSDictionary alloc] initWithCoder:aDecoder];
+ self = [self initWithDictionary:dictionary error:&error];
+ if (error) {
+ return nil;
+ }
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+ [_discoveryDictionary encodeWithCoder:aCoder];
+}
+
+#pragma mark - Properties
+
+- (NSDictionary *)discoveryDictionary {
+ return _discoveryDictionary;
+}
+
+- (NSURL *)issuer {
+ return [NSURL URLWithString:_discoveryDictionary[kIssuerKey]];
+}
+
+- (NSURL *)authorizationEndpoint {
+ return [NSURL URLWithString:_discoveryDictionary[kAuthorizationEndpointKey]];
+}
+
+- (NSURL *)tokenEndpoint {
+ return [NSURL URLWithString:_discoveryDictionary[kTokenEndpointKey]];
+}
+
+- (nullable NSURL *)userinfoEndpoint {
+ return [NSURL URLWithString:_discoveryDictionary[kUserinfoEndpointKey]];
+}
+
+- (NSURL *)jwksURL {
+ return [NSURL URLWithString:_discoveryDictionary[kJWKSURLKey]];
+}
+
+- (nullable NSURL *)registrationEndpoint {
+ return [NSURL URLWithString:_discoveryDictionary[kRegistrationEndpointKey]];
+}
+
+- (nullable NSURL *)endSessionEndpoint {
+ return [NSURL URLWithString:_discoveryDictionary[kEndSessionEndpointKey]];
+}
+
+- (nullable NSArray *)scopesSupported {
+ return _discoveryDictionary[kScopesSupportedKey];
+}
+
+- (NSArray *)responseTypesSupported {
+ return _discoveryDictionary[kResponseTypesSupportedKey];
+}
+
+- (nullable NSArray *)responseModesSupported {
+ return _discoveryDictionary[kResponseModesSupportedKey];
+}
+
+- (nullable NSArray *)grantTypesSupported {
+ return _discoveryDictionary[kGrantTypesSupportedKey];
+}
+
+- (nullable NSArray *)acrValuesSupported {
+ return _discoveryDictionary[kACRValuesSupportedKey];
+}
+
+- (NSArray *)subjectTypesSupported {
+ return _discoveryDictionary[kSubjectTypesSupportedKey];
+}
+
+- (NSArray *) IDTokenSigningAlgorithmValuesSupported {
+ return _discoveryDictionary[kIDTokenSigningAlgorithmValuesSupportedKey];
+}
+
+- (nullable NSArray *)IDTokenEncryptionAlgorithmValuesSupported {
+ return _discoveryDictionary[kIDTokenEncryptionAlgorithmValuesSupportedKey];
+}
+
+- (nullable NSArray *)IDTokenEncryptionEncodingValuesSupported {
+ return _discoveryDictionary[kIDTokenEncryptionEncodingValuesSupportedKey];
+}
+
+- (nullable NSArray *)userinfoSigningAlgorithmValuesSupported {
+ return _discoveryDictionary[kUserinfoSigningAlgorithmValuesSupportedKey];
+}
+
+- (nullable NSArray *)userinfoEncryptionAlgorithmValuesSupported {
+ return _discoveryDictionary[kUserinfoEncryptionAlgorithmValuesSupportedKey];
+}
+
+- (nullable NSArray *)userinfoEncryptionEncodingValuesSupported {
+ return _discoveryDictionary[kUserinfoEncryptionEncodingValuesSupportedKey];
+}
+
+- (nullable NSArray *)requestObjectSigningAlgorithmValuesSupported {
+ return _discoveryDictionary[kRequestObjectSigningAlgorithmValuesSupportedKey];
+}
+
+- (nullable NSArray *) requestObjectEncryptionAlgorithmValuesSupported {
+ return _discoveryDictionary[kRequestObjectEncryptionAlgorithmValuesSupportedKey];
+}
+
+- (nullable NSArray *) requestObjectEncryptionEncodingValuesSupported {
+ return _discoveryDictionary[kRequestObjectEncryptionEncodingValuesSupported];
+}
+
+- (nullable NSArray *)tokenEndpointAuthMethodsSupported {
+ return _discoveryDictionary[kTokenEndpointAuthMethodsSupportedKey];
+}
+
+- (nullable NSArray *)tokenEndpointAuthSigningAlgorithmValuesSupported {
+ return _discoveryDictionary[kTokenEndpointAuthSigningAlgorithmValuesSupportedKey];
+}
+
+- (nullable NSArray *)displayValuesSupported {
+ return _discoveryDictionary[kDisplayValuesSupportedKey];
+}
+
+- (nullable NSArray *)claimTypesSupported {
+ return _discoveryDictionary[kClaimTypesSupportedKey];
+}
+
+- (nullable NSArray *)claimsSupported {
+ return _discoveryDictionary[kClaimsSupportedKey];
+}
+
+- (nullable NSURL *)serviceDocumentation {
+ return [NSURL URLWithString:_discoveryDictionary[kServiceDocumentationKey]];
+}
+
+- (nullable NSArray *)claimsLocalesSupported {
+ return _discoveryDictionary[kClaimsLocalesSupportedKey];
+}
+
+- (nullable NSArray *)UILocalesSupported {
+ return _discoveryDictionary[kUILocalesSupportedKey];
+}
+
+- (BOOL)claimsParameterSupported {
+ return [_discoveryDictionary[kClaimsParameterSupportedKey] boolValue];
+}
+
+- (BOOL)requestParameterSupported {
+ return [_discoveryDictionary[kRequestParameterSupportedKey] boolValue];
+}
+
+- (BOOL)requestURIParameterSupported {
+ // Default is true/YES.
+ if (!_discoveryDictionary[kRequestURIParameterSupportedKey]) {
+ return YES;
+ }
+ return [_discoveryDictionary[kRequestURIParameterSupportedKey] boolValue];
+}
+
+- (BOOL)requireRequestURIRegistration {
+ return [_discoveryDictionary[kRequireRequestURIRegistrationKey] boolValue];
+}
+
+- (nullable NSURL *)OPPolicyURI {
+ return [NSURL URLWithString:_discoveryDictionary[kOPPolicyURIKey]];
+}
+
+- (nullable NSURL *)OPTosURI {
+ return [NSURL URLWithString:_discoveryDictionary[kOPTosURIKey]];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenRequest.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenRequest.h
new file mode 100644
index 0000000000..00e0c6e204
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenRequest.h
@@ -0,0 +1,162 @@
+/*! @file OIDTokenRequest.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+// This file only declares string constants useful for constructing a @c OIDTokenRequest, so it is
+// imported here for convenience.
+#import "OIDGrantTypes.h"
+
+@class OIDAuthorizationResponse;
+@class OIDServiceConfiguration;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Represents a token request.
+ @see https://tools.ietf.org/html/rfc6749#section-3.2
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.3
+ */
+@interface OIDTokenRequest : NSObject
+
+/*! @brief The service's configuration.
+ @remarks This configuration specifies how to connect to a particular OAuth provider.
+ Configurations may be created manually, or via an OpenID Connect Discovery Document.
+ */
+@property(nonatomic, readonly) OIDServiceConfiguration *configuration;
+
+/*! @brief The type of token being sent to the token endpoint, i.e. "authorization_code" for the
+ authorization code exchange, or "refresh_token" for an access token refresh request.
+ @remarks grant_type
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.3
+ @see https://www.google.com/url?sa=D&q=https%3A%2F%2Ftools.ietf.org%2Fhtml%2Frfc6749%23section-6
+ */
+@property(nonatomic, readonly) NSString *grantType;
+
+/*! @brief The authorization code received from the authorization server.
+ @remarks code
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.3
+ */
+@property(nonatomic, readonly, nullable) NSString *authorizationCode;
+
+/*! @brief The client's redirect URI.
+ @remarks redirect_uri
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.3
+ */
+@property(nonatomic, readonly, nullable) NSURL *redirectURL;
+
+/*! @brief The client identifier.
+ @remarks client_id
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.3
+ */
+@property(nonatomic, readonly) NSString *clientID;
+
+/*! @brief The client secret.
+ @remarks client_secret
+ @see https://tools.ietf.org/html/rfc6749#section-2.3.1
+ */
+@property(nonatomic, readonly, nullable) NSString *clientSecret;
+
+/*! @brief The value of the scope parameter is expressed as a list of space-delimited,
+ case-sensitive strings.
+ @remarks scope
+ @see https://tools.ietf.org/html/rfc6749#section-3.3
+ */
+@property(nonatomic, readonly, nullable) NSString *scope;
+
+/*! @brief The refresh token, which can be used to obtain new access tokens using the same
+ authorization grant.
+ @remarks refresh_token
+ @see https://tools.ietf.org/html/rfc6749#section-5.1
+ */
+@property(nonatomic, readonly, nullable) NSString *refreshToken;
+
+/*! @brief The PKCE code verifier used to redeem the authorization code.
+ @remarks code_verifier
+ @see https://tools.ietf.org/html/rfc7636#section-4.3
+ */
+@property(nonatomic, readonly, nullable) NSString *codeVerifier;
+
+/*! @brief The client's additional token request parameters.
+ */
+@property(nonatomic, readonly, nullable) NSDictionary *additionalParameters;
+
+/*! @internal
+ @brief Unavailable. Please use
+ initWithConfiguration:grantType:code:redirectURL:clientID:additionalParameters:.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @param configuration The service's configuration.
+ @param grantType the type of token being sent to the token endpoint, i.e. "authorization_code"
+ for the authorization code exchange, or "refresh_token" for an access token refresh request.
+ @see OIDGrantTypes.h
+ @param code The authorization code received from the authorization server.
+ @param redirectURL The client's redirect URI.
+ @param clientID The client identifier.
+ @param clientSecret The client secret.
+ @param scopes An array of scopes to combine into a single scope string per the OAuth2 spec.
+ @param refreshToken The refresh token.
+ @param codeVerifier The PKCE code verifier.
+ @param additionalParameters The client's additional token request parameters.
+ */
+- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
+ grantType:(NSString *)grantType
+ authorizationCode:(nullable NSString *)code
+ redirectURL:(nullable NSURL *)redirectURL
+ clientID:(NSString *)clientID
+ clientSecret:(nullable NSString *)clientSecret
+ scopes:(nullable NSArray *)scopes
+ refreshToken:(nullable NSString *)refreshToken
+ codeVerifier:(nullable NSString *)codeVerifier
+ additionalParameters:(nullable NSDictionary *)additionalParameters;
+
+/*! @brief Designated initializer.
+ @param configuration The service's configuration.
+ @param grantType the type of token being sent to the token endpoint, i.e. "authorization_code"
+ for the authorization code exchange, or "refresh_token" for an access token refresh request.
+ @see OIDGrantTypes.h
+ @param code The authorization code received from the authorization server.
+ @param redirectURL The client's redirect URI.
+ @param clientID The client identifier.
+ @param clientSecret The client secret.
+ @param scope The value of the scope parameter is expressed as a list of space-delimited,
+ case-sensitive strings.
+ @param refreshToken The refresh token.
+ @param codeVerifier The PKCE code verifier.
+ @param additionalParameters The client's additional token request parameters.
+ */
+- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
+ grantType:(NSString *)grantType
+ authorizationCode:(nullable NSString *)code
+ redirectURL:(nullable NSURL *)redirectURL
+ clientID:(NSString *)clientID
+ clientSecret:(nullable NSString *)clientSecret
+ scope:(nullable NSString *)scope
+ refreshToken:(nullable NSString *)refreshToken
+ codeVerifier:(nullable NSString *)codeVerifier
+ additionalParameters:(nullable NSDictionary *)additionalParameters
+ NS_DESIGNATED_INITIALIZER;
+
+/*! @brief Constructs an @c NSURLRequest representing the token request.
+ @return An @c NSURLRequest representing the token request.
+ */
+- (NSURLRequest *)URLRequest;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenRequest.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenRequest.m
new file mode 100644
index 0000000000..bd27dd4806
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenRequest.m
@@ -0,0 +1,307 @@
+/*! @file OIDTokenRequest.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDTokenRequest.h"
+
+#import "OIDDefines.h"
+#import "OIDError.h"
+#import "OIDScopeUtilities.h"
+#import "OIDServiceConfiguration.h"
+#import "OIDURLQueryComponent.h"
+#import "OIDTokenUtilities.h"
+
+/*! @brief The key for the @c configuration property for @c NSSecureCoding
+ */
+static NSString *const kConfigurationKey = @"configuration";
+
+/*! @brief Key used to encode the @c grantType property for @c NSSecureCoding
+ */
+static NSString *const kGrantTypeKey = @"grant_type";
+
+/*! @brief The key for the @c authorizationCode property for @c NSSecureCoding.
+ */
+static NSString *const kAuthorizationCodeKey = @"code";
+
+/*! @brief Key used to encode the @c clientID property for @c NSSecureCoding
+ */
+static NSString *const kClientIDKey = @"client_id";
+
+/*! @brief Key used to encode the @c clientSecret property for @c NSSecureCoding
+ */
+static NSString *const kClientSecretKey = @"client_secret";
+
+/*! @brief Key used to encode the @c redirectURL property for @c NSSecureCoding
+ */
+static NSString *const kRedirectURLKey = @"redirect_uri";
+
+/*! @brief Key used to encode the @c scopes property for @c NSSecureCoding
+ */
+static NSString *const kScopeKey = @"scope";
+
+/*! @brief Key used to encode the @c refreshToken property for @c NSSecureCoding
+ */
+static NSString *const kRefreshTokenKey = @"refresh_token";
+
+/*! @brief Key used to encode the @c codeVerifier property for @c NSSecureCoding and to build the
+ request URL.
+ */
+static NSString *const kCodeVerifierKey = @"code_verifier";
+
+/*! @brief Key used to encode the @c additionalParameters property for
+ @c NSSecureCoding
+ */
+static NSString *const kAdditionalParametersKey = @"additionalParameters";
+
+@implementation OIDTokenRequest
+
+- (instancetype)init
+ OID_UNAVAILABLE_USE_INITIALIZER(
+ @selector(initWithConfiguration:
+ grantType:
+ authorizationCode:
+ redirectURL:
+ clientID:
+ clientSecret:
+ scope:
+ refreshToken:
+ codeVerifier:
+ additionalParameters:)
+ )
+
+- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
+ grantType:(NSString *)grantType
+ authorizationCode:(nullable NSString *)code
+ redirectURL:(nullable NSURL *)redirectURL
+ clientID:(NSString *)clientID
+ clientSecret:(nullable NSString *)clientSecret
+ scopes:(nullable NSArray *)scopes
+ refreshToken:(nullable NSString *)refreshToken
+ codeVerifier:(nullable NSString *)codeVerifier
+ additionalParameters:(nullable NSDictionary *)additionalParameters {
+ return [self initWithConfiguration:configuration
+ grantType:grantType
+ authorizationCode:code
+ redirectURL:redirectURL
+ clientID:clientID
+ clientSecret:clientSecret
+ scope:[OIDScopeUtilities scopesWithArray:scopes]
+ refreshToken:refreshToken
+ codeVerifier:(NSString *)codeVerifier
+ additionalParameters:additionalParameters];
+}
+
+- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
+ grantType:(NSString *)grantType
+ authorizationCode:(nullable NSString *)code
+ redirectURL:(nullable NSURL *)redirectURL
+ clientID:(NSString *)clientID
+ clientSecret:(nullable NSString *)clientSecret
+ scope:(nullable NSString *)scope
+ refreshToken:(nullable NSString *)refreshToken
+ codeVerifier:(nullable NSString *)codeVerifier
+ additionalParameters:(nullable NSDictionary *)additionalParameters {
+ self = [super init];
+ if (self) {
+ _configuration = [configuration copy];
+ _grantType = [grantType copy];
+ _authorizationCode = [code copy];
+ _redirectURL = [redirectURL copy];
+ _clientID = [clientID copy];
+ _clientSecret = [clientSecret copy];
+ _scope = [scope copy];
+ _refreshToken = [refreshToken copy];
+ _codeVerifier = [codeVerifier copy];
+ _additionalParameters =
+ [[NSDictionary alloc] initWithDictionary:additionalParameters copyItems:YES];
+
+ // Additional validation for the authorization_code grant type
+ if ([_grantType isEqual:OIDGrantTypeAuthorizationCode]) {
+ // redirect URI must not be nil
+ if (!_redirectURL) {
+ [NSException raise:OIDOAuthExceptionInvalidTokenRequestNullRedirectURL
+ format:@"%@", OIDOAuthExceptionInvalidTokenRequestNullRedirectURL, nil];
+
+ }
+ }
+ }
+ return self;
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(nullable NSZone *)zone {
+ // The documentation for NSCopying specifically advises us to return a reference to the original
+ // instance in the case where instances are immutable (as ours is):
+ // "Implement NSCopying by retaining the original instead of creating a new copy when the class
+ // and its contents are immutable."
+ return self;
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+ return YES;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+ OIDServiceConfiguration *configuration =
+ [aDecoder decodeObjectOfClass:[OIDServiceConfiguration class]
+ forKey:kConfigurationKey];
+ NSString *grantType = [aDecoder decodeObjectOfClass:[NSString class] forKey:kGrantTypeKey];
+ NSString *code = [aDecoder decodeObjectOfClass:[NSString class] forKey:kAuthorizationCodeKey];
+ NSString *clientID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kClientIDKey];
+ NSString *clientSecret = [aDecoder decodeObjectOfClass:[NSString class] forKey:kClientSecretKey];
+ NSString *scope = [aDecoder decodeObjectOfClass:[NSString class] forKey:kScopeKey];
+ NSString *refreshToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:kRefreshTokenKey];
+ NSString *codeVerifier = [aDecoder decodeObjectOfClass:[NSString class] forKey:kCodeVerifierKey];
+ NSURL *redirectURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kRedirectURLKey];
+ NSSet *additionalParameterCodingClasses = [NSSet setWithArray:@[
+ [NSDictionary class],
+ [NSString class]
+ ]];
+ NSDictionary *additionalParameters =
+ [aDecoder decodeObjectOfClasses:additionalParameterCodingClasses
+ forKey:kAdditionalParametersKey];
+ self = [self initWithConfiguration:configuration
+ grantType:grantType
+ authorizationCode:code
+ redirectURL:redirectURL
+ clientID:clientID
+ clientSecret:clientSecret
+ scope:scope
+ refreshToken:refreshToken
+ codeVerifier:codeVerifier
+ additionalParameters:additionalParameters];
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+ [aCoder encodeObject:_configuration forKey:kConfigurationKey];
+ [aCoder encodeObject:_grantType forKey:kGrantTypeKey];
+ [aCoder encodeObject:_authorizationCode forKey:kAuthorizationCodeKey];
+ [aCoder encodeObject:_clientID forKey:kClientIDKey];
+ [aCoder encodeObject:_clientSecret forKey:kClientSecretKey];
+ [aCoder encodeObject:_redirectURL forKey:kRedirectURLKey];
+ [aCoder encodeObject:_scope forKey:kScopeKey];
+ [aCoder encodeObject:_refreshToken forKey:kRefreshTokenKey];
+ [aCoder encodeObject:_codeVerifier forKey:kCodeVerifierKey];
+ [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey];
+}
+
+#pragma mark - NSObject overrides
+
+- (NSString *)description {
+ NSURLRequest *request = self.URLRequest;
+ NSString *requestBody =
+ [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding];
+ return [NSString stringWithFormat:@"<%@: %p, request: >",
+ NSStringFromClass([self class]),
+ (void *)self,
+ request.URL,
+ requestBody];
+}
+
+#pragma mark -
+
+/*! @brief Constructs the request URI.
+ @return A URL representing the token request.
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.3
+ */
+- (NSURL *)tokenRequestURL {
+ return _configuration.tokenEndpoint;
+}
+
+/*! @brief Constructs the request body data by combining the request parameters using the
+ "application/x-www-form-urlencoded" format.
+ @return The data to pass to the token request URL.
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.3
+ */
+- (OIDURLQueryComponent *)tokenRequestBody {
+ OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] init];
+
+ // Add parameters, as applicable.
+ if (_grantType) {
+ [query addParameter:kGrantTypeKey value:_grantType];
+ }
+ if (_scope) {
+ [query addParameter:kScopeKey value:_scope];
+ }
+ if (_redirectURL) {
+ [query addParameter:kRedirectURLKey value:_redirectURL.absoluteString];
+ }
+ if (_refreshToken) {
+ [query addParameter:kRefreshTokenKey value:_refreshToken];
+ }
+ if (_authorizationCode) {
+ [query addParameter:kAuthorizationCodeKey value:_authorizationCode];
+ }
+ if (_codeVerifier) {
+ [query addParameter:kCodeVerifierKey value:_codeVerifier];
+ }
+
+ // Add any additional parameters the client has specified.
+ [query addParameters:_additionalParameters];
+
+ return query;
+}
+
+- (NSURLRequest *)URLRequest {
+ static NSString *const kHTTPPost = @"POST";
+ static NSString *const kHTTPContentTypeHeaderKey = @"Content-Type";
+ static NSString *const kHTTPContentTypeHeaderValue =
+ @"application/x-www-form-urlencoded; charset=UTF-8";
+
+ NSURL *tokenRequestURL = [self tokenRequestURL];
+ NSMutableURLRequest *URLRequest = [[NSURLRequest requestWithURL:tokenRequestURL] mutableCopy];
+ URLRequest.HTTPMethod = kHTTPPost;
+ [URLRequest setValue:kHTTPContentTypeHeaderValue forHTTPHeaderField:kHTTPContentTypeHeaderKey];
+
+ OIDURLQueryComponent *bodyParameters = [self tokenRequestBody];
+ NSMutableDictionary *httpHeaders = [[NSMutableDictionary alloc] init];
+
+ if (_clientSecret) {
+ // The client id and secret are encoded using the "application/x-www-form-urlencoded"
+ // encoding algorithm per RFC 6749 Section 2.3.1.
+ // https://tools.ietf.org/html/rfc6749#section-2.3.1
+ NSString *encodedClientID = [OIDTokenUtilities formUrlEncode:_clientID];
+ NSString *encodedClientSecret = [OIDTokenUtilities formUrlEncode:_clientSecret];
+
+ NSString *credentials =
+ [NSString stringWithFormat:@"%@:%@", encodedClientID, encodedClientSecret];
+ NSData *plainData = [credentials dataUsingEncoding:NSUTF8StringEncoding];
+ NSString *basicAuth = [plainData base64EncodedStringWithOptions:kNilOptions];
+
+ NSString *authValue = [NSString stringWithFormat:@"Basic %@", basicAuth];
+ [httpHeaders setObject:authValue forKey:@"Authorization"];
+ } else {
+ [bodyParameters addParameter:kClientIDKey value:_clientID];
+ }
+
+ // Constructs request with the body string and headers.
+ NSString *bodyString = [bodyParameters URLEncodedParameters];
+ NSData *body = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
+ URLRequest.HTTPBody = body;
+
+ for (id header in httpHeaders) {
+ [URLRequest setValue:httpHeaders[header] forHTTPHeaderField:header];
+ }
+
+ return URLRequest;
+}
+
+@end
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenResponse.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenResponse.h
new file mode 100644
index 0000000000..b446e944ad
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenResponse.h
@@ -0,0 +1,110 @@
+/*! @file OIDTokenResponse.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+@class OIDTokenRequest;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Represents the response to an token request.
+ @see https://tools.ietf.org/html/rfc6749#section-3.2
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.3
+ */
+@interface OIDTokenResponse : NSObject
+
+/*! @brief The request which was serviced.
+ */
+@property(nonatomic, readonly) OIDTokenRequest *request;
+
+/*! @brief The access token generated by the authorization server.
+ @remarks access_token
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.4
+ @see https://tools.ietf.org/html/rfc6749#section-5.1
+ */
+@property(nonatomic, readonly, nullable) NSString *accessToken;
+
+/*! @brief The approximate expiration date & time of the access token.
+ @remarks expires_in
+ @seealso OIDTokenResponse.accessToken
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.4
+ @see https://tools.ietf.org/html/rfc6749#section-5.1
+ */
+@property(nonatomic, readonly, nullable) NSDate *accessTokenExpirationDate;
+
+/*! @brief Typically "Bearer" when present. Otherwise, another token_type value that the Client has
+ negotiated with the Authorization Server.
+ @remarks token_type
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.4
+ @see https://tools.ietf.org/html/rfc6749#section-5.1
+ */
+@property(nonatomic, readonly, nullable) NSString *tokenType;
+
+/*! @brief ID Token value associated with the authenticated session. Always present for the
+ authorization code grant exchange when OpenID Connect is used, optional for responses to
+ access token refresh requests. Note that AppAuth does NOT verify the JWT signature. Users
+ of AppAuth are encouraged to verifying the JWT signature using the validation library of
+ their choosing.
+ @remarks id_token
+ @see http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse
+ @see http://openid.net/specs/openid-connect-core-1_0.html#RefreshTokenResponse
+ @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken
+ @see https://jwt.io
+ @discussion @c OIDIDToken can be used to parse the ID Token and extract the claims. As noted,
+ this class does not verify the JWT signature.
+*/
+@property(nonatomic, readonly, nullable) NSString *idToken;
+
+/*! @brief The refresh token, which can be used to obtain new access tokens using the same
+ authorization grant
+ @remarks refresh_token
+ @see https://tools.ietf.org/html/rfc6749#section-5.1
+ */
+@property(nonatomic, readonly, nullable) NSString *refreshToken;
+
+/*! @brief The scope of the access token. OPTIONAL, if identical to the scopes requested, otherwise,
+ REQUIRED.
+ @remarks scope
+ @see https://tools.ietf.org/html/rfc6749#section-5.1
+ */
+@property(nonatomic, readonly, nullable) NSString *scope;
+
+/*! @brief Additional parameters returned from the token server.
+ */
+@property(nonatomic, readonly, nullable)
+ NSDictionary *> *additionalParameters;
+
+/*! @internal
+ @brief Unavailable. Please use initWithParameters:.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @brief Designated initializer.
+ @param request The serviced request.
+ @param parameters The decoded parameters returned from the Authorization Server.
+ @remarks Known parameters are extracted from the @c parameters parameter and the normative
+ properties are populated. Non-normative parameters are placed in the
+ @c #additionalParameters dictionary.
+ */
+- (instancetype)initWithRequest:(OIDTokenRequest *)request
+ parameters:(NSDictionary *> *)parameters
+ NS_DESIGNATED_INITIALIZER;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenResponse.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenResponse.m
new file mode 100644
index 0000000000..6995fb9146
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenResponse.m
@@ -0,0 +1,163 @@
+/*! @file OIDTokenResponse.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDTokenResponse.h"
+
+#import "OIDDefines.h"
+#import "OIDFieldMapping.h"
+#import "OIDTokenRequest.h"
+#import "OIDTokenUtilities.h"
+
+/*! @brief Key used to encode the @c request property for @c NSSecureCoding
+ */
+static NSString *const kRequestKey = @"request";
+
+/*! @brief The key for the @c accessToken property in the incoming parameters and for
+ @c NSSecureCoding.
+ */
+static NSString *const kAccessTokenKey = @"access_token";
+
+/*! @brief The key for the @c accessTokenExpirationDate property in the incoming parameters and for
+ @c NSSecureCoding.
+ */
+static NSString *const kExpiresInKey = @"expires_in";
+
+/*! @brief The key for the @c tokenType property in the incoming parameters and for
+ @c NSSecureCoding.
+ */
+static NSString *const kTokenTypeKey = @"token_type";
+
+/*! @brief The key for the @c idToken property in the incoming parameters and for @c NSSecureCoding.
+ */
+static NSString *const kIDTokenKey = @"id_token";
+
+/*! @brief The key for the @c refreshToken property in the incoming parameters and for
+ @c NSSecureCoding.
+ */
+static NSString *const kRefreshTokenKey = @"refresh_token";
+
+/*! @brief The key for the @c scope property in the incoming parameters and for @c NSSecureCoding.
+ */
+static NSString *const kScopeKey = @"scope";
+
+/*! @brief Key used to encode the @c additionalParameters property for @c NSSecureCoding
+ */
+static NSString *const kAdditionalParametersKey = @"additionalParameters";
+
+@implementation OIDTokenResponse
+
+/*! @brief Returns a mapping of incoming parameters to instance variables.
+ @return A mapping of incoming parameters to instance variables.
+ */
++ (NSDictionary *)fieldMap {
+ static NSMutableDictionary *fieldMap;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ fieldMap = [NSMutableDictionary dictionary];
+ fieldMap[kAccessTokenKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_accessToken" type:[NSString class]];
+ fieldMap[kExpiresInKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_accessTokenExpirationDate"
+ type:[NSDate class]
+ conversion:[OIDFieldMapping dateSinceNowConversion]];
+ fieldMap[kTokenTypeKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_tokenType" type:[NSString class]];
+ fieldMap[kIDTokenKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_idToken" type:[NSString class]];
+ fieldMap[kRefreshTokenKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_refreshToken" type:[NSString class]];
+ fieldMap[kScopeKey] =
+ [[OIDFieldMapping alloc] initWithName:@"_scope" type:[NSString class]];
+ });
+ return fieldMap;
+}
+
+#pragma mark - Initializers
+
+- (instancetype)init
+ OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithRequest:parameters:))
+
+- (instancetype)initWithRequest:(OIDTokenRequest *)request
+ parameters:(NSDictionary *> *)parameters {
+ self = [super init];
+ if (self) {
+ _request = [request copy];
+ NSDictionary *> *additionalParameters =
+ [OIDFieldMapping remainingParametersWithMap:[[self class] fieldMap]
+ parameters:parameters
+ instance:self];
+ _additionalParameters = additionalParameters;
+ }
+ return self;
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(nullable NSZone *)zone {
+ // The documentation for NSCopying specifically advises us to return a reference to the original
+ // instance in the case where instances are immutable (as ours is):
+ // "Implement NSCopying by retaining the original instead of creating a new copy when the class
+ // and its contents are immutable."
+ return self;
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+ return YES;
+}
+
+- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
+ OIDTokenRequest *request =
+ [aDecoder decodeObjectOfClass:[OIDTokenRequest class] forKey:kRequestKey];
+ self = [self initWithRequest:request parameters:@{ }];
+ if (self) {
+ [OIDFieldMapping decodeWithCoder:aDecoder map:[[self class] fieldMap] instance:self];
+ _additionalParameters = [aDecoder decodeObjectOfClasses:[OIDFieldMapping JSONTypes]
+ forKey:kAdditionalParametersKey];
+ }
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+ [OIDFieldMapping encodeWithCoder:aCoder map:[[self class] fieldMap] instance:self];
+ [aCoder encodeObject:_request forKey:kRequestKey];
+ [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey];
+}
+
+#pragma mark - NSObject overrides
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@: %p, accessToken: \"%@\", accessTokenExpirationDate: %@, "
+ "tokenType: %@, idToken: \"%@\", refreshToken: \"%@\", "
+ "scope: \"%@\", additionalParameters: %@, request: %@>",
+ NSStringFromClass([self class]),
+ (void *)self,
+ [OIDTokenUtilities redact:_accessToken],
+ _accessTokenExpirationDate,
+ _tokenType,
+ [OIDTokenUtilities redact:_idToken],
+ [OIDTokenUtilities redact:_refreshToken],
+ _scope,
+ _additionalParameters,
+ _request];
+}
+
+#pragma mark -
+
+@end
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenUtilities.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenUtilities.h
new file mode 100644
index 0000000000..fda8985465
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenUtilities.h
@@ -0,0 +1,67 @@
+/*! @file OIDTokenUtilities.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief Provides data encoding/decoding methods, random string generators, etc.
+ */
+@interface OIDTokenUtilities : NSObject
+
+/*! @internal
+ @brief Unavailable. This class should not be initialized.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/*! @brief Base64url-nopadding encodes the given data.
+ @param data The input data.
+ @return The base64url encoded data as a NSString.
+ @discussion Base64url-nopadding is used in several identity specs such as PKCE and
+ OpenID Connect.
+ */
++ (NSString *)encodeBase64urlNoPadding:(NSData *)data;
+
+/*! @brief Generates a URL-safe string of random data.
+ @param size The number of random bytes to encode. NB. the length of the output string will be
+ greater than the number of random bytes, due to the URL-safe encoding.
+ @return Random data encoded with base64url.
+ */
++ (nullable NSString *)randomURLSafeStringWithSize:(NSUInteger)size;
+
+/*! @brief SHA256 hashes the input string.
+ @param inputString The input string.
+ @return The SHA256 data.
+ */
++ (NSData *)sha256:(NSString *)inputString;
+
+/*! @brief Truncated intput string after first 6 characters followed by ellipses
+ @param inputString The input string.
+ @return Truncated string.
+ */
++ (nullable NSString *)redact:(nullable NSString *)inputString;
+
+/*! @brief Form url encode the input string by applying application/x-www-form-urlencoded algorithm
+ @param inputString The input string.
+ @return The encoded string.
+ */
++ (NSString*)formUrlEncode:(NSString*)inputString;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenUtilities.m b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenUtilities.m
new file mode 100644
index 0000000000..3280c856c1
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDTokenUtilities.m
@@ -0,0 +1,89 @@
+/*! @file OIDTokenUtilities.m
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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 "OIDTokenUtilities.h"
+
+#import
+
+/*! @brief String representing the set of characters that are allowed as is for the
+ application/x-www-form-urlencoded encoding algorithm.
+ */
+static NSString *const kFormUrlEncodedAllowedCharacters =
+ @" *-._0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+@implementation OIDTokenUtilities
+
++ (NSString *)encodeBase64urlNoPadding:(NSData *)data {
+ NSString *base64string = [data base64EncodedStringWithOptions:0];
+ // converts base64 to base64url
+ base64string = [base64string stringByReplacingOccurrencesOfString:@"+" withString:@"-"];
+ base64string = [base64string stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
+ // strips padding
+ base64string = [base64string stringByReplacingOccurrencesOfString:@"=" withString:@""];
+ return base64string;
+}
+
++ (nullable NSString *)randomURLSafeStringWithSize:(NSUInteger)size {
+ NSMutableData *randomData = [NSMutableData dataWithLength:size];
+ int result = SecRandomCopyBytes(kSecRandomDefault, randomData.length, randomData.mutableBytes);
+ if (result != 0) {
+ return nil;
+ }
+ return [[self class] encodeBase64urlNoPadding:randomData];
+}
+
++ (NSData *)sha256:(NSString *)inputString {
+ NSData *verifierData = [inputString dataUsingEncoding:NSUTF8StringEncoding];
+ NSMutableData *sha256Verifier = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
+ CC_SHA256(verifierData.bytes, (CC_LONG)verifierData.length, sha256Verifier.mutableBytes);
+ return sha256Verifier;
+}
+
++ (NSString *)redact:(NSString *)inputString {
+ if (inputString == nil) {
+ return nil;
+ }
+ switch(inputString.length){
+ case 0:
+ return @"";
+ case 1 ... 8:
+ return @"[redacted]";
+ case 9:
+ default:
+ return [[inputString substringToIndex:6] stringByAppendingString:@"...[redacted]"];
+ }
+}
+
++ (NSString*)formUrlEncode:(NSString*)inputString {
+ // https://www.w3.org/TR/html5/sec-forms.html#application-x-www-form-urlencoded-encoding-algorithm
+ // Following the spec from the above link, application/x-www-form-urlencoded percent encode all
+ // the characters except *-._A-Za-z0-9
+ // Space character is replaced by + in the resulting bytes sequence
+ if (inputString.length == 0) {
+ return inputString;
+ }
+ NSCharacterSet *allowedCharacters =
+ [NSCharacterSet characterSetWithCharactersInString:kFormUrlEncodedAllowedCharacters];
+ // Percent encode all characters not present in the provided set.
+ NSString *encodedString =
+ [inputString stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
+ // Replace occurences of space by '+' character
+ return [encodedString stringByReplacingOccurrencesOfString:@" " withString:@"+"];
+}
+
+@end
diff --git a/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDURLQueryComponent.h b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDURLQueryComponent.h
new file mode 100644
index 0000000000..054b11ea17
--- /dev/null
+++ b/src/ui/osx/AppAuth-actual/Source/AppAuthCore/OIDURLQueryComponent.h
@@ -0,0 +1,93 @@
+/*! @file OIDURLQueryComponent.h
+ @brief AppAuth iOS SDK
+ @copyright
+ Copyright 2015 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
+
+@class OIDAuthorizationRequest;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @brief If set to YES, will force the iOS 7-only code for @c OIDURLQueryComponent to be used,
+ even on non-iOS 7 devices and simulators. Useful for testing the iOS 7 code paths on the
+ simulator. Defaults to NO.
+ */
+extern BOOL gOIDURLQueryComponentForceIOS7Handling;
+
+/*! @brief A utility class for creating and parsing URL query components encoded with the
+ application/x-www-form-urlencoded format.
+ @description Supports application/x-www-form-urlencoded encoding and decoding, specifically
+ '+' is replaced with space before percent decoding. For encoding, simply percent encodes
+ space, as this is valid application/x-www-form-urlencoded.
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.2
+ @see https://tools.ietf.org/html/rfc6749#section-4.1.3
+ @see https://tools.ietf.org/html/rfc6749#appendix-B
+ @see https://url.spec.whatwg.org/#urlencoded-parsing
+ */
+@interface OIDURLQueryComponent : NSObject
+
+/*! @brief The parameter names in the query.
+ */
+@property(nonatomic, readonly) NSArray *parameters;
+
+/*! @brief The parameters represented as a dictionary.
+ @remarks All values are @c NSString except for parameters which contain multiple values, in
+ which case the value is an @c NSArray