diff --git a/.github/actions/setup-android/action.yml b/.github/actions/setup-android/action.yml index 41dcafce9..3de20f56d 100644 --- a/.github/actions/setup-android/action.yml +++ b/.github/actions/setup-android/action.yml @@ -25,7 +25,7 @@ runs: - name: Install Flutter uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 #pin@v2.23.0 with: - flutter-version: 3.29.3 + flutter-version: ${{ inputs.flutter }} channel: stable cache: true diff --git a/.github/actions/setup-darwin/action.yml b/.github/actions/setup-darwin/action.yml index d5eca643a..6e7586f9c 100644 --- a/.github/actions/setup-darwin/action.yml +++ b/.github/actions/setup-darwin/action.yml @@ -6,10 +6,6 @@ inputs: description: Either iOS or macOS required: true - ruby: - description: The version of Ruby to use - required: true - flutter: description: The version of Flutter to use required: true @@ -35,14 +31,6 @@ runs: run: echo "platform=$(echo ${{ inputs.platform }} | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT" shell: bash - - name: Set up Ruby - uses: ruby/setup-ruby@9eb537ca036ebaed86729dcb9309076e4c5c3b74 # pin@v1.314.0 - with: - ruby-version: ${{ inputs.ruby }} - bundler-cache: true - cache-version: 1 - working-directory: auth0_flutter/example/${{ steps.lowercase-platform.outputs.platform }} - - name: Install Flutter uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # pin@v2.23.0 with: @@ -50,15 +38,19 @@ runs: channel: stable cache: true + - name: Setup Xcode + run: sudo xcode-select --switch /Applications/Xcode_${{ inputs.xcode }}.app/Contents/Developer + shell: bash + + - name: Enable Swift Package Manager + run: flutter config --enable-swift-package-manager + shell: bash + - name: Install Flutter dependencies working-directory: auth0_flutter/example run: flutter pub get shell: bash - - name: Setup Xcode - run: sudo xcode-select --switch /Applications/Xcode_${{ inputs.xcode }}.app/Contents/Developer - shell: bash - - name: Save Xcode version run: xcodebuild -version | tee .xcode-version shell: bash @@ -75,6 +67,29 @@ runs: run: pod install shell: bash + - name: Fix iOS minimum deployment target for SPM + if: inputs.platform == 'iOS' + run: | + PACKAGE_FILE="auth0_flutter/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift" + if [ ! -f "$PACKAGE_FILE" ]; then + echo "::error::FlutterGeneratedPluginSwiftPackage/Package.swift not found at expected path" + exit 1 + fi + sed -i '' 's/\.iOS(".*")/.iOS("14.0")/g' "$PACKAGE_FILE" + shell: bash + + - name: Fix macOS minimum deployment target for SPM + if: inputs.platform == 'macOS' + run: | + PACKAGE_FILE="auth0_flutter/example/macos/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift" + if [ ! -f "$PACKAGE_FILE" ]; then + echo "::error::FlutterGeneratedPluginSwiftPackage/Package.swift not found at expected path" + exit 1 + fi + sed -i '' 's/\.macOS(".*")/.macOS("11.0")/g' "$PACKAGE_FILE" + shell: bash + + - name: Set .env working-directory: auth0_flutter/example run: printf '%s\n%s\n%s' 'AUTH0_DOMAIN=${{ inputs.auth0-domain }}' 'AUTH0_CLIENT_ID=${{ inputs.auth0-client-id }}' 'AUTH0_CUSTOM_SCHEME=demo' >> .env diff --git a/.github/actions/setup-publish/action.yml b/.github/actions/setup-publish/action.yml index 1f96ae27c..3732b173f 100644 --- a/.github/actions/setup-publish/action.yml +++ b/.github/actions/setup-publish/action.yml @@ -20,7 +20,10 @@ runs: flutter-version: ${{ inputs.flutter }} channel: stable cache: true - + + - name: Enable Swift Package Manager + run: flutter config --enable-swift-package-manager + shell: bash - name: Install Flutter dependencies working-directory: ${{ inputs.working-directory }} run: flutter pub get diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8dd254da9..f910f2dff 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,7 +13,6 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} env: - ruby: '3.3.1' flutter: '3.x' ios-simulator: iPhone 17 java: 17 @@ -139,7 +138,6 @@ jobs: uses: ./.github/actions/setup-darwin with: platform: ${{ env.platform }} - ruby: ${{ env.ruby }} flutter: ${{ env.flutter }} xcode: ${{ matrix.xcode }} auth0-domain: ${{ vars.AUTH0_DOMAIN }} @@ -151,15 +149,21 @@ jobs: platform: ${{ env.platform }} destination: ${{ format('{0}{1}', 'platform=iOS Simulator,name=', env.ios-simulator) }} - - name: Convert coverage report + # Codecov cannot parse a raw .xcresult bundle, so convert it to + # Cobertura XML first. xcresultparser is Ruby-free, keeping the SPM + # migration's goal of dropping the Ruby/slather toolchain. + - name: Convert xcresult to Cobertura coverage working-directory: auth0_flutter/example/ios - run: bundle exec slather coverage -x --scheme Runner Runner.xcodeproj + run: | + brew install a7ex/homebrew-formulae/xcresultparser + xcresultparser --output-format cobertura unit-tests.xcresult > coverage.xml + shell: bash - name: Upload coverage report uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: iOS coverage - path: auth0_flutter/example/ios/cobertura + path: auth0_flutter/example/ios/coverage.xml # TODO: fix both android and iOS smoke testcases and uncomment them. # test-ios-smoke: # name: Run native iOS smoke tests using Xcode ${{ matrix.xcode }} @@ -217,7 +221,6 @@ jobs: uses: ./.github/actions/setup-darwin with: platform: ${{ env.platform }} - ruby: ${{ env.ruby }} flutter: ${{ env.flutter }} xcode: ${{ matrix.xcode }} auth0-domain: ${{ vars.AUTH0_DOMAIN }} diff --git a/.gitignore b/.gitignore index 2478e6f9f..fb6ebee6a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,7 @@ coverage/ appium-test/node_modules/* .idea/* + +# Swift Package Manager +.build/ +.swiftpm/ diff --git a/auth0_flutter/README.md b/auth0_flutter/README.md index a9bc27719..abe32478e 100644 --- a/auth0_flutter/README.md +++ b/auth0_flutter/README.md @@ -40,6 +40,8 @@ Add auth0_flutter into your project: flutter pub add auth0_flutter ``` +> 💡 **iOS/macOS dependency management:** auth0_flutter supports both [Swift Package Manager](https://docs.flutter.dev/packages-and-plugins/swift-package-manager) and CocoaPods. If you have Swift Package Manager enabled in Flutter (`flutter config --enable-swift-package-manager`), the plugin and its native dependencies are resolved via SPM automatically. Otherwise, CocoaPods is used as a fallback — no extra setup is required either way. + ### Configure Auth0 #### 📱 Mobile/macOS diff --git a/auth0_flutter/darwin/.gitignore b/auth0_flutter/darwin/.gitignore index 55ff257cf..1251a6438 100644 --- a/auth0_flutter/darwin/.gitignore +++ b/auth0_flutter/darwin/.gitignore @@ -40,3 +40,9 @@ Icon? /Flutter/Generated.xcconfig /Flutter/ephemeral/ /Flutter/flutter_export_environment.sh + +# Swift Package Manager +.build/ +.swiftpm/ +Package.resolved +FlutterFramework/ diff --git a/auth0_flutter/darwin/Classes/Auth0FlutterPlugin.h b/auth0_flutter/darwin/Classes/Auth0FlutterPlugin.h deleted file mode 100644 index 52f280bcd..000000000 --- a/auth0_flutter/darwin/Classes/Auth0FlutterPlugin.h +++ /dev/null @@ -1,7 +0,0 @@ -#if TARGET_OS_IOS - #import -#else - #import -#endif -@interface Auth0FlutterPlugin : NSObject -@end diff --git a/auth0_flutter/darwin/Classes/Auth0FlutterPlugin.m b/auth0_flutter/darwin/Classes/Auth0FlutterPlugin.m deleted file mode 100644 index 295047da5..000000000 --- a/auth0_flutter/darwin/Classes/Auth0FlutterPlugin.m +++ /dev/null @@ -1,15 +0,0 @@ -#import "Auth0FlutterPlugin.h" -#if __has_include() -#import -#else -// Support project import fallback if the generated compatibility header -// is not copied when this plugin is created as a library. -// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 -#import "auth0_flutter-Swift.h" -#endif - -@implementation Auth0FlutterPlugin -+ (void)registerWithRegistrar:(NSObject*)registrar { - [SwiftAuth0FlutterPlugin registerWithRegistrar:registrar]; -} -@end diff --git a/auth0_flutter/darwin/Classes/Auth0FlutterPlugin.swift b/auth0_flutter/darwin/Classes/Auth0FlutterPlugin.swift new file mode 120000 index 000000000..58a503bbe --- /dev/null +++ b/auth0_flutter/darwin/Classes/Auth0FlutterPlugin.swift @@ -0,0 +1 @@ +../../../auth0_flutter/Sources/auth0_flutter/Auth0FlutterPlugin.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift deleted file mode 100644 index f415b3b75..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift +++ /dev/null @@ -1,48 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct AuthAPICustomTokenExchangeMethodHandler: MethodHandler { - enum Argument: String { - case subjectToken - case subjectTokenType - case audience - case scopes - case organization - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let subjectToken = arguments[Argument.subjectToken] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.subjectToken.rawValue))) - } - guard let subjectTokenType = arguments[Argument.subjectTokenType] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.subjectTokenType.rawValue))) - } - guard let scopes = arguments[Argument.scopes] as? [String], !scopes.isEmpty else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) - } - - let scope = scopes.asSpaceSeparatedString - let audience = arguments[Argument.audience] as? String - let organization = arguments[Argument.organization] as? String - - client - .customTokenExchange(subjectToken: subjectToken, - subjectTokenType: subjectTokenType, - audience: audience, - scope: scope, - organization: organization) - .start { - switch $0 { - case .success(let credentials): callback(self.result(from: credentials)) - case .failure(let error): callback(FlutterError(from: error)) - } - } - } -} \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift new file mode 120000 index 000000000..87b3601b8 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift deleted file mode 100644 index 5a9f79116..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift +++ /dev/null @@ -1,47 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct AuthAPIPasswordlessEmailMethodHandler: MethodHandler { - enum Argument: String { - case email - case passwordlessType - case parameters - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let email = arguments[Argument.email] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.email.rawValue))) - } - - guard let passwordlessTypeString = arguments[Argument.passwordlessType] as? String, - let passwordlessType = PasswordlessType(rawValue: passwordlessTypeString) else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.passwordlessType.rawValue))) - } - - guard let parameters = arguments[Argument.parameters] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - - client - .startPasswordless(email: email, - type: passwordlessType, - connection: "email" - ) - .parameters(["authParams":parameters]) - .start { - switch $0 { - case let .success: - callback(nil) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift new file mode 120000 index 000000000..7ad565bab --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIExtensions.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIExtensions.swift deleted file mode 100644 index c5ec36248..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIExtensions.swift +++ /dev/null @@ -1,61 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -enum AuthAPIErrorFlag: String, CaseIterable { - case isMultifactorRequired - case isMultifactorEnrollRequired - case isMultifactorCodeInvalid - case isMultifactorTokenInvalid - case isPasswordNotStrongEnough - case isPasswordAlreadyUsed - case isRuleError - case isInvalidCredentials - case isRefreshTokenDeleted - case isAccessDenied - case isTooManyAttempts - case isVerificationRequired - case isPasswordLeaked - case isLoginRequired - case isNetworkError -} - -enum AuthAPIErrorKey: String, CaseIterable { - case errorFlags = "_errorFlags" - case statusCode = "_statusCode" -} - -// MARK: - Extensions - -extension FlutterError { - convenience init(from authenticationError: AuthenticationError) { - let errorFlags: [String: Bool] = [ - AuthAPIErrorFlag.isMultifactorRequired.rawValue: authenticationError.isMultifactorRequired, - AuthAPIErrorFlag.isMultifactorEnrollRequired.rawValue: authenticationError.isMultifactorEnrollRequired, - AuthAPIErrorFlag.isMultifactorCodeInvalid.rawValue: authenticationError.isMultifactorCodeInvalid, - AuthAPIErrorFlag.isMultifactorTokenInvalid.rawValue: authenticationError.isMultifactorTokenInvalid, - AuthAPIErrorFlag.isPasswordNotStrongEnough.rawValue: authenticationError.isPasswordNotStrongEnough, - AuthAPIErrorFlag.isPasswordAlreadyUsed.rawValue: authenticationError.isPasswordAlreadyUsed, - AuthAPIErrorFlag.isRuleError.rawValue: authenticationError.isRuleError, - AuthAPIErrorFlag.isInvalidCredentials.rawValue: authenticationError.isInvalidCredentials, - AuthAPIErrorFlag.isRefreshTokenDeleted.rawValue: authenticationError.isRefreshTokenDeleted, - AuthAPIErrorFlag.isAccessDenied.rawValue: authenticationError.isAccessDenied, - AuthAPIErrorFlag.isTooManyAttempts.rawValue: authenticationError.isTooManyAttempts, - AuthAPIErrorFlag.isVerificationRequired.rawValue: authenticationError.isVerificationRequired, - AuthAPIErrorFlag.isPasswordLeaked.rawValue: authenticationError.isPasswordLeaked, - AuthAPIErrorFlag.isLoginRequired.rawValue: authenticationError.isLoginRequired, - AuthAPIErrorFlag.isNetworkError.rawValue: authenticationError.isNetworkError, - ] - var errorDetails = authenticationError.details - errorDetails[AuthAPIErrorKey.errorFlags] = errorFlags - errorDetails[AuthAPIErrorKey.statusCode] = authenticationError.statusCode - - self.init(code: authenticationError.code, - message: String(describing: authenticationError), - details: errorDetails) - } -} diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIExtensions.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIExtensions.swift new file mode 120000 index 000000000..abb6f7d4a --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIExtensions.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIHandler.swift deleted file mode 100644 index eb41b2cb9..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIHandler.swift +++ /dev/null @@ -1,123 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -// MARK: - Providers - -typealias AuthAPIClientProvider = (_ account: Account, _ userAgent: UserAgent, _ arguments: [String: Any]) -> Authentication -typealias AuthAPIMethodHandlerProvider = (_ method: AuthAPIHandler.Method, _ client: Authentication) -> MethodHandler - -// MARK: - Auth Auth Handler - -public class AuthAPIHandler: NSObject, FlutterPlugin { - enum Method: String, CaseIterable { - case loginWithUsernameOrEmail = "auth#login" - case loginWithOTP = "auth#loginOtp" - case multifactorChallenge = "auth#multifactorChallenge" - case signup = "auth#signUp" - case userInfo = "auth#userInfo" - case renew = "auth#renew" - case customTokenExchange = "auth#customTokenExchange" - case resetPassword = "auth#resetPassword" - case passwordlessWithEmail = "auth#passwordlessWithEmail" - case passwordlessWithPhoneNumber = "auth#passwordlessWithPhoneNumber" - case loginWithEmailCode = "auth#loginWithEmail" - case loginWithSMSCode = "auth#loginWithPhoneNumber" - case ssoExchange = "auth#ssoExchange" - case passkeyLoginChallenge = "auth#passkeyLoginChallenge" - case passkeySignupChallenge = "auth#passkeySignupChallenge" - case passkeyCredentialExchange = "auth#passkeyCredentialExchange" - } - - private static let channelName = "auth0.com/auth0_flutter/auth" - - public static func register(with registrar: FlutterPluginRegistrar) { - let handler = AuthAPIHandler() - - #if os(iOS) - let channel = FlutterMethodChannel(name: AuthAPIHandler.channelName, - binaryMessenger: registrar.messenger()) - #else - let channel = FlutterMethodChannel(name: AuthAPIHandler.channelName, - binaryMessenger: registrar.messenger) - #endif - - registrar.addMethodCallDelegate(handler, channel: channel) - } - - var clientProvider: AuthAPIClientProvider = { account, userAgent, arguments in - var client = Auth0.authentication(clientId: account.clientId, domain: account.domain) - client.using(inLibrary: userAgent.name, version: userAgent.version) - - let useDPoP = arguments["useDPoP"] as? Bool ?? false - if useDPoP { - client = client.useDPoP() - } - - return client - } - - var methodHandlerProvider: AuthAPIMethodHandlerProvider = { method, client in - switch method { - case .loginWithUsernameOrEmail: return AuthAPILoginUsernameOrEmailMethodHandler(client: client) - case .loginWithOTP: return AuthAPILoginWithOTPMethodHandler(client: client) - case .multifactorChallenge: return AuthAPIMultifactorChallengeMethodHandler(client: client) - case .signup: return AuthAPISignupMethodHandler(client: client) - case .userInfo: return AuthAPIUserInfoMethodHandler(client: client) - case .renew: return AuthAPIRenewMethodHandler(client: client) - case .customTokenExchange: return AuthAPICustomTokenExchangeMethodHandler(client: client) - case .resetPassword: return AuthAPIResetPasswordMethodHandler(client: client) - case .passwordlessWithEmail: return AuthAPIPasswordlessEmailMethodHandler(client: client) - case .passwordlessWithPhoneNumber: return AuthAPIPasswordlessPhoneNumberMethodHandler(client: client) - case .loginWithEmailCode: return AuthAPILoginWithEmailMethodHandler(client: client) - case .loginWithSMSCode: return AuthAPILoginWithPhoneNumberMethodHandler(client: client) - case .ssoExchange: return SSOExchangeMethodHandler(client: client) - #if PASSKEYS_PLATFORM - case .passkeyLoginChallenge: - if #available(iOS 16.6, macOS 13.5, visionOS 1.0, *) { - return AuthAPIPasskeyLoginChallengeMethodHandler(client: client) - } - return UnsupportedMethodHandler() - case .passkeySignupChallenge: - if #available(iOS 16.6, macOS 13.5, visionOS 1.0, *) { - return AuthAPIPasskeySignupChallengeMethodHandler(client: client) - } - return UnsupportedMethodHandler() - case .passkeyCredentialExchange: - if #available(iOS 16.6, macOS 13.5, visionOS 1.0, *) { - return AuthAPIPasskeyCredentialExchangeMethodHandler(client: client) - } - return UnsupportedMethodHandler() - #else - case .passkeyLoginChallenge, .passkeySignupChallenge, .passkeyCredentialExchange: - return UnsupportedMethodHandler() - #endif - } - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - guard let arguments = call.arguments as? [String: Any] else { - return result(FlutterError(from: .argumentsMissing)) - } - guard let accountDictionary = arguments[Account.key] as? [String: String], - let account = Account(from: accountDictionary) else { - return result(FlutterError(from: .accountMissing)) - } - guard let userAgentDictionary = arguments[UserAgent.key] as? [String: String], - let userAgent = UserAgent(from: userAgentDictionary) else { - return result(FlutterError(from: .userAgentMissing)) - } - guard let method = Method(rawValue: call.method) else { - return result(FlutterMethodNotImplemented) - } - - let client = clientProvider(account, userAgent, arguments) - let methodHandler = methodHandlerProvider(method, client) - - methodHandler.handle(with: arguments, callback: result) - } -} diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIHandler.swift new file mode 120000 index 000000000..d45066336 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift deleted file mode 100644 index eed76dc20..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift +++ /dev/null @@ -1,54 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct AuthAPILoginUsernameOrEmailMethodHandler: MethodHandler { - enum Argument: String { - case usernameOrEmail - case password - case connectionOrRealm - case scopes - case parameters - case audience - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let usernameOrEmail = arguments[Argument.usernameOrEmail] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.usernameOrEmail.rawValue))) - } - guard let password = arguments[Argument.password] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.password.rawValue))) - } - guard let connectionOrRealm = arguments[Argument.connectionOrRealm] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.connectionOrRealm.rawValue))) - } - guard let scopes = arguments[Argument.scopes] as? [String] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) - } - guard let parameters = arguments[Argument.parameters] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - - let audience = arguments[Argument.audience] as? String - - client - .login(usernameOrEmail: usernameOrEmail, - password: password, - realmOrConnection: connectionOrRealm, - audience: audience, - scope: scopes.asSpaceSeparatedString) - .parameters(parameters) - .start { - switch $0 { - case let .success(credentials): callback(result(from: credentials)) - case let .failure(error): callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift new file mode 120000 index 000000000..f568e6da9 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift deleted file mode 100644 index 02f2f23d6..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift +++ /dev/null @@ -1,54 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct AuthAPILoginWithEmailMethodHandler: MethodHandler { - - enum Argument: String { - case email - case verificationCode - case scopes - case audience - case parameters - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let email = arguments[Argument.email] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.email.rawValue))) - } - - guard let verificationCode = arguments[Argument.verificationCode] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.verificationCode.rawValue))) - } - - guard let scopes = arguments[Argument.scopes] as? [String] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) - } - - guard let parameters = arguments[Argument.parameters] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - - let audience = arguments[Argument.audience] as? String - - client - .login(email: email, - code: verificationCode, - audience: audience, - scope: scopes.asSpaceSeparatedString - ) - .parameters(parameters) - .start { - switch $0 { - case let .success(credentials): callback(result(from: credentials)) - case let .failure(error):callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift new file mode 120000 index 000000000..fa137a137 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift deleted file mode 100644 index e1a36cf8f..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift +++ /dev/null @@ -1,34 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct AuthAPILoginWithOTPMethodHandler: MethodHandler { - enum Argument: String { - case otp - case mfaToken - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let otp = arguments[Argument.otp] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.otp.rawValue))) - } - guard let mfaToken = arguments[Argument.mfaToken] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.mfaToken.rawValue))) - } - - client - .login(withOTP: otp, mfaToken: mfaToken) - .start { - switch $0 { - case let .success(credentials): callback(result(from: credentials)) - case let .failure(error): callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift new file mode 120000 index 000000000..9d7c0ad79 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift deleted file mode 100644 index be1a517b3..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift +++ /dev/null @@ -1,55 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct AuthAPILoginWithPhoneNumberMethodHandler: MethodHandler { - enum Argument: String { - case phoneNumber - case verificationCode - case scopes - case audience - case parameters - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let phoneNumber = arguments[Argument.phoneNumber] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.phoneNumber.rawValue))) - } - - guard let verificationCode = arguments[Argument.verificationCode] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.verificationCode.rawValue))) - } - - guard let scopes = arguments[Argument.scopes] as? [String] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) - } - - guard let parameters = arguments[Argument.parameters] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - - - let audience = arguments[Argument.audience] as? String - - client - .login(phoneNumber: phoneNumber, - code: verificationCode, - audience: audience, - scope: scopes.asSpaceSeparatedString - ) - .parameters(parameters) - .start { - switch $0 { - case let .success(credentials): callback(result(from: credentials)) - case let .failure(error):callback(FlutterError(from: error)) - } - } - } -} - diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift new file mode 120000 index 000000000..4433691f5 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift deleted file mode 100644 index a409a4670..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift +++ /dev/null @@ -1,51 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -enum ChallengeProperty: String { - case challengeType - case oobCode - case bindingMethod -} - -fileprivate extension MethodHandler { - func result(from challenge: Challenge) -> Any? { - var data: [String: Any] = [ChallengeProperty.challengeType.rawValue: challenge.challengeType] - data[ChallengeProperty.oobCode] = challenge.oobCode - data[ChallengeProperty.bindingMethod] = challenge.bindingMethod - return data - } -} - -struct AuthAPIMultifactorChallengeMethodHandler: MethodHandler { - enum Argument: String { - case mfaToken - case types - case authenticatorId - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let mfaToken = arguments[Argument.mfaToken] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.mfaToken.rawValue))) - } - - let types = arguments[Argument.types] as? [String] - let authenticatorId = arguments[Argument.authenticatorId] as? String - - client - .multifactorChallenge(mfaToken: mfaToken, types: types, authenticatorId: authenticatorId) - .start { - switch $0 { - case let .success(challenge): callback(result(from: challenge)) - case let .failure(error): callback(FlutterError(from: error)) - } - - } - } -} diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift new file mode 120000 index 000000000..9648cc33e --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift deleted file mode 100644 index 5849d52eb..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift +++ /dev/null @@ -1,235 +0,0 @@ -#if PASSKEYS_PLATFORM -import Auth0 -import AuthenticationServices - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -/// A ``LoginPasskey`` reconstructed from a credential map provided by the -/// Flutter layer (the app presents the OS passkey UI and passes the resulting -/// assertion). -@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) -private struct ReconstructedLoginPasskey: LoginPasskey { - let userID: Data! - let credentialID: Data - let attachment: ASAuthorizationPublicKeyCredentialAttachment - let rawClientDataJSON: Data - let rawAuthenticatorData: Data! - let signature: Data! -} - -/// A ``SignupPasskey`` reconstructed from a credential map supplied by the app -/// (for example, from `ASAuthorizationController`). -@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) -private struct ReconstructedSignupPasskey: SignupPasskey { - let credentialID: Data - let attachment: ASAuthorizationPublicKeyCredentialAttachment - let rawClientDataJSON: Data - let rawAttestationObject: Data? -} - -/// Exchanges an app-supplied passkey credential (a login assertion or a signup -/// attestation) and its challenge for Auth0 tokens at the `/oauth/token` -/// endpoint. This handler does not present any UI. -/// -/// Both passkey login and signup finish here. The credential's `response` -/// determines the flow: an `attestationObject` indicates a signup attestation, -/// while `authenticatorData` + `signature` indicate a login assertion. The -/// matching `LoginPasskey`/`SignupPasskey` and challenge are reconstructed and -/// passed to the shared `Authentication.login(passkey:challenge:...)` call. -@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) -struct AuthAPIPasskeyCredentialExchangeMethodHandler: MethodHandler { - enum Argument: String { - case challenge - case credential - case connection - case audience - case scopes - case organization - case parameters - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let challengeMap = arguments[Argument.challenge.rawValue] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.challenge.rawValue))) - } - guard let credentialMap = arguments[Argument.credential.rawValue] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.credential.rawValue))) - } - - let connection = arguments[Argument.connection.rawValue] as? String - let audience = arguments[Argument.audience.rawValue] as? String - let scopes = (arguments[Argument.scopes.rawValue] as? [String]) ?? [] - let organization = arguments[Argument.organization.rawValue] as? String - let parameters = (arguments[Argument.parameters.rawValue] as? [String: Any]) ?? [:] - - let response = credentialMap["response"] as? [String: Any] - let isSignup = response?["attestationObject"] != nil - - let request: Request - if isSignup { - guard let challenge = Self.reconstructSignupChallenge(from: challengeMap) else { - return callback(FlutterError(code: "PASSKEY_ERROR", - message: "Failed to reconstruct signup challenge", - details: nil)) - } - guard let passkey = Self.reconstructSignupPasskey(from: credentialMap) else { - return callback(FlutterError(code: "PASSKEY_ERROR", - message: "Failed to reconstruct passkey credential", - details: nil)) - } - request = client.login(passkey: passkey, - challenge: challenge, - connection: connection, - audience: audience, - scope: scopes.asSpaceSeparatedString, - organization: organization) - } else { - guard let challenge = Self.reconstructLoginChallenge(from: challengeMap) else { - return callback(FlutterError(code: "PASSKEY_ERROR", - message: "Failed to reconstruct login challenge", - details: nil)) - } - guard let passkey = Self.reconstructLoginPasskey(from: credentialMap) else { - return callback(FlutterError(code: "PASSKEY_ERROR", - message: "Failed to reconstruct passkey credential", - details: nil)) - } - request = client.login(passkey: passkey, - challenge: challenge, - connection: connection, - audience: audience, - scope: scopes.asSpaceSeparatedString, - organization: organization) - } - - request - .parameters(parameters) - .start { - switch $0 { - case let .success(credentials): - callback(self.result(from: credentials)) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } - - // MARK: - Login reconstruction - - private static func reconstructLoginChallenge( - from challengeMap: [String: Any]) -> PasskeyLoginChallenge? { - guard let authParamsPublicKey = challengeMap["authParamsPublicKey"] as? [String: Any], - let authSession = challengeMap["authSession"] as? String, - let challengeString = authParamsPublicKey["challenge"] as? String, - let relyingPartyId = authParamsPublicKey["rpId"] as? String else { - return nil - } - - let challengeJson: [String: Any] = [ - "auth_session": authSession, - "authn_params_public_key": [ - "rpId": relyingPartyId, - "challenge": challengeString - ] - ] - - guard let jsonData = try? JSONSerialization.data(withJSONObject: challengeJson) else { - return nil - } - return try? JSONDecoder().decode(PasskeyLoginChallenge.self, from: jsonData) - } - - private static func reconstructLoginPasskey( - from credentialMap: [String: Any]) -> LoginPasskey? { - guard let credentialIdString = credentialMap["rawId"] as? String - ?? credentialMap["id"] as? String, - let credentialID = Data.fromBase64URLEncoded(credentialIdString), - let response = credentialMap["response"] as? [String: Any], - let clientDataString = response["clientDataJSON"] as? String, - let rawClientDataJSON = Data.fromBase64URLEncoded(clientDataString), - let authenticatorDataString = response["authenticatorData"] as? String, - let rawAuthenticatorData = Data.fromBase64URLEncoded(authenticatorDataString), - let signatureString = response["signature"] as? String, - let signature = Data.fromBase64URLEncoded(signatureString) else { - return nil - } - - // Auth0.swift force-unwraps `userID` when building the request, so fall - // back to empty data rather than nil when no user handle was returned. - let userID = (response["userHandle"] as? String) - .flatMap { Data.fromBase64URLEncoded($0) } ?? Data() - - let attachment: ASAuthorizationPublicKeyCredentialAttachment = - (credentialMap["authenticatorAttachment"] as? String) == "crossPlatform" - ? .crossPlatform : .platform - - return ReconstructedLoginPasskey( - userID: userID, - credentialID: credentialID, - attachment: attachment, - rawClientDataJSON: rawClientDataJSON, - rawAuthenticatorData: rawAuthenticatorData, - signature: signature - ) - } - - // MARK: - Signup reconstruction - - private static func reconstructSignupChallenge( - from challengeMap: [String: Any]) -> PasskeySignupChallenge? { - guard let authParamsPublicKey = challengeMap["authParamsPublicKey"] as? [String: Any], - let authSession = challengeMap["authSession"] as? String, - let challengeString = authParamsPublicKey["challenge"] as? String, - let relyingPartyId = authParamsPublicKey["rpId"] as? String, - let userId = authParamsPublicKey["userId"] as? String, - let userName = authParamsPublicKey["userName"] as? String else { - return nil - } - - let challengeJson: [String: Any] = [ - "auth_session": authSession, - "authn_params_public_key": [ - "rp": ["id": relyingPartyId], - "user": ["id": userId, "name": userName], - "challenge": challengeString - ] - ] - - guard let jsonData = try? JSONSerialization.data(withJSONObject: challengeJson) else { - return nil - } - return try? JSONDecoder().decode(PasskeySignupChallenge.self, from: jsonData) - } - - private static func reconstructSignupPasskey( - from credentialMap: [String: Any]) -> SignupPasskey? { - guard let credentialIdString = credentialMap["rawId"] as? String - ?? credentialMap["id"] as? String, - let credentialID = Data.fromBase64URLEncoded(credentialIdString), - let response = credentialMap["response"] as? [String: Any], - let clientDataString = response["clientDataJSON"] as? String, - let rawClientDataJSON = Data.fromBase64URLEncoded(clientDataString), - let attestationString = response["attestationObject"] as? String, - let rawAttestationObject = Data.fromBase64URLEncoded(attestationString) else { - return nil - } - - let attachment: ASAuthorizationPublicKeyCredentialAttachment = - (credentialMap["authenticatorAttachment"] as? String) == "crossPlatform" - ? .crossPlatform : .platform - - return ReconstructedSignupPasskey( - credentialID: credentialID, - attachment: attachment, - rawClientDataJSON: rawClientDataJSON, - rawAttestationObject: rawAttestationObject - ) - } -} -#endif diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift new file mode 120000 index 000000000..234c73c90 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift deleted file mode 100644 index 213681b3a..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift +++ /dev/null @@ -1,21 +0,0 @@ -#if PASSKEYS_PLATFORM -import Foundation - -extension Data { - func base64URLEncodedString() -> String { - return self.base64EncodedString() - .replacingOccurrences(of: "+", with: "-") - .replacingOccurrences(of: "/", with: "_") - .trimmingCharacters(in: CharacterSet(charactersIn: "=")) - } - - static func fromBase64URLEncoded(_ string: String) -> Data? { - var base64 = string - .replacingOccurrences(of: "-", with: "+") - .replacingOccurrences(of: "_", with: "/") - let paddingLength = (4 - base64.count % 4) % 4 - base64 += String(repeating: "=", count: paddingLength) - return Data(base64Encoded: base64) - } -} -#endif diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift new file mode 120000 index 000000000..bb5aa79f4 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeyExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift deleted file mode 100644 index 5f0ed3928..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift +++ /dev/null @@ -1,47 +0,0 @@ -#if PASSKEYS_PLATFORM -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) -struct AuthAPIPasskeyLoginChallengeMethodHandler: MethodHandler { - enum Argument: String { - case connection - case organization - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - let connection = arguments[Argument.connection] as? String - let organization = arguments[Argument.organization] as? String - - client - .passkeyLoginChallenge(connection: connection, organization: organization) - .start { - switch $0 { - case let .success(challenge): - // Unlike Android, the iOS Auth0.swift challenge only exposes - // the relying-party id and challenge data; `timeout` and - // `userVerification` are not surfaced by the native API and - // are not needed to build the assertion request here. The - // asymmetry with the Android payload is intentional. - let response: [String: Any] = [ - "authSession": challenge.authenticationSession, - "authParamsPublicKey": [ - "challenge": challenge.challengeData.base64URLEncodedString(), - "rpId": challenge.relyingPartyId - ] - ] - callback(response) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} -#endif diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift new file mode 120000 index 000000000..8005a0c85 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift deleted file mode 100644 index 3e7fe20cf..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift +++ /dev/null @@ -1,72 +0,0 @@ -#if PASSKEYS_PLATFORM -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) -struct AuthAPIPasskeySignupChallengeMethodHandler: MethodHandler { - enum Argument: String { - case email - case phoneNumber - case username - case name - case givenName - case familyName - case nickname - case picture - case connection - case organization - case userMetadata - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - let email = arguments[Argument.email] as? String - let phoneNumber = arguments[Argument.phoneNumber] as? String - let username = arguments[Argument.username] as? String - let name = arguments[Argument.name] as? String - let givenName = arguments[Argument.givenName] as? String - let familyName = arguments[Argument.familyName] as? String - let nickname = arguments[Argument.nickname] as? String - let picture = arguments[Argument.picture] as? String - let connection = arguments[Argument.connection] as? String - let organization = arguments[Argument.organization] as? String - let userMetadata = arguments[Argument.userMetadata] as? [String: String] - - client - .passkeySignupChallenge(email: email, - phoneNumber: phoneNumber, - username: username, - name: name, - givenName: givenName, - familyName: familyName, - nickname: nickname, - picture: picture, - userMetadata: userMetadata, - connection: connection, - organization: organization) - .start { - switch $0 { - case let .success(challenge): - let response: [String: Any] = [ - "authSession": challenge.authenticationSession, - "authParamsPublicKey": [ - "challenge": challenge.challengeData.base64URLEncodedString(), - "rpId": challenge.relyingPartyId, - "userId": challenge.userId.base64URLEncodedString(), - "userName": challenge.userName - ] - ] - callback(response) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} -#endif diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift new file mode 120000 index 000000000..04eb9d249 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift deleted file mode 100644 index c09f52e6a..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift +++ /dev/null @@ -1,49 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct AuthAPIPasswordlessPhoneNumberMethodHandler: MethodHandler { - enum Argument: String { - case phoneNumber - case passwordlessType - case parameters - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let phoneNumber = arguments[Argument.phoneNumber] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.phoneNumber.rawValue))) - } - - guard let passwordlessTypeString = arguments[Argument.passwordlessType] as? String, - let passwordlessType = PasswordlessType(rawValue: passwordlessTypeString) else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.passwordlessType.rawValue))) - } - - guard let parameters = arguments[Argument.parameters] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - - client - .startPasswordless(phoneNumber: phoneNumber, - type: passwordlessType, - connection: "sms" - ) - .parameters(["authParams":parameters]) - .start { - switch $0 { - case .success: - callback(nil) - - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} - diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift new file mode 120000 index 000000000..4eb7f0e95 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift deleted file mode 100644 index 5e21075a7..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift +++ /dev/null @@ -1,40 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct AuthAPIRenewMethodHandler: MethodHandler { - enum Argument: String { - case refreshToken - case scopes - case parameters - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let refreshToken = arguments[Argument.refreshToken] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.refreshToken.rawValue))) - } - guard let scopes = arguments[Argument.scopes] as? [String] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) - } - guard let parameters = arguments[Argument.parameters] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - - client - .renew(withRefreshToken: refreshToken, - scope: scopes.isEmpty ? nil : scopes.asSpaceSeparatedString) - .parameters(parameters) - .start { - switch $0 { - case let .success(credentials): callback(result(from: credentials)) - case let .failure(error): callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift new file mode 120000 index 000000000..8285db055 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIRenewMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift deleted file mode 100644 index f1a844e91..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift +++ /dev/null @@ -1,39 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct AuthAPIResetPasswordMethodHandler: MethodHandler { - enum Argument: String { - case email - case connection - case parameters - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let email = arguments[Argument.email] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.email.rawValue))) - } - guard let connection = arguments[Argument.connection] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.connection.rawValue))) - } - guard let parameters = arguments[Argument.parameters] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - - client - .resetPassword(email: email, connection: connection) - .parameters(parameters) - .start { - switch $0 { - case .success: callback(nil) - case let .failure(error): callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift new file mode 120000 index 000000000..99dc67350 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIResetPasswordMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPISignupMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPISignupMethodHandler.swift deleted file mode 100644 index 650698d8f..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPISignupMethodHandler.swift +++ /dev/null @@ -1,72 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -enum DatabaseUserProperty: String { - case email - case emailVerified - case username -} - -fileprivate extension MethodHandler { - func result(from databaseUser: DatabaseUser) -> Any? { - var data: [String: Any] = [ - DatabaseUserProperty.email.rawValue: databaseUser.email, - DatabaseUserProperty.emailVerified.rawValue: databaseUser.verified - ] - data[DatabaseUserProperty.username] = databaseUser.username - return data - } -} - -struct AuthAPISignupMethodHandler: MethodHandler { - enum Argument: String { - case email - case password - case connection - case username - case userMetadata - case parameters - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let email = arguments[Argument.email] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.email.rawValue))) - } - guard let password = arguments[Argument.password] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.password.rawValue))) - } - guard let connection = arguments[Argument.connection] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.connection.rawValue))) - } - guard let userMetadata = arguments[Argument.userMetadata] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.userMetadata.rawValue))) - } - guard let parameters = arguments[Argument.parameters] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - - let username = arguments[Argument.username] as? String - - client - .signup(email: email, - username: username, - password: password, - connection: connection, - userMetadata: userMetadata) - .parameters(parameters) - .start { - switch $0 { - case let .success(databaseUser): callback(result(from: databaseUser)) - case let .failure(error): callback(FlutterError(from: error)) - } - - } - } -} diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPISignupMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPISignupMethodHandler.swift new file mode 120000 index 000000000..71d3dbadc --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPISignupMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPISignupMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift deleted file mode 100644 index 2790d109a..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -fileprivate extension MethodHandler { - func result(from userInfo: UserInfo) -> Any? { - return userInfo.asDictionary() - } -} - -struct AuthAPIUserInfoMethodHandler: MethodHandler { - enum Argument: String { - case accessToken - case parameters - case tokenType - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let accessToken = arguments[Argument.accessToken] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.accessToken.rawValue))) - } - guard let parameters = arguments[Argument.parameters] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - - let tokenType = arguments[Argument.tokenType] as? String ?? "Bearer" - - client - .userInfo(withAccessToken: accessToken, tokenType: tokenType) - .parameters(parameters) - .start { - switch $0 { - case let .success(userInfo): callback(result(from: userInfo)) - case let .failure(error): callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift new file mode 120000 index 000000000..ccbec5c96 --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIUserInfoMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/AuthAPI/SSOExchangeMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/SSOExchangeMethodHandler.swift deleted file mode 100644 index 6cf5c08f4..000000000 --- a/auth0_flutter/darwin/Classes/AuthAPI/SSOExchangeMethodHandler.swift +++ /dev/null @@ -1,50 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct SSOExchangeMethodHandler: MethodHandler { - enum Argument: String { - case refreshToken - case parameters - case headers - } - - let client: Authentication - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let refreshToken = arguments[Argument.refreshToken] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.refreshToken.rawValue))) - } - guard let parameters = arguments[Argument.parameters] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - guard let headers = arguments[Argument.headers] as? [String: String] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.headers.rawValue))) - } - - client - .ssoExchange(withRefreshToken: refreshToken) - .parameters(parameters) - .headers(headers) - .start { - switch $0 { - case let .success(ssoCredentials): - var response: [String: Any] = [ - "sessionTransferToken": ssoCredentials.sessionTransferToken, - "tokenType": ssoCredentials.issuedTokenType, - "expiresIn": Int(ssoCredentials.expiresIn.timeIntervalSinceNow) - ] - response["idToken"] = ssoCredentials.idToken - if let refreshToken = ssoCredentials.refreshToken { - response["refreshToken"] = refreshToken - } - callback(response) - case let .failure(error): callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/AuthAPI/SSOExchangeMethodHandler.swift b/auth0_flutter/darwin/Classes/AuthAPI/SSOExchangeMethodHandler.swift new file mode 120000 index 000000000..d594c2f4a --- /dev/null +++ b/auth0_flutter/darwin/Classes/AuthAPI/SSOExchangeMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/AuthAPI/SSOExchangeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift deleted file mode 100644 index b884e1b03..000000000 --- a/auth0_flutter/darwin/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift +++ /dev/null @@ -1,50 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct ApiCredentialsMethodHandler: MethodHandler { - - enum Argument: String { - case audience - case scopes - case minTtl - case parameters - case headers - } - - let credentialsManager: CredentialsManager - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let audience = arguments[Argument.audience] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.audience.rawValue))) - } - guard let scopes = arguments[Argument.scopes] as? [String] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) - } - guard let minTTL = arguments[Argument.minTtl] as? Int else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.minTtl.rawValue))) - } - guard let parameters = arguments[Argument.parameters] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - guard let headers = arguments[Argument.headers] as? [String: String] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.headers.rawValue))) - } - - self.credentialsManager.apiCredentials(forAudience: audience, - scope: scopes.isEmpty ? nil : scopes.asSpaceSeparatedString, - minTTL: minTTL, - parameters: parameters, - headers: headers) { - switch $0 { - case let .success(apiCredentials): callback(apiCredentials.asDictionary()) - case let .failure(error): callback(FlutterError(from: error)) - } - } - } - -} diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift new file mode 120000 index 000000000..f9361f16b --- /dev/null +++ b/auth0_flutter/darwin/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/CredentialsManager/ApiCredentialsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift deleted file mode 100644 index ef3fdbea7..000000000 --- a/auth0_flutter/darwin/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift +++ /dev/null @@ -1,27 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct ClearApiCredentialsMethodHandler: MethodHandler { - - enum Argument: String { - case audience - case scope - } - - let credentialsManager: CredentialsManager - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let audience = arguments[Argument.audience] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.audience.rawValue))) - } - let scope = arguments[Argument.scope] as? String - - callback(self.credentialsManager.clear(forAudience: audience, scope: scope)) - } - -} diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift new file mode 120000 index 000000000..6733bd5ca --- /dev/null +++ b/auth0_flutter/darwin/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/CredentialsManager/ClearApiCredentialsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift deleted file mode 100644 index 000136322..000000000 --- a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct CredentialsManagerClearMethodHandler: MethodHandler { - let credentialsManager: CredentialsManager - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - callback(self.credentialsManager.clear()) - } -} diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift new file mode 120000 index 000000000..c0c0fb8d8 --- /dev/null +++ b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerClearMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerExtensions.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerExtensions.swift deleted file mode 100644 index a3efc75ba..000000000 --- a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerExtensions.swift +++ /dev/null @@ -1,32 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -extension FlutterError { - convenience init(from credentialsManagerError: CredentialsManagerError) { - var code: String - switch credentialsManagerError { - case .noCredentials: code = "NO_CREDENTIALS" - case .noRefreshToken: code = "NO_REFRESH_TOKEN" - case .renewFailed: code = "RENEW_FAILED" - case .storeFailed: code = "STORE_FAILED" - case .biometricsFailed: code = "BIOMETRICS_FAILED" - case .revokeFailed: code = "REVOKE_FAILED" - case .largeMinTTL: code = "LARGE_MIN_TTL" - default: code = "UNKNOWN" - } - - let isRetryable = (credentialsManagerError.cause as? Auth0APIError)?.isRetryable ?? false - - var errorDetails = credentialsManagerError.details - errorDetails["_isRetryable"] = isRetryable - - self.init(code: code, - message: String(describing: credentialsManagerError), - details: errorDetails) - } -} diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerExtensions.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerExtensions.swift new file mode 120000 index 000000000..85bfaeb10 --- /dev/null +++ b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerExtensions.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift deleted file mode 100644 index 11eccc07a..000000000 --- a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift +++ /dev/null @@ -1,38 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct CredentialsManagerGetMethodHandler: MethodHandler { - enum Argument: String { - case scopes - case minTtl - case parameters - } - - let credentialsManager: CredentialsManager - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let scopes = arguments[Argument.scopes] as? [String] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) - } - guard let minTTL = arguments[Argument.minTtl] as? Int else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.minTtl.rawValue))) - } - guard let parameters = arguments[Argument.parameters] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - - self.credentialsManager.credentials(withScope: scopes.isEmpty ? nil : scopes.asSpaceSeparatedString, - minTTL: minTTL, - parameters: parameters) { - switch $0 { - case let .success(credentials): callback(result(from: credentials)) - case let .failure(error): callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift new file mode 120000 index 000000000..a0f5322f7 --- /dev/null +++ b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerGetMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerHandler.swift deleted file mode 100644 index 908097dfe..000000000 --- a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerHandler.swift +++ /dev/null @@ -1,167 +0,0 @@ -import Auth0 -import SimpleKeychain - - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -// MARK: - Providers - -typealias CredentialsManagerProvider = (_ apiClient: Authentication, _ arguments: [String: Any]) -> CredentialsManager -typealias CredentialsManagerMethodHandlerProvider = (_ method: CredentialsManagerHandler.Method, - _ credentialsManager: CredentialsManager) -> MethodHandler - -// MARK: - Credentials Manager Handler - -public class CredentialsManagerHandler: NSObject, FlutterPlugin { - enum Method: String, CaseIterable { - case save = "credentialsManager#saveCredentials" - case hasValid = "credentialsManager#hasValidCredentials" - case get = "credentialsManager#getCredentials" - case renew = "credentialsManager#renewCredentials" - case clear = "credentialsManager#clearCredentials" - case userInfo = "credentialsManager#user" - case sso = "credentialsManager#getSSOCredentials" - case apiCredentials = "credentialsManager#getApiCredentials" - case clearApiCredentials = "credentialsManager#clearApiCredentials" - } - - private struct ManagerCacheKey: Equatable { - let accountDomain: String - let accountClientId: String - let storeKey: String - let accessGroup: String? - let useDPoP: Bool - let hasLocalAuth: Bool - } - - private static let channelName = "auth0.com/auth0_flutter/credentials_manager" - private static var credentialsManager: CredentialsManager? - private static var cachedKey: ManagerCacheKey? - - public static func register(with registrar: FlutterPluginRegistrar) { - let handler = CredentialsManagerHandler() - - #if os(iOS) - let channel = FlutterMethodChannel(name: CredentialsManagerHandler.channelName, - binaryMessenger: registrar.messenger()) - #else - let channel = FlutterMethodChannel(name: CredentialsManagerHandler.channelName, - binaryMessenger: registrar.messenger) - #endif - - registrar.addMethodCallDelegate(handler, channel: channel) - } - - func createCredentialManager(_ apiClient: Authentication, _ arguments: [String: Any]) -> CredentialsManager { - if let configuration = arguments["credentialsManagerConfiguration"] as? [String: Any], - let iosConfiguration = configuration["ios"] as? [String: String] { - - let storeKey = iosConfiguration["storeKey"] ?? "credentials" - let accessGroup = iosConfiguration["accessGroup"] - let accessibilityString = iosConfiguration["accessibility"] ?? "afterFirstUnlock" - let accessibility = Accessibility(rawValue: accessibilityString as CFString) - - let storage = SimpleKeychain( - accessGroup: accessGroup, - accessibility: accessibility - ) - return CredentialsManager(authentication: apiClient, storeKey: storeKey, storage: storage) - } else { - return CredentialsManager(authentication: apiClient) - } - } - - var apiClientProvider: AuthAPIClientProvider = { account, userAgent, arguments in - let useDPoP = arguments["useDPoP"] as? Bool ?? false - var client = Auth0.authentication(clientId: account.clientId, domain: account.domain) - client.using(inLibrary: userAgent.name, version: userAgent.version) - return useDPoP ? client.useDPoP() : client - } - - - lazy var credentialsManagerProvider: CredentialsManagerProvider = { apiClient, arguments in - - let configuration = arguments["credentialsManagerConfiguration"] as? [String: Any] - let iosConfiguration = configuration?["ios"] as? [String: String] - let storeKey = iosConfiguration?["storeKey"] ?? "credentials" - let accessGroup = iosConfiguration?["accessGroup"] - let useDPoP = arguments["useDPoP"] as? Bool ?? false - let hasLocalAuth = arguments[LocalAuthentication.key] != nil - - guard let accountDictionary = arguments[Account.key] as? [String: String], - let account = Account(from: accountDictionary) else { - return self.createCredentialManager(apiClient, arguments) - } - - let currentKey = ManagerCacheKey( - accountDomain: account.domain, - accountClientId: account.clientId, - storeKey: storeKey, - accessGroup: accessGroup, - useDPoP: useDPoP, - hasLocalAuth: hasLocalAuth - ) - - var instance: CredentialsManager - if let cachedKey = CredentialsManagerHandler.cachedKey, - cachedKey == currentKey, - let cachedManager = CredentialsManagerHandler.credentialsManager { - instance = cachedManager - } else { - instance = self.createCredentialManager(apiClient, arguments) - - CredentialsManagerHandler.credentialsManager = instance - CredentialsManagerHandler.cachedKey = currentKey - } - - if let localAuthenticationDictionary = arguments[LocalAuthentication.key] as? [String: String?] { - let localAuthentication = LocalAuthentication(from: localAuthenticationDictionary) - instance.enableBiometrics(withTitle: localAuthentication.title, - cancelTitle: localAuthentication.cancelTitle, - fallbackTitle: localAuthentication.fallbackTitle) - } - - return instance - } - - var methodHandlerProvider: CredentialsManagerMethodHandlerProvider = { method, credentialsManager in - switch method { - case .save: return CredentialsManagerSaveMethodHandler(credentialsManager: credentialsManager) - case .hasValid: return CredentialsManagerHasValidMethodHandler(credentialsManager: credentialsManager) - case .get: return CredentialsManagerGetMethodHandler(credentialsManager: credentialsManager) - case .clear: return CredentialsManagerClearMethodHandler(credentialsManager: credentialsManager) - case .userInfo: return CredentialsManagerUserInfoMethodHandler(credentialsManager: credentialsManager) - case .renew: return CredentialsManagerRenewMethodHandler(credentialsManager: credentialsManager) - case .sso: return SSOCredentialsMethodHandler(credentialsManager: credentialsManager) - case .apiCredentials: return ApiCredentialsMethodHandler(credentialsManager: credentialsManager) - case .clearApiCredentials: return ClearApiCredentialsMethodHandler(credentialsManager: credentialsManager) - } - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - guard let arguments = call.arguments as? [String: Any] else { - return result(FlutterError(from: .argumentsMissing)) - } - guard let accountDictionary = arguments[Account.key] as? [String: String], - let account = Account(from: accountDictionary) else { - return result(FlutterError(from: .accountMissing)) - } - guard let userAgentDictionary = arguments[UserAgent.key] as? [String: String], - let userAgent = UserAgent(from: userAgentDictionary) else { - return result(FlutterError(from: .userAgentMissing)) - } - guard let method = Method(rawValue: call.method) else { - return result(FlutterMethodNotImplemented) - } - - let apiClient = apiClientProvider(account, userAgent, arguments) - let credentialsManager = credentialsManagerProvider(apiClient, arguments) - let methodHandler = methodHandlerProvider(method, credentialsManager) - methodHandler.handle(with: arguments, callback: result) - } - -} diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerHandler.swift new file mode 120000 index 000000000..c65736607 --- /dev/null +++ b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift deleted file mode 100644 index bf307d784..000000000 --- a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift +++ /dev/null @@ -1,24 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct CredentialsManagerHasValidMethodHandler: MethodHandler { - enum Argument: String { - case minTtl - } - - let credentialsManager: CredentialsManager - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let minTTL = arguments[Argument.minTtl] as? Int else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.minTtl.rawValue))) - } - - // So it behaves the same as the Credentials Manager from Auth0.Android - callback(self.credentialsManager.canRenew() || self.credentialsManager.hasValid(minTTL: minTTL)) - } -} diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift new file mode 120000 index 000000000..95028bf96 --- /dev/null +++ b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerModels.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerModels.swift deleted file mode 100644 index 390b11cb1..000000000 --- a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerModels.swift +++ /dev/null @@ -1,19 +0,0 @@ -enum LocalAuthenticationProperty: String, CaseIterable { - case title - case cancelTitle - case fallbackTitle -} - -struct LocalAuthentication { - let title: String - let cancelTitle: String? - let fallbackTitle: String? - - static let key = "localAuthentication" - - init(from dictionary: [String: String?]) { - self.title = dictionary[LocalAuthenticationProperty.title] as? String ?? "Please authenticate to continue" - self.cancelTitle = dictionary[LocalAuthenticationProperty.cancelTitle] as? String - self.fallbackTitle = dictionary[LocalAuthenticationProperty.fallbackTitle] as? String - } -} diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerModels.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerModels.swift new file mode 120000 index 000000000..23323420b --- /dev/null +++ b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerModels.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerModels.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift deleted file mode 100644 index d0caced3d..000000000 --- a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift +++ /dev/null @@ -1,31 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct CredentialsManagerRenewMethodHandler: MethodHandler { - - enum Argument: String { - case parameters - } - - let credentialsManager: CredentialsManager - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - - guard let parameters = arguments[Argument.parameters] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - - self.credentialsManager.renew(parameters: parameters) { - switch $0 { - case let .success(credentials): callback(result(from: credentials)) - case let .failure(error): callback(FlutterError(from: error)) - } - } - } - -} diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift new file mode 120000 index 000000000..25de6d630 --- /dev/null +++ b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerRenewMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift deleted file mode 100644 index 723a0d072..000000000 --- a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift +++ /dev/null @@ -1,24 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct CredentialsManagerSaveMethodHandler: MethodHandler { - enum Argument: String { - case credentials - } - - let credentialsManager: CredentialsManager - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let credentialsDictionary = arguments[Argument.credentials] as? [String: Any], - let credentials = Credentials(from: credentialsDictionary) else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.credentials.rawValue))) - } - - callback(self.credentialsManager.store(credentials: credentials)) - } -} diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift new file mode 120000 index 000000000..c9907cfa5 --- /dev/null +++ b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerSaveMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift deleted file mode 100644 index f09591825..000000000 --- a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift +++ /dev/null @@ -1,20 +0,0 @@ - -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct CredentialsManagerUserInfoMethodHandler: MethodHandler { - let credentialsManager: CredentialsManager - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - if let user = credentialsManager.user { - callback(user.asDictionary()) - } else { - callback(nil) - } - } -} diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift new file mode 120000 index 000000000..7b64c4ed3 --- /dev/null +++ b/auth0_flutter/darwin/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift deleted file mode 100644 index 8e6457183..000000000 --- a/auth0_flutter/darwin/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct SSOCredentialsMethodHandler: MethodHandler { - - enum Argument: String { - case parameters - case headers - } - - let credentialsManager: CredentialsManager - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let parameters = arguments[Argument.parameters] as? [String: String] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - guard let headers = arguments[Argument.headers] as? [String: String] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.headers.rawValue))) - } - - self.credentialsManager.ssoCredentials(parameters: parameters, headers: headers) { - switch $0 { - case let .success(ssoCredentials): - var response: [String: Any] = [ - "sessionTransferToken": ssoCredentials.sessionTransferToken, - "tokenType": ssoCredentials.issuedTokenType, - "expiresIn": Int(ssoCredentials.expiresIn.timeIntervalSinceNow) - ] - response["idToken"] = ssoCredentials.idToken - if let refreshToken = ssoCredentials.refreshToken { - response["refreshToken"] = refreshToken - } - callback(response) - case let .failure(error): callback(FlutterError(from: error)) - } - } - } - -} diff --git a/auth0_flutter/darwin/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift b/auth0_flutter/darwin/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift new file mode 120000 index 000000000..3f5e526fd --- /dev/null +++ b/auth0_flutter/darwin/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/CredentialsManager/SSOCredentialsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/DPoP/DPoPClearKeyMethodHandler.swift b/auth0_flutter/darwin/Classes/DPoP/DPoPClearKeyMethodHandler.swift deleted file mode 100644 index 88091de20..000000000 --- a/auth0_flutter/darwin/Classes/DPoP/DPoPClearKeyMethodHandler.swift +++ /dev/null @@ -1,20 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct DPoPClearKeyMethodHandler: MethodHandler { - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - do { - try DPoP.clearKeypair() - callback(nil) - } catch { - callback(FlutterError(code: "CLEAR_DPOP_KEY_ERROR", - message: error.localizedDescription, - details: nil)) - } - } -} diff --git a/auth0_flutter/darwin/Classes/DPoP/DPoPClearKeyMethodHandler.swift b/auth0_flutter/darwin/Classes/DPoP/DPoPClearKeyMethodHandler.swift new file mode 120000 index 000000000..de3ce0014 --- /dev/null +++ b/auth0_flutter/darwin/Classes/DPoP/DPoPClearKeyMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/DPoP/DPoPClearKeyMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/DPoP/DPoPGetHeadersMethodHandler.swift b/auth0_flutter/darwin/Classes/DPoP/DPoPGetHeadersMethodHandler.swift deleted file mode 100644 index 6a796dfc6..000000000 --- a/auth0_flutter/darwin/Classes/DPoP/DPoPGetHeadersMethodHandler.swift +++ /dev/null @@ -1,55 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct DPoPGetHeadersMethodHandler: MethodHandler { - enum Argument: String { - case url - case method - case accessToken - case tokenType - } - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let urlString = arguments[Argument.url] as? String, - let url = URL(string: urlString) else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.url.rawValue))) - } - guard let method = arguments[Argument.method] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.method.rawValue))) - } - guard let accessToken = arguments[Argument.accessToken] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.accessToken.rawValue))) - } - guard let tokenType = arguments[Argument.tokenType] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.tokenType.rawValue))) - } - - let nonce = arguments["nonce"] as? String - - var request = URLRequest(url: url) - request.httpMethod = method - - do { - try DPoP.addHeaders(to: &request, - accessToken: accessToken, - tokenType: tokenType, - nonce: nonce) - - let result: [String: String] = [ - "authorization": request.value(forHTTPHeaderField: "Authorization") ?? "\(tokenType) \(accessToken)", - "dpop": request.value(forHTTPHeaderField: "DPoP") ?? "" - ] - - callback(result) - } catch { - callback(FlutterError(code: "GET_DPOP_HEADERS_ERROR", - message: error.localizedDescription, - details: nil)) - } - } -} diff --git a/auth0_flutter/darwin/Classes/DPoP/DPoPGetHeadersMethodHandler.swift b/auth0_flutter/darwin/Classes/DPoP/DPoPGetHeadersMethodHandler.swift new file mode 120000 index 000000000..d1b7b6b37 --- /dev/null +++ b/auth0_flutter/darwin/Classes/DPoP/DPoPGetHeadersMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/DPoP/DPoPGetHeadersMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/DPoP/DPoPHandler.swift b/auth0_flutter/darwin/Classes/DPoP/DPoPHandler.swift deleted file mode 100644 index b9466cd16..000000000 --- a/auth0_flutter/darwin/Classes/DPoP/DPoPHandler.swift +++ /dev/null @@ -1,50 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - - -public class DPoPHandler: NSObject, FlutterPlugin { - enum Method: String, CaseIterable { - case getDPoPHeaders = "dpop#getDPoPHeaders" - case clearDPoPKey = "dpop#clearDPoPKey" - } - - private static let channelName = "auth0.com/auth0_flutter/dpop" - - public static func register(with registrar: FlutterPluginRegistrar) { - let handler = DPoPHandler() - - #if os(iOS) - let channel = FlutterMethodChannel(name: DPoPHandler.channelName, - binaryMessenger: registrar.messenger()) - #else - let channel = FlutterMethodChannel(name: DPoPHandler.channelName, - binaryMessenger: registrar.messenger) - #endif - - registrar.addMethodCallDelegate(handler, channel: channel) - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - guard let arguments = call.arguments as? [String: Any] else { - return result(FlutterError(from: .argumentsMissing)) - } - guard let method = Method(rawValue: call.method) else { - return result(FlutterMethodNotImplemented) - } - - let methodHandler: MethodHandler - switch method { - case .getDPoPHeaders: - methodHandler = DPoPGetHeadersMethodHandler() - case .clearDPoPKey: - methodHandler = DPoPClearKeyMethodHandler() - } - - methodHandler.handle(with: arguments, callback: result) - } -} diff --git a/auth0_flutter/darwin/Classes/DPoP/DPoPHandler.swift b/auth0_flutter/darwin/Classes/DPoP/DPoPHandler.swift new file mode 120000 index 000000000..47840c2cc --- /dev/null +++ b/auth0_flutter/darwin/Classes/DPoP/DPoPHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/DPoP/DPoPHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/Extensions.swift b/auth0_flutter/darwin/Classes/Extensions.swift deleted file mode 100644 index c5c7b203e..000000000 --- a/auth0_flutter/darwin/Classes/Extensions.swift +++ /dev/null @@ -1,145 +0,0 @@ -import Auth0 -import JWTDecode - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -extension Array where Element == String { - var asSpaceSeparatedString: String { - return self.joined(separator: " ") - } -} - -extension Dictionary where Key == String { - subscript(_ key: K) -> Value? where K.RawValue == String { - get { - return self[key.rawValue] - } - set { - self[key.rawValue] = newValue - } - } -} - -extension Date { - static var iso8601Formatter: ISO8601DateFormatter { - let formatter = ISO8601DateFormatter() - formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] - return formatter - } - - var asISO8601String: String { - return Date.iso8601Formatter.string(from: self) - } -} - -extension FlutterError { - convenience init(from handlerError: HandlerError) { - self.init(code: handlerError.code, message: handlerError.message, details: nil) - } -} - -extension Auth0Error { - var details: [String: Any] { - guard let cause = cause else { return [:] } - return ["cause": String(describing: cause)] - } -} - -extension Auth0APIError { - var details: [String: Any] { - var info = self.info - info.removeValue(forKey: "statusCode") - if let cause = cause { - info["cause"] = String(describing: cause) - } - return info - } -} - -extension Credentials { - convenience init?(from dictionary: [String: Any]) { - guard let accessToken = dictionary[CredentialsProperty.accessToken] as? String, - let idToken = dictionary[CredentialsProperty.idToken] as? String, - let expiresAt = dictionary[CredentialsProperty.expiresAt] as? String, - let expiresIn = Date.iso8601Formatter.date(from: expiresAt), - let scopes = dictionary[CredentialsProperty.scopes] as? [String], - let tokenType = dictionary[CredentialsProperty.tokenType] as? String else { - return nil - } - - self.init(accessToken: accessToken, - tokenType: tokenType, - idToken: idToken, - refreshToken: dictionary[CredentialsProperty.refreshToken] as? String, - expiresIn: expiresIn, - scope: scopes.isEmpty ? nil : scopes.asSpaceSeparatedString, - recoveryCode: nil) - } - - func asDictionary() throws -> [String: Any] { - let jwt = try decode(jwt: idToken) - var data: [String: Any] = [ - CredentialsProperty.accessToken.rawValue: accessToken, - CredentialsProperty.idToken.rawValue: idToken, - CredentialsProperty.expiresAt.rawValue: expiresIn.asISO8601String, - CredentialsProperty.scopes.rawValue: scope?.split(separator: " ").map(String.init) ?? [], - CredentialsProperty.userProfile.rawValue: UserInfo(json: jwt.body)?.asDictionary() ?? [:], - CredentialsProperty.tokenType.rawValue: tokenType - ] - data[CredentialsProperty.refreshToken] = refreshToken - return data - } -} - -extension APICredentials { - func asDictionary() -> [String: Any] { - return [ - "accessToken": accessToken, - "tokenType": tokenType, - "expiresAt": expiresIn.asISO8601String, - "scopes": scope.split(separator: " ").map(String.init) - ] - } -} - -extension UserInfo { - func asDictionary() -> [String: Any] { - let claimsToFilter = ["aud", - "iss", - "iat", - "exp", - "nbf", - "nonce", - "azp", - "auth_time", - "s_hash", - "at_hash", - "c_hash"] - var data: [String: Any] = [UserInfoProperty.sub.rawValue: sub] - data[UserInfoProperty.name] = name - data[UserInfoProperty.givenName] = givenName - data[UserInfoProperty.familyName] = familyName - data[UserInfoProperty.middleName] = middleName - data[UserInfoProperty.nickname] = nickname - data[UserInfoProperty.preferredUsername] = preferredUsername - data[UserInfoProperty.profile] = profile?.absoluteString - data[UserInfoProperty.picture] = picture?.absoluteString - data[UserInfoProperty.website] = website?.absoluteString - data[UserInfoProperty.email] = email - data[UserInfoProperty.emailVerified] = emailVerified - data[UserInfoProperty.gender] = gender - data[UserInfoProperty.birthdate] = birthdate - data[UserInfoProperty.zoneinfo] = zoneinfo?.identifier - data[UserInfoProperty.locale] = locale?.identifier - data[UserInfoProperty.phoneNumber] = phoneNumber - data[UserInfoProperty.phoneNumberVerified] = phoneNumberVerified - data[UserInfoProperty.address] = address - data[UserInfoProperty.updatedAt] = updatedAt?.asISO8601String - data[UserInfoProperty.customClaims] = customClaims?.filter { !claimsToFilter.contains($0.key) } - return data - } -} diff --git a/auth0_flutter/darwin/Classes/Extensions.swift b/auth0_flutter/darwin/Classes/Extensions.swift new file mode 120000 index 000000000..8eeb92824 --- /dev/null +++ b/auth0_flutter/darwin/Classes/Extensions.swift @@ -0,0 +1 @@ +../../../auth0_flutter/Sources/auth0_flutter/Extensions.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/HandlerError.swift b/auth0_flutter/darwin/Classes/HandlerError.swift deleted file mode 100644 index 0479a5caa..000000000 --- a/auth0_flutter/darwin/Classes/HandlerError.swift +++ /dev/null @@ -1,28 +0,0 @@ -enum HandlerError { - case argumentsMissing - case accountMissing - case userAgentMissing - case requiredArgumentMissing(String) - case idTokenDecodingFailed - - var code: String { - switch self { - case .argumentsMissing: return "SWIFT_ARGUMENTS_MISSING" - case .accountMissing: return "SWIFT_ACCOUNT_MISSING" - case .userAgentMissing: return "SWIFT_USER_AGENT_MISSING" - case .requiredArgumentMissing: return "SWIFT_REQUIRED_ARGUMENT_MISSING" - case .idTokenDecodingFailed: return "SWIFT_ID_TOKEN_DECODING_FAILED" - } - } - - var message: String { - switch self { - case .argumentsMissing: return "The arguments dictionary is missing or has the wrong type." - case .accountMissing: return "The account dictionary is missing or incomplete, or has the wrong type." - case .userAgentMissing: return "The userAgent dictionary is missing or incomplete, or has the wrong type." - case let .requiredArgumentMissing(argument): - return "The required argument '\(argument)' is missing or has the wrong type." - case .idTokenDecodingFailed: return "Unable to decode the ID Token." - } - } -} diff --git a/auth0_flutter/darwin/Classes/HandlerError.swift b/auth0_flutter/darwin/Classes/HandlerError.swift new file mode 120000 index 000000000..40c3d8aa2 --- /dev/null +++ b/auth0_flutter/darwin/Classes/HandlerError.swift @@ -0,0 +1 @@ +../../../auth0_flutter/Sources/auth0_flutter/HandlerError.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MethodHandler.swift b/auth0_flutter/darwin/Classes/MethodHandler.swift deleted file mode 100644 index 8743c6b5b..000000000 --- a/auth0_flutter/darwin/Classes/MethodHandler.swift +++ /dev/null @@ -1,29 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -protocol MethodHandler { - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) -} - -extension MethodHandler { - func result(from credentials: Credentials) -> Any? { - do { - return try credentials.asDictionary() - } catch { - return FlutterError(from: .idTokenDecodingFailed) - } - } -} - -struct UnsupportedMethodHandler: MethodHandler { - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - callback(FlutterError(code: "UNSUPPORTED_PLATFORM", - message: "This method is not supported on this platform version.", - details: nil)) - } -} diff --git a/auth0_flutter/darwin/Classes/MethodHandler.swift b/auth0_flutter/darwin/Classes/MethodHandler.swift new file mode 120000 index 000000000..1c9558b6d --- /dev/null +++ b/auth0_flutter/darwin/Classes/MethodHandler.swift @@ -0,0 +1 @@ +../../../auth0_flutter/Sources/auth0_flutter/MethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/Models.swift b/auth0_flutter/darwin/Classes/Models.swift deleted file mode 100644 index 900c36ca8..000000000 --- a/auth0_flutter/darwin/Classes/Models.swift +++ /dev/null @@ -1,42 +0,0 @@ -enum AccountProperty: String { - case clientId - case domain -} - -struct Account { - let clientId: String - let domain: String - - static let key = "_account" - - init?(from dictionary: [String: String]) { - guard let clientId = dictionary[AccountProperty.clientId], - let domain = dictionary[AccountProperty.domain] else { - return nil - } - - self.clientId = clientId - self.domain = domain - } -} - -enum UserAgentProperty: String { - case name - case version -} - -struct UserAgent { - let name: String - let version: String - - static let key = "_userAgent" - - init?(from dictionary: [String: String]) { - guard let name = dictionary[UserAgentProperty.name], let version = dictionary[UserAgentProperty.version] else { - return nil - } - - self.name = name - self.version = version - } -} diff --git a/auth0_flutter/darwin/Classes/Models.swift b/auth0_flutter/darwin/Classes/Models.swift new file mode 120000 index 000000000..2b4445ca2 --- /dev/null +++ b/auth0_flutter/darwin/Classes/Models.swift @@ -0,0 +1 @@ +../../../auth0_flutter/Sources/auth0_flutter/Models.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift deleted file mode 100644 index bb41c2ef0..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift +++ /dev/null @@ -1,40 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct MyAccountConfirmEnrollmentMethodHandler: MethodHandler { - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let id = arguments["id"] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing("id"))) - } - guard let authSession = arguments["authSession"] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing("authSession"))) - } - - guard let factorType = arguments["factorType"] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing("factorType"))) - } - - let request: Request - if factorType == "push-notification" { - request = client.authenticationMethods.confirmPushNotificationEnrollment(id: id, authSession: authSession) - } else { - request = client.authenticationMethods.confirmRecoveryCodeEnrollment(id: id, authSession: authSession) - } - - request.start { - switch $0 { - case let .success(method): - callback(method.asDictionary()) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift new file mode 120000 index 000000000..162bc31d9 --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift deleted file mode 100644 index b00656d0e..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift +++ /dev/null @@ -1,29 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct MyAccountDeleteAuthMethodMethodHandler: MethodHandler { - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let id = arguments["id"] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing("id"))) - } - - client - .authenticationMethods - .deleteAuthenticationMethod(by: id) - .start { - switch $0 { - case .success: - callback(nil) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift new file mode 120000 index 000000000..830c4a588 --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift deleted file mode 100644 index 54768136f..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift +++ /dev/null @@ -1,29 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct MyAccountEnrollEmailMethodHandler: MethodHandler { - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let email = arguments["email"] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing("email"))) - } - - client - .authenticationMethods - .enrollEmail(emailAddress: email) - .start { - switch $0 { - case let .success(challenge): - callback(challenge.asDictionary()) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift new file mode 120000 index 000000000..78d697651 --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift deleted file mode 100644 index 12f2c3979..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift +++ /dev/null @@ -1,39 +0,0 @@ -#if PASSKEYS_PLATFORM -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -/// Requests a passkey enrollment challenge from the My Account API. This is the -/// first part of the enrollment flow; the app then presents the OS passkey -/// creation UI and finishes with `myAccount#enrollPasskey`. -@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) -struct MyAccountEnrollPasskeyChallengeMethodHandler: MethodHandler { - enum Argument: String { - case userIdentityId - case connection - } - - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - let userIdentityId = arguments[Argument.userIdentityId.rawValue] as? String - let connection = arguments[Argument.connection.rawValue] as? String - - client - .authenticationMethods - .passkeyEnrollmentChallenge(userIdentityId: userIdentityId, connection: connection) - .start { - switch $0 { - case let .success(challenge): - callback(challenge.asDictionary()) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} -#endif diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift new file mode 120000 index 000000000..6ede04e31 --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift deleted file mode 100644 index 8a908157a..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift +++ /dev/null @@ -1,131 +0,0 @@ -#if PASSKEYS_PLATFORM -import Auth0 -import AuthenticationServices - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -/// A ``NewPasskey`` reconstructed from a credential map supplied by the app -/// (for example, from `ASAuthorizationController`). -@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) -private struct ReconstructedNewPasskey: NewPasskey { - let credentialID: Data - let attachment: ASAuthorizationPublicKeyCredentialAttachment - let rawClientDataJSON: Data - let rawAttestationObject: Data? -} - -/// Enrolls an app-supplied passkey credential (a signup attestation) against a -/// previously obtained enrollment challenge via the My Account API. This is the -/// last part of the enrollment flow. This handler does not present any UI. -@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) -struct MyAccountEnrollPasskeyMethodHandler: MethodHandler { - enum Argument: String { - case challenge - case credential - } - - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let challengeMap = arguments[Argument.challenge.rawValue] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.challenge.rawValue))) - } - guard let credentialMap = arguments[Argument.credential.rawValue] as? [String: Any] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.credential.rawValue))) - } - - guard let challenge = Self.reconstructChallenge(from: challengeMap) else { - return callback(FlutterError(code: "PASSKEY_ERROR", - message: "Failed to reconstruct enrollment challenge", - details: nil)) - } - guard let passkey = Self.reconstructPasskey(from: credentialMap) else { - return callback(FlutterError(code: "PASSKEY_ERROR", - message: "Failed to reconstruct passkey credential", - details: nil)) - } - - client - .authenticationMethods - .enroll(passkey: passkey, challenge: challenge) - .start { - switch $0 { - case let .success(method): - callback(method.asDictionary()) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } - - // MARK: - Reconstruction - - private static func reconstructChallenge( - from challengeMap: [String: Any]) -> PasskeyEnrollmentChallenge? { - guard let authenticationMethodId = challengeMap["authenticationMethodId"] as? String, - let authSession = challengeMap["authSession"] as? String, - let authParamsPublicKey = challengeMap["authParamsPublicKey"] as? [String: Any], - let challengeString = authParamsPublicKey["challenge"] as? String, - let relyingPartyId = authParamsPublicKey["rpId"] as? String, - let userIdString = authParamsPublicKey["userId"] as? String, - let userName = authParamsPublicKey["userName"] as? String else { - return nil - } - - // `PasskeyEnrollmentChallenge`'s memberwise initializer is internal to - // Auth0.swift, so reconstruct it the way the SDK itself does: decode - // from the WebAuthn JSON with the authentication method id supplied via - // the `locationHeader` decoder userInfo key. - let challengeJson: [String: Any] = [ - "auth_session": authSession, - "authn_params_public_key": [ - "rp": ["id": relyingPartyId], - "user": ["id": userIdString, "name": userName], - "challenge": challengeString - ] - ] - - guard let jsonData = try? JSONSerialization.data(withJSONObject: challengeJson) else { - return nil - } - - let decoder = JSONDecoder() - // Matches Auth0.swift's internal `CodingUserInfoKey.locationHeaderKey`, - // whose raw value is "locationHeader". The decoder reads the last path - // component as the authentication method id. - if let locationHeaderKey = CodingUserInfoKey(rawValue: "locationHeader") { - decoder.userInfo[locationHeaderKey] = authenticationMethodId - } - return try? decoder.decode(PasskeyEnrollmentChallenge.self, from: jsonData) - } - - private static func reconstructPasskey( - from credentialMap: [String: Any]) -> NewPasskey? { - guard let credentialIdString = credentialMap["rawId"] as? String - ?? credentialMap["id"] as? String, - let credentialID = Data.fromBase64URLEncoded(credentialIdString), - let response = credentialMap["response"] as? [String: Any], - let clientDataString = response["clientDataJSON"] as? String, - let rawClientDataJSON = Data.fromBase64URLEncoded(clientDataString), - let attestationString = response["attestationObject"] as? String, - let rawAttestationObject = Data.fromBase64URLEncoded(attestationString) else { - return nil - } - - let attachment: ASAuthorizationPublicKeyCredentialAttachment = - (credentialMap["authenticatorAttachment"] as? String) == "crossPlatform" - ? .crossPlatform : .platform - - return ReconstructedNewPasskey( - credentialID: credentialID, - attachment: attachment, - rawClientDataJSON: rawClientDataJSON, - rawAttestationObject: rawAttestationObject - ) - } -} -#endif diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift new file mode 120000 index 000000000..c262e8b1c --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift deleted file mode 100644 index 815382645..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift +++ /dev/null @@ -1,34 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct MyAccountEnrollPhoneMethodHandler: MethodHandler { - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let phoneNumber = arguments["phoneNumber"] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing("phoneNumber"))) - } - guard let typeString = arguments["type"] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing("type"))) - } - - let preferredMethod: PreferredAuthenticationMethod = typeString == "voice" ? .voice : .sms - - client - .authenticationMethods - .enrollPhone(phoneNumber: phoneNumber, preferredAuthenticationMethod: preferredMethod) - .start { - switch $0 { - case let .success(challenge): - callback(challenge.asDictionary()) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift new file mode 120000 index 000000000..ef3179716 --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift deleted file mode 100644 index 0318e7814..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift +++ /dev/null @@ -1,25 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct MyAccountEnrollPushMethodHandler: MethodHandler { - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - client - .authenticationMethods - .enrollPushNotification() - .start { - switch $0 { - case let .success(challenge): - callback(challenge.asDictionary()) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift new file mode 120000 index 000000000..d7f8de56a --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift deleted file mode 100644 index 0bbaefe50..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift +++ /dev/null @@ -1,25 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct MyAccountEnrollRecoveryCodeMethodHandler: MethodHandler { - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - client - .authenticationMethods - .enrollRecoveryCode() - .start { - switch $0 { - case let .success(challenge): - callback(challenge.asDictionary()) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift new file mode 120000 index 000000000..7246ac88a --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift deleted file mode 100644 index 307a3b31c..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift +++ /dev/null @@ -1,25 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct MyAccountEnrollTotpMethodHandler: MethodHandler { - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - client - .authenticationMethods - .enrollTOTP() - .start { - switch $0 { - case let .success(challenge): - callback(challenge.asDictionary()) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift new file mode 120000 index 000000000..c627dc0d4 --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountExtensions.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountExtensions.swift deleted file mode 100644 index 0f73e0391..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountExtensions.swift +++ /dev/null @@ -1,151 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -extension FlutterError { - convenience init(from error: MyAccountError) { - let details: [String: Any] = [ - "_statusCode": error.statusCode, - "_title": error.title, - "_detail": error.detail, - "_errorFlags": [ - "isNetworkError": error.isNetworkError - ] - ] - self.init(code: error.code, - message: error.detail.isEmpty ? error.title : error.detail, - details: details) - } -} - -extension AuthenticationMethod { - func asDictionary() -> [String: Any?] { - return [ - "id": id, - "type": type, - "name": name, - "phone_number": phoneNumber, - "email": nil, - "totp_secret": nil, - "totp_uri": nil, - "preferred_authentication_method": preferredAuthenticationMethod, - "created_at": createdAt, - "last_auth_at": nil, - "confirmed": confirmed, - "usage": usage - ] - } -} - -extension PhoneEnrollmentChallenge { - func asDictionary() -> [String: Any?] { - return [ - "id": authenticationId, - "auth_session": authenticationSession, - "totp_secret": nil, - "totp_uri": nil, - "barcode_uri": nil, - "recovery_code": nil - ] - } -} - -extension EmailEnrollmentChallenge { - func asDictionary() -> [String: Any?] { - return [ - "id": authenticationId, - "auth_session": authenticationSession, - "totp_secret": nil, - "totp_uri": nil, - "barcode_uri": nil, - "recovery_code": nil - ] - } -} - -extension TOTPEnrollmentChallenge { - func asDictionary() -> [String: Any?] { - return [ - "id": authenticationId, - "auth_session": authenticationSession, - "totp_secret": authenticatorManualInputCode, - "totp_uri": authenticatorQRCodeURI, - "barcode_uri": authenticatorQRCodeURI, - "recovery_code": nil - ] - } -} - -extension PushEnrollmentChallenge { - func asDictionary() -> [String: Any?] { - return [ - "id": authenticationId, - "auth_session": authenticationSession, - "totp_secret": nil, - "totp_uri": nil, - "barcode_uri": authenticatorQRCodeURI, - "recovery_code": nil - ] - } -} - -extension RecoveryCodeEnrollmentChallenge { - func asDictionary() -> [String: Any?] { - return [ - "id": authenticationId, - "auth_session": authenticationSession, - "totp_secret": nil, - "totp_uri": nil, - "barcode_uri": nil, - "recovery_code": recoveryCode - ] - } -} - -#if PASSKEYS_PLATFORM -@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) -extension PasskeyEnrollmentChallenge { - func asDictionary() -> [String: Any?] { - // Forward the WebAuthn creation options in the flat shape the app's - // platform-authenticator ceremony consumes, plus the authentication - // method id needed to finish enrollment. - return [ - "authenticationMethodId": authenticationMethodId, - "authSession": authenticationSession, - "authParamsPublicKey": [ - "challenge": challengeData.base64URLEncodedString(), - "rpId": relyingPartyId, - "userId": userId.base64URLEncodedString(), - "userName": userName - ] - ] - } -} - -@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) -extension PasskeyAuthenticationMethod { - func asDictionary() -> [String: Any?] { - let createdAtFormatter = ISO8601DateFormatter() - createdAtFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] - - return [ - "id": id, - "type": type, - "identity_user_id": userIdentityId, - "user_agent": userAgent, - "key_id": credential.id, - "public_key": credential.publicKey.base64EncodedString(), - "user_handle": credential.userHandle.base64URLEncodedString(), - "credential_device_type": credential.deviceType.rawValue, - "credential_backed_up": credential.isBackedUp, - "aaguid": aaguid, - "relying_party_id": relyingPartyIdentifier, - "created_at": createdAtFormatter.string(from: createdAt) - ] - } -} -#endif diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountExtensions.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountExtensions.swift new file mode 120000 index 000000000..99816f7f2 --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountExtensions.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift deleted file mode 100644 index ac819216f..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift +++ /dev/null @@ -1,29 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct MyAccountGetAuthMethodMethodHandler: MethodHandler { - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let id = arguments["id"] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing("id"))) - } - - client - .authenticationMethods - .getAuthenticationMethod(by: id) - .start { - switch $0 { - case let .success(method): - callback(method.asDictionary()) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift new file mode 120000 index 000000000..ef8e70f2b --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift deleted file mode 100644 index ccbd6dc55..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift +++ /dev/null @@ -1,28 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct MyAccountGetAuthMethodsMethodHandler: MethodHandler { - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - let type = (arguments["type"] as? String) - .flatMap(AuthenticationMethodType.init(rawValue:)) - - client - .authenticationMethods - .getAuthenticationMethods(type: type) - .start { - switch $0 { - case let .success(methods): - callback(methods.map { $0.asDictionary() }) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift new file mode 120000 index 000000000..87165e2c3 --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift deleted file mode 100644 index 8f35c6ef5..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift +++ /dev/null @@ -1,25 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct MyAccountGetFactorsMethodHandler: MethodHandler { - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - client - .authenticationMethods - .getFactors() - .start { - switch $0 { - case let .success(factors): - callback(factors.map { ["type": $0.type, "usage": $0.usage as Any] }) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift new file mode 120000 index 000000000..5c78ae20a --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountHandler.swift deleted file mode 100644 index 3371614c0..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountHandler.swift +++ /dev/null @@ -1,111 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -typealias MyAccountClientProvider = (_ account: Account, _ userAgent: UserAgent, _ accessToken: String, _ useDPoP: Bool) -> MyAccount -typealias MyAccountMethodHandlerProvider = (_ method: MyAccountHandler.Method, _ client: MyAccount) -> MethodHandler - -public class MyAccountHandler: NSObject, FlutterPlugin { - enum Method: String, CaseIterable { - case getAuthenticationMethods = "myAccount#getAuthenticationMethods" - case getAuthenticationMethod = "myAccount#getAuthenticationMethod" - case deleteAuthenticationMethod = "myAccount#deleteAuthenticationMethod" - case getFactors = "myAccount#getFactors" - case enrollPasskeyChallenge = "myAccount#enrollPasskeyChallenge" - case enrollPasskey = "myAccount#enrollPasskey" - case enrollPhone = "myAccount#enrollPhone" - case enrollEmail = "myAccount#enrollEmail" - case enrollTotp = "myAccount#enrollTotp" - case enrollPush = "myAccount#enrollPush" - case enrollRecoveryCode = "myAccount#enrollRecoveryCode" - case verifyOtp = "myAccount#verifyOtp" - case confirmEnrollment = "myAccount#confirmEnrollment" - case updateAuthenticationMethod = "myAccount#updateAuthenticationMethod" - } - - private static let channelName = "auth0.com/auth0_flutter/my_account" - - public static func register(with registrar: FlutterPluginRegistrar) { - let handler = MyAccountHandler() - - #if os(iOS) - let channel = FlutterMethodChannel(name: MyAccountHandler.channelName, - binaryMessenger: registrar.messenger()) - #else - let channel = FlutterMethodChannel(name: MyAccountHandler.channelName, - binaryMessenger: registrar.messenger) - #endif - - registrar.addMethodCallDelegate(handler, channel: channel) - } - - var clientProvider: MyAccountClientProvider = { account, userAgent, accessToken, useDPoP in - var client = Auth0.myAccount(token: accessToken, domain: account.domain) - if useDPoP { - client = client.useDPoP() - } - return client - } - - var methodHandlerProvider: MyAccountMethodHandlerProvider = { method, client in - switch method { - case .getAuthenticationMethods: return MyAccountGetAuthMethodsMethodHandler(client: client) - case .getAuthenticationMethod: return MyAccountGetAuthMethodMethodHandler(client: client) - case .deleteAuthenticationMethod: return MyAccountDeleteAuthMethodMethodHandler(client: client) - case .getFactors: return MyAccountGetFactorsMethodHandler(client: client) - #if PASSKEYS_PLATFORM - case .enrollPasskeyChallenge: - if #available(iOS 16.6, macOS 13.5, visionOS 1.0, *) { - return MyAccountEnrollPasskeyChallengeMethodHandler(client: client) - } - return UnsupportedMethodHandler() - case .enrollPasskey: - if #available(iOS 16.6, macOS 13.5, visionOS 1.0, *) { - return MyAccountEnrollPasskeyMethodHandler(client: client) - } - return UnsupportedMethodHandler() - #else - case .enrollPasskeyChallenge, .enrollPasskey: - return UnsupportedMethodHandler() - #endif - case .enrollPhone: return MyAccountEnrollPhoneMethodHandler(client: client) - case .enrollEmail: return MyAccountEnrollEmailMethodHandler(client: client) - case .enrollTotp: return MyAccountEnrollTotpMethodHandler(client: client) - case .enrollPush: return MyAccountEnrollPushMethodHandler(client: client) - case .enrollRecoveryCode: return MyAccountEnrollRecoveryCodeMethodHandler(client: client) - case .verifyOtp: return MyAccountVerifyOtpMethodHandler(client: client) - case .confirmEnrollment: return MyAccountConfirmEnrollmentMethodHandler(client: client) - case .updateAuthenticationMethod: return MyAccountUpdateAuthMethodMethodHandler(client: client) - } - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - guard let arguments = call.arguments as? [String: Any] else { - return result(FlutterError(from: .argumentsMissing)) - } - guard let accountDictionary = arguments[Account.key] as? [String: String], - let account = Account(from: accountDictionary) else { - return result(FlutterError(from: .accountMissing)) - } - guard let userAgentDictionary = arguments[UserAgent.key] as? [String: String], - let userAgent = UserAgent(from: userAgentDictionary) else { - return result(FlutterError(from: .userAgentMissing)) - } - guard let method = Method(rawValue: call.method) else { - return result(FlutterMethodNotImplemented) - } - guard let accessToken = arguments["accessToken"] as? String else { - return result(FlutterError(from: .requiredArgumentMissing("accessToken"))) - } - - let useDPoP = arguments["useDPoP"] as? Bool ?? false - let client = clientProvider(account, userAgent, accessToken, useDPoP) - let methodHandler = methodHandlerProvider(method, client) - - methodHandler.handle(with: arguments, callback: result) - } -} diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountHandler.swift new file mode 120000 index 000000000..ddba6e76d --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift deleted file mode 100644 index 64389b8a8..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift +++ /dev/null @@ -1,36 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct MyAccountUpdateAuthMethodMethodHandler: MethodHandler { - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let id = arguments["id"] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing("id"))) - } - - let name = arguments["name"] as? String - let preferredAuthenticationMethod = - (arguments["preferredAuthenticationMethod"] as? String) - .flatMap(PreferredAuthenticationMethod.init(rawValue:)) - - client - .authenticationMethods - .updateAuthenticationMethod(by: id, - name: name, - preferredAuthenticationMethod: preferredAuthenticationMethod) - .start { - switch $0 { - case let .success(method): - callback(method.asDictionary()) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift new file mode 120000 index 000000000..68a38c913 --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift deleted file mode 100644 index 69ccbcf0c..000000000 --- a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift +++ /dev/null @@ -1,46 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct MyAccountVerifyOtpMethodHandler: MethodHandler { - let client: MyAccount - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let id = arguments["id"] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing("id"))) - } - guard let authSession = arguments["authSession"] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing("authSession"))) - } - guard let otp = arguments["otp"] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing("otp"))) - } - - guard let factorType = arguments["factorType"] as? String else { - return callback(FlutterError(from: .requiredArgumentMissing("factorType"))) - } - - let request: Request - switch factorType { - case "email": - request = client.authenticationMethods.confirmEmailEnrollment(id: id, authSession: authSession, otpCode: otp) - case "totp": - request = client.authenticationMethods.confirmTOTPEnrollment(id: id, authSession: authSession, otpCode: otp) - default: - request = client.authenticationMethods.confirmPhoneEnrollment(id: id, authSession: authSession, otpCode: otp) - } - - request.start { - switch $0 { - case let .success(method): - callback(method.asDictionary()) - case let .failure(error): - callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift new file mode 120000 index 000000000..91ba5a60b --- /dev/null +++ b/auth0_flutter/darwin/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/Properties.swift b/auth0_flutter/darwin/Classes/Properties.swift deleted file mode 100644 index a72a3658b..000000000 --- a/auth0_flutter/darwin/Classes/Properties.swift +++ /dev/null @@ -1,41 +0,0 @@ -enum CredentialsProperty: String, CaseIterable { - case accessToken - case idToken - case userProfile - case refreshToken - case expiresAt - case scopes - case tokenType -} - -enum SSOCredentialsProperty: String, CaseIterable { - case sessionTransferToken - case tokenType - case expiresIn - case idToken - case refreshToken -} - -enum UserInfoProperty: String, CaseIterable { - case sub - case name - case givenName = "given_name" - case familyName = "family_name" - case middleName = "middle_name" - case nickname - case preferredUsername = "preferred_username" - case profile - case picture - case website - case email - case emailVerified = "email_verified" - case gender - case birthdate - case zoneinfo - case locale - case phoneNumber = "phone_number" - case phoneNumberVerified = "phone_number_verified" - case address - case updatedAt = "updated_at" - case customClaims = "custom_claims" -} diff --git a/auth0_flutter/darwin/Classes/Properties.swift b/auth0_flutter/darwin/Classes/Properties.swift new file mode 120000 index 000000000..ca58ded28 --- /dev/null +++ b/auth0_flutter/darwin/Classes/Properties.swift @@ -0,0 +1 @@ +../../../auth0_flutter/Sources/auth0_flutter/Properties.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/WebAuth/WebAuthExtensions.swift b/auth0_flutter/darwin/Classes/WebAuth/WebAuthExtensions.swift deleted file mode 100644 index 6f706b998..000000000 --- a/auth0_flutter/darwin/Classes/WebAuth/WebAuthExtensions.swift +++ /dev/null @@ -1,29 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -extension FlutterError { - convenience init(from webAuthError: WebAuthError) { - var code: String - switch webAuthError { - case WebAuthError.noBundleIdentifier: code = "NO_BUNDLE_IDENTIFIER" - case WebAuthError.invalidInvitationURL: code = "INVALID_INVITATION_URL" - case WebAuthError.userCancelled: code = "USER_CANCELLED" - case WebAuthError.noAuthorizationCode: code = "NO_AUTHORIZATION_CODE" - case WebAuthError.pkceNotAllowed: code = "PKCE_NOT_ALLOWED" - case WebAuthError.idTokenValidationFailed: code = "ID_TOKEN_VALIDATION_FAILED" - case WebAuthError.transactionActiveAlready: code = "TRANSACTION_ACTIVE_ALREADY" - case WebAuthError.other: code = "OTHER" - default: code = "UNKNOWN" - } - var details = webAuthError.details - let isRetryable = (webAuthError.cause as? Auth0APIError)?.isRetryable ?? false - details["_isRetryable"] = isRetryable - self.init(code: code, message: String(describing: webAuthError), details: details) - } -} - diff --git a/auth0_flutter/darwin/Classes/WebAuth/WebAuthExtensions.swift b/auth0_flutter/darwin/Classes/WebAuth/WebAuthExtensions.swift new file mode 120000 index 000000000..1e1f4b108 --- /dev/null +++ b/auth0_flutter/darwin/Classes/WebAuth/WebAuthExtensions.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/WebAuth/WebAuthHandler.swift b/auth0_flutter/darwin/Classes/WebAuth/WebAuthHandler.swift deleted file mode 100644 index 208ffd48e..000000000 --- a/auth0_flutter/darwin/Classes/WebAuth/WebAuthHandler.swift +++ /dev/null @@ -1,78 +0,0 @@ -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -// MARK: - Providers - -typealias WebAuthClientProvider = (_ account: Account, _ userAgent: UserAgent) -> WebAuth -typealias WebAuthMethodHandlerProvider = (_ method: WebAuthHandler.Method, _ client: WebAuth) -> MethodHandler - -// MARK: - Web Auth Handler - -public class WebAuthHandler: NSObject, FlutterPlugin { - enum Method: String, CaseIterable { - case login = "webAuth#login" - case logout = "webAuth#logout" - } - - private static let channelName = "auth0.com/auth0_flutter/web_auth" - - public static func register(with registrar: FlutterPluginRegistrar) { - let handler = WebAuthHandler() - - #if os(iOS) - let channel = FlutterMethodChannel(name: WebAuthHandler.channelName, - binaryMessenger: registrar.messenger()) - #else - let channel = FlutterMethodChannel(name: WebAuthHandler.channelName, - binaryMessenger: registrar.messenger) - #endif - - registrar.addMethodCallDelegate(handler, channel: channel) - } - - var clientProvider: WebAuthClientProvider = { account, userAgent in - var client = Auth0.webAuth(clientId: account.clientId, domain: account.domain) - client.using(inLibrary: userAgent.name, version: userAgent.version) - return client - } - - var methodHandlerProvider: WebAuthMethodHandlerProvider = { method, client in - switch method { - case .login: return WebAuthLoginMethodHandler(client: client) - case .logout: return WebAuthLogoutMethodHandler(client: client) - } - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - - if call.method == "webAuth#cancel" { - WebAuthentication.cancel() - return - } - - guard let arguments = call.arguments as? [String: Any] else { - return result(FlutterError(from: .argumentsMissing)) - } - guard let accountDictionary = arguments[Account.key] as? [String: String], - let account = Account(from: accountDictionary) else { - return result(FlutterError(from: .accountMissing)) - } - guard let userAgentDictionary = arguments[UserAgent.key] as? [String: String], - let userAgent = UserAgent(from: userAgentDictionary) else { - return result(FlutterError(from: .userAgentMissing)) - } - guard let method = Method(rawValue: call.method) else { - return result(FlutterMethodNotImplemented) - } - - let client = clientProvider(account, userAgent) - let methodHandler = methodHandlerProvider(method, client) - - methodHandler.handle(with: arguments, callback: result) - } -} diff --git a/auth0_flutter/darwin/Classes/WebAuth/WebAuthHandler.swift b/auth0_flutter/darwin/Classes/WebAuth/WebAuthHandler.swift new file mode 120000 index 000000000..0b1894187 --- /dev/null +++ b/auth0_flutter/darwin/Classes/WebAuth/WebAuthHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/WebAuth/WebAuthLoginMethodHandler.swift b/auth0_flutter/darwin/Classes/WebAuth/WebAuthLoginMethodHandler.swift deleted file mode 100644 index b0898c8c4..000000000 --- a/auth0_flutter/darwin/Classes/WebAuth/WebAuthLoginMethodHandler.swift +++ /dev/null @@ -1,121 +0,0 @@ -import Foundation -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -#if os(iOS) -typealias WebAuthProviderFunction = (UIModalPresentationStyle) -> WebAuthProvider -#endif - -struct WebAuthLoginMethodHandler: MethodHandler { - enum Argument: String { - case scopes - case parameters - case useHTTPS - case useEphemeralSession - case audience - case redirectUrl - case organizationId - case invitationUrl - case leeway - case useDPoP - case issuer - case maxAge - #if os(iOS) - case safariViewController - #endif - } - - let client: WebAuth - - #if os(iOS) - let safariProvider: WebAuthProviderFunction - - init(client: WebAuth, safariProvider: @escaping WebAuthProviderFunction = WebAuthentication.safariProvider) { - self.client = client - self.safariProvider = safariProvider - } - #else - init(client: WebAuth) { - self.client = client - } - #endif - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let useHTTPS = arguments[Argument.useHTTPS] as? Bool else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.useHTTPS.rawValue))) - } - guard let useEphemeralSession = arguments[Argument.useEphemeralSession] as? Bool else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.useEphemeralSession.rawValue))) - } - guard let scopes = arguments[Argument.scopes] as? [String] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) - } - guard let parameters = arguments[Argument.parameters] as? [String: String] else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) - } - - var webAuth = client - .scope(scopes.asSpaceSeparatedString) - .parameters(parameters) - - if useHTTPS { - webAuth = webAuth.useHTTPS() - } - - if useEphemeralSession { - webAuth = webAuth.useEphemeralSession() - } - - if let audience = arguments[Argument.audience] as? String { - webAuth = webAuth.audience(audience) - } - - if let redirectURL = arguments[Argument.redirectUrl] as? String, let url = URL(string: redirectURL) { - webAuth = webAuth.redirectURL(url) - } - - if let organizationId = arguments[Argument.organizationId] as? String { - webAuth = webAuth.organization(organizationId) - } - - if let invitationURL = arguments[Argument.invitationUrl] as? String, - let url = URL(string: invitationURL) { - webAuth = webAuth.invitationURL(url) - } - - if let leeway = arguments[Argument.leeway] as? Int { - webAuth = webAuth.leeway(leeway) - } - - if let issuer = arguments[Argument.issuer] as? String { - webAuth = webAuth.issuer(issuer) - } - - if let maxAge = arguments[Argument.maxAge] as? Int { - webAuth = webAuth.maxAge(maxAge) - } - - #if os(iOS) - if let safariViewControllerDictionary = arguments[SafariViewController.key] as? [String: Any?] { - let safariViewController = SafariViewController(from: safariViewControllerDictionary) - webAuth = webAuth.provider(self.safariProvider(safariViewController.presentationStyle)) - } - #endif - - if arguments[Argument.useDPoP.rawValue] as? Bool == true { - webAuth = webAuth.useDPoP() - } - - webAuth.start { - switch $0 { - case let .success(credentials): callback(result(from: credentials)) - case let .failure(error): callback(FlutterError(from: error)) - } - } - } -} \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/WebAuth/WebAuthLoginMethodHandler.swift b/auth0_flutter/darwin/Classes/WebAuth/WebAuthLoginMethodHandler.swift new file mode 120000 index 000000000..ae9720bec --- /dev/null +++ b/auth0_flutter/darwin/Classes/WebAuth/WebAuthLoginMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthLoginMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/WebAuth/WebAuthLogoutMethodHandler.swift b/auth0_flutter/darwin/Classes/WebAuth/WebAuthLogoutMethodHandler.swift deleted file mode 100644 index af59de4e1..000000000 --- a/auth0_flutter/darwin/Classes/WebAuth/WebAuthLogoutMethodHandler.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Foundation -import Auth0 - -#if os(iOS) -import Flutter -#else -import FlutterMacOS -#endif - -struct WebAuthLogoutMethodHandler: MethodHandler { - enum Argument: String { - case useHTTPS - case returnTo - case federated // Add this - } - - let client: WebAuth - - func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { - guard let useHTTPS = arguments[Argument.useHTTPS] as? Bool else { - return callback(FlutterError(from: .requiredArgumentMissing(Argument.useHTTPS.rawValue))) - } - - // Extract federated parameter, default to false if not provided - let federated = arguments[Argument.federated.rawValue] as? Bool ?? false - - var webAuth = client - - if useHTTPS { - webAuth = webAuth.useHTTPS() - } - - if let returnTo = arguments[Argument.returnTo] as? String, let url = URL(string: returnTo) { - webAuth = webAuth.redirectURL(url) - } - - webAuth.clearSession(federated: federated) { // Pass federated here - switch $0 { - case .success: callback(nil) - case let .failure(error): callback(FlutterError(from: error)) - } - } - } -} diff --git a/auth0_flutter/darwin/Classes/WebAuth/WebAuthLogoutMethodHandler.swift b/auth0_flutter/darwin/Classes/WebAuth/WebAuthLogoutMethodHandler.swift new file mode 120000 index 000000000..19c9f62aa --- /dev/null +++ b/auth0_flutter/darwin/Classes/WebAuth/WebAuthLogoutMethodHandler.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthLogoutMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/Classes/WebAuth/WebAuthModels.swift b/auth0_flutter/darwin/Classes/WebAuth/WebAuthModels.swift deleted file mode 100644 index 70d4b2737..000000000 --- a/auth0_flutter/darwin/Classes/WebAuth/WebAuthModels.swift +++ /dev/null @@ -1,18 +0,0 @@ -#if os(iOS) -enum SafariViewControllerProperty: String, CaseIterable { - case presentationStyle -} - -struct SafariViewController { - var presentationStyle: UIModalPresentationStyle = UIModalPresentationStyle.fullScreen - - static let key = "safariViewController"; - - init(from dictionary: [String: Any?]) { - if let presentationStyle = dictionary[SafariViewControllerProperty.presentationStyle] as? Int, - let uiModalPresentationStyle = UIModalPresentationStyle(rawValue: presentationStyle) { - self.presentationStyle = uiModalPresentationStyle - } - } -} -#endif diff --git a/auth0_flutter/darwin/Classes/WebAuth/WebAuthModels.swift b/auth0_flutter/darwin/Classes/WebAuth/WebAuthModels.swift new file mode 120000 index 000000000..94ff60048 --- /dev/null +++ b/auth0_flutter/darwin/Classes/WebAuth/WebAuthModels.swift @@ -0,0 +1 @@ +../../../../auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthModels.swift \ No newline at end of file diff --git a/auth0_flutter/darwin/auth0_flutter.podspec b/auth0_flutter/darwin/auth0_flutter.podspec index 2212784b7..bcd300aee 100644 --- a/auth0_flutter/darwin/auth0_flutter.podspec +++ b/auth0_flutter/darwin/auth0_flutter.podspec @@ -11,7 +11,8 @@ Pod::Spec.new do |s| s.license = { :file => '../LICENSE' } s.author = { 'Auth0' => 'support@auth0.com' } s.source = { :path => '.' } - s.source_files = 'Classes/**/*' + s.source_files = 'auth0_flutter/Sources/auth0_flutter/**/*.{h,m,swift}' + s.public_header_files = 'auth0_flutter/Sources/auth0_flutter/include/**/*.h' s.ios.deployment_target = '14.0' s.ios.dependency 'Flutter' diff --git a/auth0_flutter/darwin/auth0_flutter/Package.swift b/auth0_flutter/darwin/auth0_flutter/Package.swift new file mode 100644 index 000000000..2689ee509 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Package.swift @@ -0,0 +1,30 @@ +// swift-tools-version: 5.9 +import PackageDescription + +let package = Package( + name: "auth0_flutter", + platforms: [ + .iOS("14.0"), + .macOS("11.0"), + ], + products: [ + .library(name: "auth0-flutter", targets: ["auth0_flutter"]), + ], + dependencies: [ + .package(url: "https://github.com/auth0/Auth0.swift", .upToNextMajor(from: "2.21.2")), + .package(url: "https://github.com/auth0/JWTDecode.swift", exact: "3.3.0"), + .package(url: "https://github.com/auth0/SimpleKeychain", exact: "1.3.0"), + ], + targets: [ + .target( + name: "auth0_flutter", + dependencies: [ + .product(name: "Auth0", package: "Auth0.swift"), + .product(name: "JWTDecode", package: "JWTDecode.swift"), + .product(name: "SimpleKeychain", package: "SimpleKeychain"), + ], + path: "Sources/auth0_flutter", + swiftSettings: [.define("PASSKEYS_PLATFORM")] + ), + ] +) diff --git a/auth0_flutter/darwin/Classes/SwiftAuth0FlutterPlugin.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/Auth0FlutterPlugin.swift similarity index 89% rename from auth0_flutter/darwin/Classes/SwiftAuth0FlutterPlugin.swift rename to auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/Auth0FlutterPlugin.swift index 74b9b37a2..df83c9c1f 100644 --- a/auth0_flutter/darwin/Classes/SwiftAuth0FlutterPlugin.swift +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/Auth0FlutterPlugin.swift @@ -4,7 +4,7 @@ import Flutter import FlutterMacOS #endif -public class SwiftAuth0FlutterPlugin: NSObject, FlutterPlugin { +public class Auth0FlutterPlugin: NSObject, FlutterPlugin { static var handlers: [FlutterPlugin.Type] = [WebAuthHandler.self, AuthAPIHandler.self, DPoPHandler.self, diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift new file mode 100644 index 000000000..f415b3b75 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift @@ -0,0 +1,48 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct AuthAPICustomTokenExchangeMethodHandler: MethodHandler { + enum Argument: String { + case subjectToken + case subjectTokenType + case audience + case scopes + case organization + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let subjectToken = arguments[Argument.subjectToken] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.subjectToken.rawValue))) + } + guard let subjectTokenType = arguments[Argument.subjectTokenType] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.subjectTokenType.rawValue))) + } + guard let scopes = arguments[Argument.scopes] as? [String], !scopes.isEmpty else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) + } + + let scope = scopes.asSpaceSeparatedString + let audience = arguments[Argument.audience] as? String + let organization = arguments[Argument.organization] as? String + + client + .customTokenExchange(subjectToken: subjectToken, + subjectTokenType: subjectTokenType, + audience: audience, + scope: scope, + organization: organization) + .start { + switch $0 { + case .success(let credentials): callback(self.result(from: credentials)) + case .failure(let error): callback(FlutterError(from: error)) + } + } + } +} \ No newline at end of file diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift new file mode 100644 index 000000000..5a9f79116 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift @@ -0,0 +1,47 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct AuthAPIPasswordlessEmailMethodHandler: MethodHandler { + enum Argument: String { + case email + case passwordlessType + case parameters + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let email = arguments[Argument.email] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.email.rawValue))) + } + + guard let passwordlessTypeString = arguments[Argument.passwordlessType] as? String, + let passwordlessType = PasswordlessType(rawValue: passwordlessTypeString) else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.passwordlessType.rawValue))) + } + + guard let parameters = arguments[Argument.parameters] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + + client + .startPasswordless(email: email, + type: passwordlessType, + connection: "email" + ) + .parameters(["authParams":parameters]) + .start { + switch $0 { + case let .success: + callback(nil) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIExtensions.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIExtensions.swift new file mode 100644 index 000000000..c5ec36248 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIExtensions.swift @@ -0,0 +1,61 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +enum AuthAPIErrorFlag: String, CaseIterable { + case isMultifactorRequired + case isMultifactorEnrollRequired + case isMultifactorCodeInvalid + case isMultifactorTokenInvalid + case isPasswordNotStrongEnough + case isPasswordAlreadyUsed + case isRuleError + case isInvalidCredentials + case isRefreshTokenDeleted + case isAccessDenied + case isTooManyAttempts + case isVerificationRequired + case isPasswordLeaked + case isLoginRequired + case isNetworkError +} + +enum AuthAPIErrorKey: String, CaseIterable { + case errorFlags = "_errorFlags" + case statusCode = "_statusCode" +} + +// MARK: - Extensions + +extension FlutterError { + convenience init(from authenticationError: AuthenticationError) { + let errorFlags: [String: Bool] = [ + AuthAPIErrorFlag.isMultifactorRequired.rawValue: authenticationError.isMultifactorRequired, + AuthAPIErrorFlag.isMultifactorEnrollRequired.rawValue: authenticationError.isMultifactorEnrollRequired, + AuthAPIErrorFlag.isMultifactorCodeInvalid.rawValue: authenticationError.isMultifactorCodeInvalid, + AuthAPIErrorFlag.isMultifactorTokenInvalid.rawValue: authenticationError.isMultifactorTokenInvalid, + AuthAPIErrorFlag.isPasswordNotStrongEnough.rawValue: authenticationError.isPasswordNotStrongEnough, + AuthAPIErrorFlag.isPasswordAlreadyUsed.rawValue: authenticationError.isPasswordAlreadyUsed, + AuthAPIErrorFlag.isRuleError.rawValue: authenticationError.isRuleError, + AuthAPIErrorFlag.isInvalidCredentials.rawValue: authenticationError.isInvalidCredentials, + AuthAPIErrorFlag.isRefreshTokenDeleted.rawValue: authenticationError.isRefreshTokenDeleted, + AuthAPIErrorFlag.isAccessDenied.rawValue: authenticationError.isAccessDenied, + AuthAPIErrorFlag.isTooManyAttempts.rawValue: authenticationError.isTooManyAttempts, + AuthAPIErrorFlag.isVerificationRequired.rawValue: authenticationError.isVerificationRequired, + AuthAPIErrorFlag.isPasswordLeaked.rawValue: authenticationError.isPasswordLeaked, + AuthAPIErrorFlag.isLoginRequired.rawValue: authenticationError.isLoginRequired, + AuthAPIErrorFlag.isNetworkError.rawValue: authenticationError.isNetworkError, + ] + var errorDetails = authenticationError.details + errorDetails[AuthAPIErrorKey.errorFlags] = errorFlags + errorDetails[AuthAPIErrorKey.statusCode] = authenticationError.statusCode + + self.init(code: authenticationError.code, + message: String(describing: authenticationError), + details: errorDetails) + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIHandler.swift new file mode 100644 index 000000000..eb41b2cb9 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIHandler.swift @@ -0,0 +1,123 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +// MARK: - Providers + +typealias AuthAPIClientProvider = (_ account: Account, _ userAgent: UserAgent, _ arguments: [String: Any]) -> Authentication +typealias AuthAPIMethodHandlerProvider = (_ method: AuthAPIHandler.Method, _ client: Authentication) -> MethodHandler + +// MARK: - Auth Auth Handler + +public class AuthAPIHandler: NSObject, FlutterPlugin { + enum Method: String, CaseIterable { + case loginWithUsernameOrEmail = "auth#login" + case loginWithOTP = "auth#loginOtp" + case multifactorChallenge = "auth#multifactorChallenge" + case signup = "auth#signUp" + case userInfo = "auth#userInfo" + case renew = "auth#renew" + case customTokenExchange = "auth#customTokenExchange" + case resetPassword = "auth#resetPassword" + case passwordlessWithEmail = "auth#passwordlessWithEmail" + case passwordlessWithPhoneNumber = "auth#passwordlessWithPhoneNumber" + case loginWithEmailCode = "auth#loginWithEmail" + case loginWithSMSCode = "auth#loginWithPhoneNumber" + case ssoExchange = "auth#ssoExchange" + case passkeyLoginChallenge = "auth#passkeyLoginChallenge" + case passkeySignupChallenge = "auth#passkeySignupChallenge" + case passkeyCredentialExchange = "auth#passkeyCredentialExchange" + } + + private static let channelName = "auth0.com/auth0_flutter/auth" + + public static func register(with registrar: FlutterPluginRegistrar) { + let handler = AuthAPIHandler() + + #if os(iOS) + let channel = FlutterMethodChannel(name: AuthAPIHandler.channelName, + binaryMessenger: registrar.messenger()) + #else + let channel = FlutterMethodChannel(name: AuthAPIHandler.channelName, + binaryMessenger: registrar.messenger) + #endif + + registrar.addMethodCallDelegate(handler, channel: channel) + } + + var clientProvider: AuthAPIClientProvider = { account, userAgent, arguments in + var client = Auth0.authentication(clientId: account.clientId, domain: account.domain) + client.using(inLibrary: userAgent.name, version: userAgent.version) + + let useDPoP = arguments["useDPoP"] as? Bool ?? false + if useDPoP { + client = client.useDPoP() + } + + return client + } + + var methodHandlerProvider: AuthAPIMethodHandlerProvider = { method, client in + switch method { + case .loginWithUsernameOrEmail: return AuthAPILoginUsernameOrEmailMethodHandler(client: client) + case .loginWithOTP: return AuthAPILoginWithOTPMethodHandler(client: client) + case .multifactorChallenge: return AuthAPIMultifactorChallengeMethodHandler(client: client) + case .signup: return AuthAPISignupMethodHandler(client: client) + case .userInfo: return AuthAPIUserInfoMethodHandler(client: client) + case .renew: return AuthAPIRenewMethodHandler(client: client) + case .customTokenExchange: return AuthAPICustomTokenExchangeMethodHandler(client: client) + case .resetPassword: return AuthAPIResetPasswordMethodHandler(client: client) + case .passwordlessWithEmail: return AuthAPIPasswordlessEmailMethodHandler(client: client) + case .passwordlessWithPhoneNumber: return AuthAPIPasswordlessPhoneNumberMethodHandler(client: client) + case .loginWithEmailCode: return AuthAPILoginWithEmailMethodHandler(client: client) + case .loginWithSMSCode: return AuthAPILoginWithPhoneNumberMethodHandler(client: client) + case .ssoExchange: return SSOExchangeMethodHandler(client: client) + #if PASSKEYS_PLATFORM + case .passkeyLoginChallenge: + if #available(iOS 16.6, macOS 13.5, visionOS 1.0, *) { + return AuthAPIPasskeyLoginChallengeMethodHandler(client: client) + } + return UnsupportedMethodHandler() + case .passkeySignupChallenge: + if #available(iOS 16.6, macOS 13.5, visionOS 1.0, *) { + return AuthAPIPasskeySignupChallengeMethodHandler(client: client) + } + return UnsupportedMethodHandler() + case .passkeyCredentialExchange: + if #available(iOS 16.6, macOS 13.5, visionOS 1.0, *) { + return AuthAPIPasskeyCredentialExchangeMethodHandler(client: client) + } + return UnsupportedMethodHandler() + #else + case .passkeyLoginChallenge, .passkeySignupChallenge, .passkeyCredentialExchange: + return UnsupportedMethodHandler() + #endif + } + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + guard let arguments = call.arguments as? [String: Any] else { + return result(FlutterError(from: .argumentsMissing)) + } + guard let accountDictionary = arguments[Account.key] as? [String: String], + let account = Account(from: accountDictionary) else { + return result(FlutterError(from: .accountMissing)) + } + guard let userAgentDictionary = arguments[UserAgent.key] as? [String: String], + let userAgent = UserAgent(from: userAgentDictionary) else { + return result(FlutterError(from: .userAgentMissing)) + } + guard let method = Method(rawValue: call.method) else { + return result(FlutterMethodNotImplemented) + } + + let client = clientProvider(account, userAgent, arguments) + let methodHandler = methodHandlerProvider(method, client) + + methodHandler.handle(with: arguments, callback: result) + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift new file mode 100644 index 000000000..eed76dc20 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift @@ -0,0 +1,54 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct AuthAPILoginUsernameOrEmailMethodHandler: MethodHandler { + enum Argument: String { + case usernameOrEmail + case password + case connectionOrRealm + case scopes + case parameters + case audience + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let usernameOrEmail = arguments[Argument.usernameOrEmail] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.usernameOrEmail.rawValue))) + } + guard let password = arguments[Argument.password] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.password.rawValue))) + } + guard let connectionOrRealm = arguments[Argument.connectionOrRealm] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.connectionOrRealm.rawValue))) + } + guard let scopes = arguments[Argument.scopes] as? [String] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) + } + guard let parameters = arguments[Argument.parameters] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + + let audience = arguments[Argument.audience] as? String + + client + .login(usernameOrEmail: usernameOrEmail, + password: password, + realmOrConnection: connectionOrRealm, + audience: audience, + scope: scopes.asSpaceSeparatedString) + .parameters(parameters) + .start { + switch $0 { + case let .success(credentials): callback(result(from: credentials)) + case let .failure(error): callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift new file mode 100644 index 000000000..02f2f23d6 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift @@ -0,0 +1,54 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct AuthAPILoginWithEmailMethodHandler: MethodHandler { + + enum Argument: String { + case email + case verificationCode + case scopes + case audience + case parameters + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let email = arguments[Argument.email] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.email.rawValue))) + } + + guard let verificationCode = arguments[Argument.verificationCode] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.verificationCode.rawValue))) + } + + guard let scopes = arguments[Argument.scopes] as? [String] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) + } + + guard let parameters = arguments[Argument.parameters] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + + let audience = arguments[Argument.audience] as? String + + client + .login(email: email, + code: verificationCode, + audience: audience, + scope: scopes.asSpaceSeparatedString + ) + .parameters(parameters) + .start { + switch $0 { + case let .success(credentials): callback(result(from: credentials)) + case let .failure(error):callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift new file mode 100644 index 000000000..e1a36cf8f --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift @@ -0,0 +1,34 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct AuthAPILoginWithOTPMethodHandler: MethodHandler { + enum Argument: String { + case otp + case mfaToken + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let otp = arguments[Argument.otp] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.otp.rawValue))) + } + guard let mfaToken = arguments[Argument.mfaToken] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.mfaToken.rawValue))) + } + + client + .login(withOTP: otp, mfaToken: mfaToken) + .start { + switch $0 { + case let .success(credentials): callback(result(from: credentials)) + case let .failure(error): callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift new file mode 100644 index 000000000..be1a517b3 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift @@ -0,0 +1,55 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct AuthAPILoginWithPhoneNumberMethodHandler: MethodHandler { + enum Argument: String { + case phoneNumber + case verificationCode + case scopes + case audience + case parameters + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let phoneNumber = arguments[Argument.phoneNumber] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.phoneNumber.rawValue))) + } + + guard let verificationCode = arguments[Argument.verificationCode] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.verificationCode.rawValue))) + } + + guard let scopes = arguments[Argument.scopes] as? [String] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) + } + + guard let parameters = arguments[Argument.parameters] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + + + let audience = arguments[Argument.audience] as? String + + client + .login(phoneNumber: phoneNumber, + code: verificationCode, + audience: audience, + scope: scopes.asSpaceSeparatedString + ) + .parameters(parameters) + .start { + switch $0 { + case let .success(credentials): callback(result(from: credentials)) + case let .failure(error):callback(FlutterError(from: error)) + } + } + } +} + diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift new file mode 100644 index 000000000..a409a4670 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift @@ -0,0 +1,51 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +enum ChallengeProperty: String { + case challengeType + case oobCode + case bindingMethod +} + +fileprivate extension MethodHandler { + func result(from challenge: Challenge) -> Any? { + var data: [String: Any] = [ChallengeProperty.challengeType.rawValue: challenge.challengeType] + data[ChallengeProperty.oobCode] = challenge.oobCode + data[ChallengeProperty.bindingMethod] = challenge.bindingMethod + return data + } +} + +struct AuthAPIMultifactorChallengeMethodHandler: MethodHandler { + enum Argument: String { + case mfaToken + case types + case authenticatorId + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let mfaToken = arguments[Argument.mfaToken] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.mfaToken.rawValue))) + } + + let types = arguments[Argument.types] as? [String] + let authenticatorId = arguments[Argument.authenticatorId] as? String + + client + .multifactorChallenge(mfaToken: mfaToken, types: types, authenticatorId: authenticatorId) + .start { + switch $0 { + case let .success(challenge): callback(result(from: challenge)) + case let .failure(error): callback(FlutterError(from: error)) + } + + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift new file mode 100644 index 000000000..5849d52eb --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift @@ -0,0 +1,235 @@ +#if PASSKEYS_PLATFORM +import Auth0 +import AuthenticationServices + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +/// A ``LoginPasskey`` reconstructed from a credential map provided by the +/// Flutter layer (the app presents the OS passkey UI and passes the resulting +/// assertion). +@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) +private struct ReconstructedLoginPasskey: LoginPasskey { + let userID: Data! + let credentialID: Data + let attachment: ASAuthorizationPublicKeyCredentialAttachment + let rawClientDataJSON: Data + let rawAuthenticatorData: Data! + let signature: Data! +} + +/// A ``SignupPasskey`` reconstructed from a credential map supplied by the app +/// (for example, from `ASAuthorizationController`). +@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) +private struct ReconstructedSignupPasskey: SignupPasskey { + let credentialID: Data + let attachment: ASAuthorizationPublicKeyCredentialAttachment + let rawClientDataJSON: Data + let rawAttestationObject: Data? +} + +/// Exchanges an app-supplied passkey credential (a login assertion or a signup +/// attestation) and its challenge for Auth0 tokens at the `/oauth/token` +/// endpoint. This handler does not present any UI. +/// +/// Both passkey login and signup finish here. The credential's `response` +/// determines the flow: an `attestationObject` indicates a signup attestation, +/// while `authenticatorData` + `signature` indicate a login assertion. The +/// matching `LoginPasskey`/`SignupPasskey` and challenge are reconstructed and +/// passed to the shared `Authentication.login(passkey:challenge:...)` call. +@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) +struct AuthAPIPasskeyCredentialExchangeMethodHandler: MethodHandler { + enum Argument: String { + case challenge + case credential + case connection + case audience + case scopes + case organization + case parameters + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let challengeMap = arguments[Argument.challenge.rawValue] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.challenge.rawValue))) + } + guard let credentialMap = arguments[Argument.credential.rawValue] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.credential.rawValue))) + } + + let connection = arguments[Argument.connection.rawValue] as? String + let audience = arguments[Argument.audience.rawValue] as? String + let scopes = (arguments[Argument.scopes.rawValue] as? [String]) ?? [] + let organization = arguments[Argument.organization.rawValue] as? String + let parameters = (arguments[Argument.parameters.rawValue] as? [String: Any]) ?? [:] + + let response = credentialMap["response"] as? [String: Any] + let isSignup = response?["attestationObject"] != nil + + let request: Request + if isSignup { + guard let challenge = Self.reconstructSignupChallenge(from: challengeMap) else { + return callback(FlutterError(code: "PASSKEY_ERROR", + message: "Failed to reconstruct signup challenge", + details: nil)) + } + guard let passkey = Self.reconstructSignupPasskey(from: credentialMap) else { + return callback(FlutterError(code: "PASSKEY_ERROR", + message: "Failed to reconstruct passkey credential", + details: nil)) + } + request = client.login(passkey: passkey, + challenge: challenge, + connection: connection, + audience: audience, + scope: scopes.asSpaceSeparatedString, + organization: organization) + } else { + guard let challenge = Self.reconstructLoginChallenge(from: challengeMap) else { + return callback(FlutterError(code: "PASSKEY_ERROR", + message: "Failed to reconstruct login challenge", + details: nil)) + } + guard let passkey = Self.reconstructLoginPasskey(from: credentialMap) else { + return callback(FlutterError(code: "PASSKEY_ERROR", + message: "Failed to reconstruct passkey credential", + details: nil)) + } + request = client.login(passkey: passkey, + challenge: challenge, + connection: connection, + audience: audience, + scope: scopes.asSpaceSeparatedString, + organization: organization) + } + + request + .parameters(parameters) + .start { + switch $0 { + case let .success(credentials): + callback(self.result(from: credentials)) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } + + // MARK: - Login reconstruction + + private static func reconstructLoginChallenge( + from challengeMap: [String: Any]) -> PasskeyLoginChallenge? { + guard let authParamsPublicKey = challengeMap["authParamsPublicKey"] as? [String: Any], + let authSession = challengeMap["authSession"] as? String, + let challengeString = authParamsPublicKey["challenge"] as? String, + let relyingPartyId = authParamsPublicKey["rpId"] as? String else { + return nil + } + + let challengeJson: [String: Any] = [ + "auth_session": authSession, + "authn_params_public_key": [ + "rpId": relyingPartyId, + "challenge": challengeString + ] + ] + + guard let jsonData = try? JSONSerialization.data(withJSONObject: challengeJson) else { + return nil + } + return try? JSONDecoder().decode(PasskeyLoginChallenge.self, from: jsonData) + } + + private static func reconstructLoginPasskey( + from credentialMap: [String: Any]) -> LoginPasskey? { + guard let credentialIdString = credentialMap["rawId"] as? String + ?? credentialMap["id"] as? String, + let credentialID = Data.fromBase64URLEncoded(credentialIdString), + let response = credentialMap["response"] as? [String: Any], + let clientDataString = response["clientDataJSON"] as? String, + let rawClientDataJSON = Data.fromBase64URLEncoded(clientDataString), + let authenticatorDataString = response["authenticatorData"] as? String, + let rawAuthenticatorData = Data.fromBase64URLEncoded(authenticatorDataString), + let signatureString = response["signature"] as? String, + let signature = Data.fromBase64URLEncoded(signatureString) else { + return nil + } + + // Auth0.swift force-unwraps `userID` when building the request, so fall + // back to empty data rather than nil when no user handle was returned. + let userID = (response["userHandle"] as? String) + .flatMap { Data.fromBase64URLEncoded($0) } ?? Data() + + let attachment: ASAuthorizationPublicKeyCredentialAttachment = + (credentialMap["authenticatorAttachment"] as? String) == "crossPlatform" + ? .crossPlatform : .platform + + return ReconstructedLoginPasskey( + userID: userID, + credentialID: credentialID, + attachment: attachment, + rawClientDataJSON: rawClientDataJSON, + rawAuthenticatorData: rawAuthenticatorData, + signature: signature + ) + } + + // MARK: - Signup reconstruction + + private static func reconstructSignupChallenge( + from challengeMap: [String: Any]) -> PasskeySignupChallenge? { + guard let authParamsPublicKey = challengeMap["authParamsPublicKey"] as? [String: Any], + let authSession = challengeMap["authSession"] as? String, + let challengeString = authParamsPublicKey["challenge"] as? String, + let relyingPartyId = authParamsPublicKey["rpId"] as? String, + let userId = authParamsPublicKey["userId"] as? String, + let userName = authParamsPublicKey["userName"] as? String else { + return nil + } + + let challengeJson: [String: Any] = [ + "auth_session": authSession, + "authn_params_public_key": [ + "rp": ["id": relyingPartyId], + "user": ["id": userId, "name": userName], + "challenge": challengeString + ] + ] + + guard let jsonData = try? JSONSerialization.data(withJSONObject: challengeJson) else { + return nil + } + return try? JSONDecoder().decode(PasskeySignupChallenge.self, from: jsonData) + } + + private static func reconstructSignupPasskey( + from credentialMap: [String: Any]) -> SignupPasskey? { + guard let credentialIdString = credentialMap["rawId"] as? String + ?? credentialMap["id"] as? String, + let credentialID = Data.fromBase64URLEncoded(credentialIdString), + let response = credentialMap["response"] as? [String: Any], + let clientDataString = response["clientDataJSON"] as? String, + let rawClientDataJSON = Data.fromBase64URLEncoded(clientDataString), + let attestationString = response["attestationObject"] as? String, + let rawAttestationObject = Data.fromBase64URLEncoded(attestationString) else { + return nil + } + + let attachment: ASAuthorizationPublicKeyCredentialAttachment = + (credentialMap["authenticatorAttachment"] as? String) == "crossPlatform" + ? .crossPlatform : .platform + + return ReconstructedSignupPasskey( + credentialID: credentialID, + attachment: attachment, + rawClientDataJSON: rawClientDataJSON, + rawAttestationObject: rawAttestationObject + ) + } +} +#endif diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeyExtensions.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeyExtensions.swift new file mode 100644 index 000000000..213681b3a --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeyExtensions.swift @@ -0,0 +1,21 @@ +#if PASSKEYS_PLATFORM +import Foundation + +extension Data { + func base64URLEncodedString() -> String { + return self.base64EncodedString() + .replacingOccurrences(of: "+", with: "-") + .replacingOccurrences(of: "/", with: "_") + .trimmingCharacters(in: CharacterSet(charactersIn: "=")) + } + + static func fromBase64URLEncoded(_ string: String) -> Data? { + var base64 = string + .replacingOccurrences(of: "-", with: "+") + .replacingOccurrences(of: "_", with: "/") + let paddingLength = (4 - base64.count % 4) % 4 + base64 += String(repeating: "=", count: paddingLength) + return Data(base64Encoded: base64) + } +} +#endif diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift new file mode 100644 index 000000000..5f0ed3928 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift @@ -0,0 +1,47 @@ +#if PASSKEYS_PLATFORM +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) +struct AuthAPIPasskeyLoginChallengeMethodHandler: MethodHandler { + enum Argument: String { + case connection + case organization + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + let connection = arguments[Argument.connection] as? String + let organization = arguments[Argument.organization] as? String + + client + .passkeyLoginChallenge(connection: connection, organization: organization) + .start { + switch $0 { + case let .success(challenge): + // Unlike Android, the iOS Auth0.swift challenge only exposes + // the relying-party id and challenge data; `timeout` and + // `userVerification` are not surfaced by the native API and + // are not needed to build the assertion request here. The + // asymmetry with the Android payload is intentional. + let response: [String: Any] = [ + "authSession": challenge.authenticationSession, + "authParamsPublicKey": [ + "challenge": challenge.challengeData.base64URLEncodedString(), + "rpId": challenge.relyingPartyId + ] + ] + callback(response) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} +#endif diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift new file mode 100644 index 000000000..3e7fe20cf --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift @@ -0,0 +1,72 @@ +#if PASSKEYS_PLATFORM +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) +struct AuthAPIPasskeySignupChallengeMethodHandler: MethodHandler { + enum Argument: String { + case email + case phoneNumber + case username + case name + case givenName + case familyName + case nickname + case picture + case connection + case organization + case userMetadata + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + let email = arguments[Argument.email] as? String + let phoneNumber = arguments[Argument.phoneNumber] as? String + let username = arguments[Argument.username] as? String + let name = arguments[Argument.name] as? String + let givenName = arguments[Argument.givenName] as? String + let familyName = arguments[Argument.familyName] as? String + let nickname = arguments[Argument.nickname] as? String + let picture = arguments[Argument.picture] as? String + let connection = arguments[Argument.connection] as? String + let organization = arguments[Argument.organization] as? String + let userMetadata = arguments[Argument.userMetadata] as? [String: String] + + client + .passkeySignupChallenge(email: email, + phoneNumber: phoneNumber, + username: username, + name: name, + givenName: givenName, + familyName: familyName, + nickname: nickname, + picture: picture, + userMetadata: userMetadata, + connection: connection, + organization: organization) + .start { + switch $0 { + case let .success(challenge): + let response: [String: Any] = [ + "authSession": challenge.authenticationSession, + "authParamsPublicKey": [ + "challenge": challenge.challengeData.base64URLEncodedString(), + "rpId": challenge.relyingPartyId, + "userId": challenge.userId.base64URLEncodedString(), + "userName": challenge.userName + ] + ] + callback(response) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} +#endif diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift new file mode 100644 index 000000000..c09f52e6a --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift @@ -0,0 +1,49 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct AuthAPIPasswordlessPhoneNumberMethodHandler: MethodHandler { + enum Argument: String { + case phoneNumber + case passwordlessType + case parameters + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let phoneNumber = arguments[Argument.phoneNumber] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.phoneNumber.rawValue))) + } + + guard let passwordlessTypeString = arguments[Argument.passwordlessType] as? String, + let passwordlessType = PasswordlessType(rawValue: passwordlessTypeString) else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.passwordlessType.rawValue))) + } + + guard let parameters = arguments[Argument.parameters] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + + client + .startPasswordless(phoneNumber: phoneNumber, + type: passwordlessType, + connection: "sms" + ) + .parameters(["authParams":parameters]) + .start { + switch $0 { + case .success: + callback(nil) + + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} + diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIRenewMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIRenewMethodHandler.swift new file mode 100644 index 000000000..5e21075a7 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIRenewMethodHandler.swift @@ -0,0 +1,40 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct AuthAPIRenewMethodHandler: MethodHandler { + enum Argument: String { + case refreshToken + case scopes + case parameters + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let refreshToken = arguments[Argument.refreshToken] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.refreshToken.rawValue))) + } + guard let scopes = arguments[Argument.scopes] as? [String] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) + } + guard let parameters = arguments[Argument.parameters] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + + client + .renew(withRefreshToken: refreshToken, + scope: scopes.isEmpty ? nil : scopes.asSpaceSeparatedString) + .parameters(parameters) + .start { + switch $0 { + case let .success(credentials): callback(result(from: credentials)) + case let .failure(error): callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIResetPasswordMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIResetPasswordMethodHandler.swift new file mode 100644 index 000000000..f1a844e91 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIResetPasswordMethodHandler.swift @@ -0,0 +1,39 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct AuthAPIResetPasswordMethodHandler: MethodHandler { + enum Argument: String { + case email + case connection + case parameters + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let email = arguments[Argument.email] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.email.rawValue))) + } + guard let connection = arguments[Argument.connection] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.connection.rawValue))) + } + guard let parameters = arguments[Argument.parameters] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + + client + .resetPassword(email: email, connection: connection) + .parameters(parameters) + .start { + switch $0 { + case .success: callback(nil) + case let .failure(error): callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPISignupMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPISignupMethodHandler.swift new file mode 100644 index 000000000..650698d8f --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPISignupMethodHandler.swift @@ -0,0 +1,72 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +enum DatabaseUserProperty: String { + case email + case emailVerified + case username +} + +fileprivate extension MethodHandler { + func result(from databaseUser: DatabaseUser) -> Any? { + var data: [String: Any] = [ + DatabaseUserProperty.email.rawValue: databaseUser.email, + DatabaseUserProperty.emailVerified.rawValue: databaseUser.verified + ] + data[DatabaseUserProperty.username] = databaseUser.username + return data + } +} + +struct AuthAPISignupMethodHandler: MethodHandler { + enum Argument: String { + case email + case password + case connection + case username + case userMetadata + case parameters + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let email = arguments[Argument.email] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.email.rawValue))) + } + guard let password = arguments[Argument.password] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.password.rawValue))) + } + guard let connection = arguments[Argument.connection] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.connection.rawValue))) + } + guard let userMetadata = arguments[Argument.userMetadata] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.userMetadata.rawValue))) + } + guard let parameters = arguments[Argument.parameters] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + + let username = arguments[Argument.username] as? String + + client + .signup(email: email, + username: username, + password: password, + connection: connection, + userMetadata: userMetadata) + .parameters(parameters) + .start { + switch $0 { + case let .success(databaseUser): callback(result(from: databaseUser)) + case let .failure(error): callback(FlutterError(from: error)) + } + + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIUserInfoMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIUserInfoMethodHandler.swift new file mode 100644 index 000000000..2790d109a --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/AuthAPIUserInfoMethodHandler.swift @@ -0,0 +1,44 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +fileprivate extension MethodHandler { + func result(from userInfo: UserInfo) -> Any? { + return userInfo.asDictionary() + } +} + +struct AuthAPIUserInfoMethodHandler: MethodHandler { + enum Argument: String { + case accessToken + case parameters + case tokenType + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let accessToken = arguments[Argument.accessToken] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.accessToken.rawValue))) + } + guard let parameters = arguments[Argument.parameters] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + + let tokenType = arguments[Argument.tokenType] as? String ?? "Bearer" + + client + .userInfo(withAccessToken: accessToken, tokenType: tokenType) + .parameters(parameters) + .start { + switch $0 { + case let .success(userInfo): callback(result(from: userInfo)) + case let .failure(error): callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/SSOExchangeMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/SSOExchangeMethodHandler.swift new file mode 100644 index 000000000..6cf5c08f4 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/AuthAPI/SSOExchangeMethodHandler.swift @@ -0,0 +1,50 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct SSOExchangeMethodHandler: MethodHandler { + enum Argument: String { + case refreshToken + case parameters + case headers + } + + let client: Authentication + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let refreshToken = arguments[Argument.refreshToken] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.refreshToken.rawValue))) + } + guard let parameters = arguments[Argument.parameters] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + guard let headers = arguments[Argument.headers] as? [String: String] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.headers.rawValue))) + } + + client + .ssoExchange(withRefreshToken: refreshToken) + .parameters(parameters) + .headers(headers) + .start { + switch $0 { + case let .success(ssoCredentials): + var response: [String: Any] = [ + "sessionTransferToken": ssoCredentials.sessionTransferToken, + "tokenType": ssoCredentials.issuedTokenType, + "expiresIn": Int(ssoCredentials.expiresIn.timeIntervalSinceNow) + ] + response["idToken"] = ssoCredentials.idToken + if let refreshToken = ssoCredentials.refreshToken { + response["refreshToken"] = refreshToken + } + callback(response) + case let .failure(error): callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/ApiCredentialsMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/ApiCredentialsMethodHandler.swift new file mode 100644 index 000000000..b884e1b03 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/ApiCredentialsMethodHandler.swift @@ -0,0 +1,50 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct ApiCredentialsMethodHandler: MethodHandler { + + enum Argument: String { + case audience + case scopes + case minTtl + case parameters + case headers + } + + let credentialsManager: CredentialsManager + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let audience = arguments[Argument.audience] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.audience.rawValue))) + } + guard let scopes = arguments[Argument.scopes] as? [String] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) + } + guard let minTTL = arguments[Argument.minTtl] as? Int else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.minTtl.rawValue))) + } + guard let parameters = arguments[Argument.parameters] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + guard let headers = arguments[Argument.headers] as? [String: String] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.headers.rawValue))) + } + + self.credentialsManager.apiCredentials(forAudience: audience, + scope: scopes.isEmpty ? nil : scopes.asSpaceSeparatedString, + minTTL: minTTL, + parameters: parameters, + headers: headers) { + switch $0 { + case let .success(apiCredentials): callback(apiCredentials.asDictionary()) + case let .failure(error): callback(FlutterError(from: error)) + } + } + } + +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/ClearApiCredentialsMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/ClearApiCredentialsMethodHandler.swift new file mode 100644 index 000000000..ef3fdbea7 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/ClearApiCredentialsMethodHandler.swift @@ -0,0 +1,27 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct ClearApiCredentialsMethodHandler: MethodHandler { + + enum Argument: String { + case audience + case scope + } + + let credentialsManager: CredentialsManager + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let audience = arguments[Argument.audience] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.audience.rawValue))) + } + let scope = arguments[Argument.scope] as? String + + callback(self.credentialsManager.clear(forAudience: audience, scope: scope)) + } + +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerClearMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerClearMethodHandler.swift new file mode 100644 index 000000000..000136322 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerClearMethodHandler.swift @@ -0,0 +1,15 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct CredentialsManagerClearMethodHandler: MethodHandler { + let credentialsManager: CredentialsManager + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + callback(self.credentialsManager.clear()) + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerExtensions.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerExtensions.swift new file mode 100644 index 000000000..a3efc75ba --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerExtensions.swift @@ -0,0 +1,32 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +extension FlutterError { + convenience init(from credentialsManagerError: CredentialsManagerError) { + var code: String + switch credentialsManagerError { + case .noCredentials: code = "NO_CREDENTIALS" + case .noRefreshToken: code = "NO_REFRESH_TOKEN" + case .renewFailed: code = "RENEW_FAILED" + case .storeFailed: code = "STORE_FAILED" + case .biometricsFailed: code = "BIOMETRICS_FAILED" + case .revokeFailed: code = "REVOKE_FAILED" + case .largeMinTTL: code = "LARGE_MIN_TTL" + default: code = "UNKNOWN" + } + + let isRetryable = (credentialsManagerError.cause as? Auth0APIError)?.isRetryable ?? false + + var errorDetails = credentialsManagerError.details + errorDetails["_isRetryable"] = isRetryable + + self.init(code: code, + message: String(describing: credentialsManagerError), + details: errorDetails) + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerGetMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerGetMethodHandler.swift new file mode 100644 index 000000000..11eccc07a --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerGetMethodHandler.swift @@ -0,0 +1,38 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct CredentialsManagerGetMethodHandler: MethodHandler { + enum Argument: String { + case scopes + case minTtl + case parameters + } + + let credentialsManager: CredentialsManager + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let scopes = arguments[Argument.scopes] as? [String] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) + } + guard let minTTL = arguments[Argument.minTtl] as? Int else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.minTtl.rawValue))) + } + guard let parameters = arguments[Argument.parameters] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + + self.credentialsManager.credentials(withScope: scopes.isEmpty ? nil : scopes.asSpaceSeparatedString, + minTTL: minTTL, + parameters: parameters) { + switch $0 { + case let .success(credentials): callback(result(from: credentials)) + case let .failure(error): callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerHandler.swift new file mode 100644 index 000000000..908097dfe --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerHandler.swift @@ -0,0 +1,167 @@ +import Auth0 +import SimpleKeychain + + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +// MARK: - Providers + +typealias CredentialsManagerProvider = (_ apiClient: Authentication, _ arguments: [String: Any]) -> CredentialsManager +typealias CredentialsManagerMethodHandlerProvider = (_ method: CredentialsManagerHandler.Method, + _ credentialsManager: CredentialsManager) -> MethodHandler + +// MARK: - Credentials Manager Handler + +public class CredentialsManagerHandler: NSObject, FlutterPlugin { + enum Method: String, CaseIterable { + case save = "credentialsManager#saveCredentials" + case hasValid = "credentialsManager#hasValidCredentials" + case get = "credentialsManager#getCredentials" + case renew = "credentialsManager#renewCredentials" + case clear = "credentialsManager#clearCredentials" + case userInfo = "credentialsManager#user" + case sso = "credentialsManager#getSSOCredentials" + case apiCredentials = "credentialsManager#getApiCredentials" + case clearApiCredentials = "credentialsManager#clearApiCredentials" + } + + private struct ManagerCacheKey: Equatable { + let accountDomain: String + let accountClientId: String + let storeKey: String + let accessGroup: String? + let useDPoP: Bool + let hasLocalAuth: Bool + } + + private static let channelName = "auth0.com/auth0_flutter/credentials_manager" + private static var credentialsManager: CredentialsManager? + private static var cachedKey: ManagerCacheKey? + + public static func register(with registrar: FlutterPluginRegistrar) { + let handler = CredentialsManagerHandler() + + #if os(iOS) + let channel = FlutterMethodChannel(name: CredentialsManagerHandler.channelName, + binaryMessenger: registrar.messenger()) + #else + let channel = FlutterMethodChannel(name: CredentialsManagerHandler.channelName, + binaryMessenger: registrar.messenger) + #endif + + registrar.addMethodCallDelegate(handler, channel: channel) + } + + func createCredentialManager(_ apiClient: Authentication, _ arguments: [String: Any]) -> CredentialsManager { + if let configuration = arguments["credentialsManagerConfiguration"] as? [String: Any], + let iosConfiguration = configuration["ios"] as? [String: String] { + + let storeKey = iosConfiguration["storeKey"] ?? "credentials" + let accessGroup = iosConfiguration["accessGroup"] + let accessibilityString = iosConfiguration["accessibility"] ?? "afterFirstUnlock" + let accessibility = Accessibility(rawValue: accessibilityString as CFString) + + let storage = SimpleKeychain( + accessGroup: accessGroup, + accessibility: accessibility + ) + return CredentialsManager(authentication: apiClient, storeKey: storeKey, storage: storage) + } else { + return CredentialsManager(authentication: apiClient) + } + } + + var apiClientProvider: AuthAPIClientProvider = { account, userAgent, arguments in + let useDPoP = arguments["useDPoP"] as? Bool ?? false + var client = Auth0.authentication(clientId: account.clientId, domain: account.domain) + client.using(inLibrary: userAgent.name, version: userAgent.version) + return useDPoP ? client.useDPoP() : client + } + + + lazy var credentialsManagerProvider: CredentialsManagerProvider = { apiClient, arguments in + + let configuration = arguments["credentialsManagerConfiguration"] as? [String: Any] + let iosConfiguration = configuration?["ios"] as? [String: String] + let storeKey = iosConfiguration?["storeKey"] ?? "credentials" + let accessGroup = iosConfiguration?["accessGroup"] + let useDPoP = arguments["useDPoP"] as? Bool ?? false + let hasLocalAuth = arguments[LocalAuthentication.key] != nil + + guard let accountDictionary = arguments[Account.key] as? [String: String], + let account = Account(from: accountDictionary) else { + return self.createCredentialManager(apiClient, arguments) + } + + let currentKey = ManagerCacheKey( + accountDomain: account.domain, + accountClientId: account.clientId, + storeKey: storeKey, + accessGroup: accessGroup, + useDPoP: useDPoP, + hasLocalAuth: hasLocalAuth + ) + + var instance: CredentialsManager + if let cachedKey = CredentialsManagerHandler.cachedKey, + cachedKey == currentKey, + let cachedManager = CredentialsManagerHandler.credentialsManager { + instance = cachedManager + } else { + instance = self.createCredentialManager(apiClient, arguments) + + CredentialsManagerHandler.credentialsManager = instance + CredentialsManagerHandler.cachedKey = currentKey + } + + if let localAuthenticationDictionary = arguments[LocalAuthentication.key] as? [String: String?] { + let localAuthentication = LocalAuthentication(from: localAuthenticationDictionary) + instance.enableBiometrics(withTitle: localAuthentication.title, + cancelTitle: localAuthentication.cancelTitle, + fallbackTitle: localAuthentication.fallbackTitle) + } + + return instance + } + + var methodHandlerProvider: CredentialsManagerMethodHandlerProvider = { method, credentialsManager in + switch method { + case .save: return CredentialsManagerSaveMethodHandler(credentialsManager: credentialsManager) + case .hasValid: return CredentialsManagerHasValidMethodHandler(credentialsManager: credentialsManager) + case .get: return CredentialsManagerGetMethodHandler(credentialsManager: credentialsManager) + case .clear: return CredentialsManagerClearMethodHandler(credentialsManager: credentialsManager) + case .userInfo: return CredentialsManagerUserInfoMethodHandler(credentialsManager: credentialsManager) + case .renew: return CredentialsManagerRenewMethodHandler(credentialsManager: credentialsManager) + case .sso: return SSOCredentialsMethodHandler(credentialsManager: credentialsManager) + case .apiCredentials: return ApiCredentialsMethodHandler(credentialsManager: credentialsManager) + case .clearApiCredentials: return ClearApiCredentialsMethodHandler(credentialsManager: credentialsManager) + } + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + guard let arguments = call.arguments as? [String: Any] else { + return result(FlutterError(from: .argumentsMissing)) + } + guard let accountDictionary = arguments[Account.key] as? [String: String], + let account = Account(from: accountDictionary) else { + return result(FlutterError(from: .accountMissing)) + } + guard let userAgentDictionary = arguments[UserAgent.key] as? [String: String], + let userAgent = UserAgent(from: userAgentDictionary) else { + return result(FlutterError(from: .userAgentMissing)) + } + guard let method = Method(rawValue: call.method) else { + return result(FlutterMethodNotImplemented) + } + + let apiClient = apiClientProvider(account, userAgent, arguments) + let credentialsManager = credentialsManagerProvider(apiClient, arguments) + let methodHandler = methodHandlerProvider(method, credentialsManager) + methodHandler.handle(with: arguments, callback: result) + } + +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift new file mode 100644 index 000000000..bf307d784 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift @@ -0,0 +1,24 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct CredentialsManagerHasValidMethodHandler: MethodHandler { + enum Argument: String { + case minTtl + } + + let credentialsManager: CredentialsManager + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let minTTL = arguments[Argument.minTtl] as? Int else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.minTtl.rawValue))) + } + + // So it behaves the same as the Credentials Manager from Auth0.Android + callback(self.credentialsManager.canRenew() || self.credentialsManager.hasValid(minTTL: minTTL)) + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerModels.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerModels.swift new file mode 100644 index 000000000..390b11cb1 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerModels.swift @@ -0,0 +1,19 @@ +enum LocalAuthenticationProperty: String, CaseIterable { + case title + case cancelTitle + case fallbackTitle +} + +struct LocalAuthentication { + let title: String + let cancelTitle: String? + let fallbackTitle: String? + + static let key = "localAuthentication" + + init(from dictionary: [String: String?]) { + self.title = dictionary[LocalAuthenticationProperty.title] as? String ?? "Please authenticate to continue" + self.cancelTitle = dictionary[LocalAuthenticationProperty.cancelTitle] as? String + self.fallbackTitle = dictionary[LocalAuthenticationProperty.fallbackTitle] as? String + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerRenewMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerRenewMethodHandler.swift new file mode 100644 index 000000000..d0caced3d --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerRenewMethodHandler.swift @@ -0,0 +1,31 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct CredentialsManagerRenewMethodHandler: MethodHandler { + + enum Argument: String { + case parameters + } + + let credentialsManager: CredentialsManager + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + + guard let parameters = arguments[Argument.parameters] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + + self.credentialsManager.renew(parameters: parameters) { + switch $0 { + case let .success(credentials): callback(result(from: credentials)) + case let .failure(error): callback(FlutterError(from: error)) + } + } + } + +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerSaveMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerSaveMethodHandler.swift new file mode 100644 index 000000000..723a0d072 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerSaveMethodHandler.swift @@ -0,0 +1,24 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct CredentialsManagerSaveMethodHandler: MethodHandler { + enum Argument: String { + case credentials + } + + let credentialsManager: CredentialsManager + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let credentialsDictionary = arguments[Argument.credentials] as? [String: Any], + let credentials = Credentials(from: credentialsDictionary) else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.credentials.rawValue))) + } + + callback(self.credentialsManager.store(credentials: credentials)) + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift new file mode 100644 index 000000000..f09591825 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift @@ -0,0 +1,20 @@ + +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct CredentialsManagerUserInfoMethodHandler: MethodHandler { + let credentialsManager: CredentialsManager + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + if let user = credentialsManager.user { + callback(user.asDictionary()) + } else { + callback(nil) + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/SSOCredentialsMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/SSOCredentialsMethodHandler.swift new file mode 100644 index 000000000..8e6457183 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/CredentialsManager/SSOCredentialsMethodHandler.swift @@ -0,0 +1,44 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct SSOCredentialsMethodHandler: MethodHandler { + + enum Argument: String { + case parameters + case headers + } + + let credentialsManager: CredentialsManager + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let parameters = arguments[Argument.parameters] as? [String: String] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + guard let headers = arguments[Argument.headers] as? [String: String] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.headers.rawValue))) + } + + self.credentialsManager.ssoCredentials(parameters: parameters, headers: headers) { + switch $0 { + case let .success(ssoCredentials): + var response: [String: Any] = [ + "sessionTransferToken": ssoCredentials.sessionTransferToken, + "tokenType": ssoCredentials.issuedTokenType, + "expiresIn": Int(ssoCredentials.expiresIn.timeIntervalSinceNow) + ] + response["idToken"] = ssoCredentials.idToken + if let refreshToken = ssoCredentials.refreshToken { + response["refreshToken"] = refreshToken + } + callback(response) + case let .failure(error): callback(FlutterError(from: error)) + } + } + } + +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/DPoP/DPoPClearKeyMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/DPoP/DPoPClearKeyMethodHandler.swift new file mode 100644 index 000000000..88091de20 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/DPoP/DPoPClearKeyMethodHandler.swift @@ -0,0 +1,20 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct DPoPClearKeyMethodHandler: MethodHandler { + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + do { + try DPoP.clearKeypair() + callback(nil) + } catch { + callback(FlutterError(code: "CLEAR_DPOP_KEY_ERROR", + message: error.localizedDescription, + details: nil)) + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/DPoP/DPoPGetHeadersMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/DPoP/DPoPGetHeadersMethodHandler.swift new file mode 100644 index 000000000..6a796dfc6 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/DPoP/DPoPGetHeadersMethodHandler.swift @@ -0,0 +1,55 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct DPoPGetHeadersMethodHandler: MethodHandler { + enum Argument: String { + case url + case method + case accessToken + case tokenType + } + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let urlString = arguments[Argument.url] as? String, + let url = URL(string: urlString) else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.url.rawValue))) + } + guard let method = arguments[Argument.method] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.method.rawValue))) + } + guard let accessToken = arguments[Argument.accessToken] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.accessToken.rawValue))) + } + guard let tokenType = arguments[Argument.tokenType] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.tokenType.rawValue))) + } + + let nonce = arguments["nonce"] as? String + + var request = URLRequest(url: url) + request.httpMethod = method + + do { + try DPoP.addHeaders(to: &request, + accessToken: accessToken, + tokenType: tokenType, + nonce: nonce) + + let result: [String: String] = [ + "authorization": request.value(forHTTPHeaderField: "Authorization") ?? "\(tokenType) \(accessToken)", + "dpop": request.value(forHTTPHeaderField: "DPoP") ?? "" + ] + + callback(result) + } catch { + callback(FlutterError(code: "GET_DPOP_HEADERS_ERROR", + message: error.localizedDescription, + details: nil)) + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/DPoP/DPoPHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/DPoP/DPoPHandler.swift new file mode 100644 index 000000000..b9466cd16 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/DPoP/DPoPHandler.swift @@ -0,0 +1,50 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + + +public class DPoPHandler: NSObject, FlutterPlugin { + enum Method: String, CaseIterable { + case getDPoPHeaders = "dpop#getDPoPHeaders" + case clearDPoPKey = "dpop#clearDPoPKey" + } + + private static let channelName = "auth0.com/auth0_flutter/dpop" + + public static func register(with registrar: FlutterPluginRegistrar) { + let handler = DPoPHandler() + + #if os(iOS) + let channel = FlutterMethodChannel(name: DPoPHandler.channelName, + binaryMessenger: registrar.messenger()) + #else + let channel = FlutterMethodChannel(name: DPoPHandler.channelName, + binaryMessenger: registrar.messenger) + #endif + + registrar.addMethodCallDelegate(handler, channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + guard let arguments = call.arguments as? [String: Any] else { + return result(FlutterError(from: .argumentsMissing)) + } + guard let method = Method(rawValue: call.method) else { + return result(FlutterMethodNotImplemented) + } + + let methodHandler: MethodHandler + switch method { + case .getDPoPHeaders: + methodHandler = DPoPGetHeadersMethodHandler() + case .clearDPoPKey: + methodHandler = DPoPClearKeyMethodHandler() + } + + methodHandler.handle(with: arguments, callback: result) + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/Extensions.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/Extensions.swift new file mode 100644 index 000000000..c5c7b203e --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/Extensions.swift @@ -0,0 +1,145 @@ +import Auth0 +import JWTDecode + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +extension Array where Element == String { + var asSpaceSeparatedString: String { + return self.joined(separator: " ") + } +} + +extension Dictionary where Key == String { + subscript(_ key: K) -> Value? where K.RawValue == String { + get { + return self[key.rawValue] + } + set { + self[key.rawValue] = newValue + } + } +} + +extension Date { + static var iso8601Formatter: ISO8601DateFormatter { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + return formatter + } + + var asISO8601String: String { + return Date.iso8601Formatter.string(from: self) + } +} + +extension FlutterError { + convenience init(from handlerError: HandlerError) { + self.init(code: handlerError.code, message: handlerError.message, details: nil) + } +} + +extension Auth0Error { + var details: [String: Any] { + guard let cause = cause else { return [:] } + return ["cause": String(describing: cause)] + } +} + +extension Auth0APIError { + var details: [String: Any] { + var info = self.info + info.removeValue(forKey: "statusCode") + if let cause = cause { + info["cause"] = String(describing: cause) + } + return info + } +} + +extension Credentials { + convenience init?(from dictionary: [String: Any]) { + guard let accessToken = dictionary[CredentialsProperty.accessToken] as? String, + let idToken = dictionary[CredentialsProperty.idToken] as? String, + let expiresAt = dictionary[CredentialsProperty.expiresAt] as? String, + let expiresIn = Date.iso8601Formatter.date(from: expiresAt), + let scopes = dictionary[CredentialsProperty.scopes] as? [String], + let tokenType = dictionary[CredentialsProperty.tokenType] as? String else { + return nil + } + + self.init(accessToken: accessToken, + tokenType: tokenType, + idToken: idToken, + refreshToken: dictionary[CredentialsProperty.refreshToken] as? String, + expiresIn: expiresIn, + scope: scopes.isEmpty ? nil : scopes.asSpaceSeparatedString, + recoveryCode: nil) + } + + func asDictionary() throws -> [String: Any] { + let jwt = try decode(jwt: idToken) + var data: [String: Any] = [ + CredentialsProperty.accessToken.rawValue: accessToken, + CredentialsProperty.idToken.rawValue: idToken, + CredentialsProperty.expiresAt.rawValue: expiresIn.asISO8601String, + CredentialsProperty.scopes.rawValue: scope?.split(separator: " ").map(String.init) ?? [], + CredentialsProperty.userProfile.rawValue: UserInfo(json: jwt.body)?.asDictionary() ?? [:], + CredentialsProperty.tokenType.rawValue: tokenType + ] + data[CredentialsProperty.refreshToken] = refreshToken + return data + } +} + +extension APICredentials { + func asDictionary() -> [String: Any] { + return [ + "accessToken": accessToken, + "tokenType": tokenType, + "expiresAt": expiresIn.asISO8601String, + "scopes": scope.split(separator: " ").map(String.init) + ] + } +} + +extension UserInfo { + func asDictionary() -> [String: Any] { + let claimsToFilter = ["aud", + "iss", + "iat", + "exp", + "nbf", + "nonce", + "azp", + "auth_time", + "s_hash", + "at_hash", + "c_hash"] + var data: [String: Any] = [UserInfoProperty.sub.rawValue: sub] + data[UserInfoProperty.name] = name + data[UserInfoProperty.givenName] = givenName + data[UserInfoProperty.familyName] = familyName + data[UserInfoProperty.middleName] = middleName + data[UserInfoProperty.nickname] = nickname + data[UserInfoProperty.preferredUsername] = preferredUsername + data[UserInfoProperty.profile] = profile?.absoluteString + data[UserInfoProperty.picture] = picture?.absoluteString + data[UserInfoProperty.website] = website?.absoluteString + data[UserInfoProperty.email] = email + data[UserInfoProperty.emailVerified] = emailVerified + data[UserInfoProperty.gender] = gender + data[UserInfoProperty.birthdate] = birthdate + data[UserInfoProperty.zoneinfo] = zoneinfo?.identifier + data[UserInfoProperty.locale] = locale?.identifier + data[UserInfoProperty.phoneNumber] = phoneNumber + data[UserInfoProperty.phoneNumberVerified] = phoneNumberVerified + data[UserInfoProperty.address] = address + data[UserInfoProperty.updatedAt] = updatedAt?.asISO8601String + data[UserInfoProperty.customClaims] = customClaims?.filter { !claimsToFilter.contains($0.key) } + return data + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/HandlerError.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/HandlerError.swift new file mode 100644 index 000000000..0479a5caa --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/HandlerError.swift @@ -0,0 +1,28 @@ +enum HandlerError { + case argumentsMissing + case accountMissing + case userAgentMissing + case requiredArgumentMissing(String) + case idTokenDecodingFailed + + var code: String { + switch self { + case .argumentsMissing: return "SWIFT_ARGUMENTS_MISSING" + case .accountMissing: return "SWIFT_ACCOUNT_MISSING" + case .userAgentMissing: return "SWIFT_USER_AGENT_MISSING" + case .requiredArgumentMissing: return "SWIFT_REQUIRED_ARGUMENT_MISSING" + case .idTokenDecodingFailed: return "SWIFT_ID_TOKEN_DECODING_FAILED" + } + } + + var message: String { + switch self { + case .argumentsMissing: return "The arguments dictionary is missing or has the wrong type." + case .accountMissing: return "The account dictionary is missing or incomplete, or has the wrong type." + case .userAgentMissing: return "The userAgent dictionary is missing or incomplete, or has the wrong type." + case let .requiredArgumentMissing(argument): + return "The required argument '\(argument)' is missing or has the wrong type." + case .idTokenDecodingFailed: return "Unable to decode the ID Token." + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MethodHandler.swift new file mode 100644 index 000000000..8743c6b5b --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MethodHandler.swift @@ -0,0 +1,29 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +protocol MethodHandler { + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) +} + +extension MethodHandler { + func result(from credentials: Credentials) -> Any? { + do { + return try credentials.asDictionary() + } catch { + return FlutterError(from: .idTokenDecodingFailed) + } + } +} + +struct UnsupportedMethodHandler: MethodHandler { + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + callback(FlutterError(code: "UNSUPPORTED_PLATFORM", + message: "This method is not supported on this platform version.", + details: nil)) + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/Models.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/Models.swift new file mode 100644 index 000000000..900c36ca8 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/Models.swift @@ -0,0 +1,42 @@ +enum AccountProperty: String { + case clientId + case domain +} + +struct Account { + let clientId: String + let domain: String + + static let key = "_account" + + init?(from dictionary: [String: String]) { + guard let clientId = dictionary[AccountProperty.clientId], + let domain = dictionary[AccountProperty.domain] else { + return nil + } + + self.clientId = clientId + self.domain = domain + } +} + +enum UserAgentProperty: String { + case name + case version +} + +struct UserAgent { + let name: String + let version: String + + static let key = "_userAgent" + + init?(from dictionary: [String: String]) { + guard let name = dictionary[UserAgentProperty.name], let version = dictionary[UserAgentProperty.version] else { + return nil + } + + self.name = name + self.version = version + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift new file mode 100644 index 000000000..bb41c2ef0 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift @@ -0,0 +1,40 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct MyAccountConfirmEnrollmentMethodHandler: MethodHandler { + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let id = arguments["id"] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing("id"))) + } + guard let authSession = arguments["authSession"] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing("authSession"))) + } + + guard let factorType = arguments["factorType"] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing("factorType"))) + } + + let request: Request + if factorType == "push-notification" { + request = client.authenticationMethods.confirmPushNotificationEnrollment(id: id, authSession: authSession) + } else { + request = client.authenticationMethods.confirmRecoveryCodeEnrollment(id: id, authSession: authSession) + } + + request.start { + switch $0 { + case let .success(method): + callback(method.asDictionary()) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift new file mode 100644 index 000000000..b00656d0e --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift @@ -0,0 +1,29 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct MyAccountDeleteAuthMethodMethodHandler: MethodHandler { + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let id = arguments["id"] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing("id"))) + } + + client + .authenticationMethods + .deleteAuthenticationMethod(by: id) + .start { + switch $0 { + case .success: + callback(nil) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift new file mode 100644 index 000000000..54768136f --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift @@ -0,0 +1,29 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct MyAccountEnrollEmailMethodHandler: MethodHandler { + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let email = arguments["email"] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing("email"))) + } + + client + .authenticationMethods + .enrollEmail(emailAddress: email) + .start { + switch $0 { + case let .success(challenge): + callback(challenge.asDictionary()) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift new file mode 100644 index 000000000..12f2c3979 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift @@ -0,0 +1,39 @@ +#if PASSKEYS_PLATFORM +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +/// Requests a passkey enrollment challenge from the My Account API. This is the +/// first part of the enrollment flow; the app then presents the OS passkey +/// creation UI and finishes with `myAccount#enrollPasskey`. +@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) +struct MyAccountEnrollPasskeyChallengeMethodHandler: MethodHandler { + enum Argument: String { + case userIdentityId + case connection + } + + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + let userIdentityId = arguments[Argument.userIdentityId.rawValue] as? String + let connection = arguments[Argument.connection.rawValue] as? String + + client + .authenticationMethods + .passkeyEnrollmentChallenge(userIdentityId: userIdentityId, connection: connection) + .start { + switch $0 { + case let .success(challenge): + callback(challenge.asDictionary()) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} +#endif diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift new file mode 100644 index 000000000..8a908157a --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift @@ -0,0 +1,131 @@ +#if PASSKEYS_PLATFORM +import Auth0 +import AuthenticationServices + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +/// A ``NewPasskey`` reconstructed from a credential map supplied by the app +/// (for example, from `ASAuthorizationController`). +@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) +private struct ReconstructedNewPasskey: NewPasskey { + let credentialID: Data + let attachment: ASAuthorizationPublicKeyCredentialAttachment + let rawClientDataJSON: Data + let rawAttestationObject: Data? +} + +/// Enrolls an app-supplied passkey credential (a signup attestation) against a +/// previously obtained enrollment challenge via the My Account API. This is the +/// last part of the enrollment flow. This handler does not present any UI. +@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) +struct MyAccountEnrollPasskeyMethodHandler: MethodHandler { + enum Argument: String { + case challenge + case credential + } + + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let challengeMap = arguments[Argument.challenge.rawValue] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.challenge.rawValue))) + } + guard let credentialMap = arguments[Argument.credential.rawValue] as? [String: Any] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.credential.rawValue))) + } + + guard let challenge = Self.reconstructChallenge(from: challengeMap) else { + return callback(FlutterError(code: "PASSKEY_ERROR", + message: "Failed to reconstruct enrollment challenge", + details: nil)) + } + guard let passkey = Self.reconstructPasskey(from: credentialMap) else { + return callback(FlutterError(code: "PASSKEY_ERROR", + message: "Failed to reconstruct passkey credential", + details: nil)) + } + + client + .authenticationMethods + .enroll(passkey: passkey, challenge: challenge) + .start { + switch $0 { + case let .success(method): + callback(method.asDictionary()) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } + + // MARK: - Reconstruction + + private static func reconstructChallenge( + from challengeMap: [String: Any]) -> PasskeyEnrollmentChallenge? { + guard let authenticationMethodId = challengeMap["authenticationMethodId"] as? String, + let authSession = challengeMap["authSession"] as? String, + let authParamsPublicKey = challengeMap["authParamsPublicKey"] as? [String: Any], + let challengeString = authParamsPublicKey["challenge"] as? String, + let relyingPartyId = authParamsPublicKey["rpId"] as? String, + let userIdString = authParamsPublicKey["userId"] as? String, + let userName = authParamsPublicKey["userName"] as? String else { + return nil + } + + // `PasskeyEnrollmentChallenge`'s memberwise initializer is internal to + // Auth0.swift, so reconstruct it the way the SDK itself does: decode + // from the WebAuthn JSON with the authentication method id supplied via + // the `locationHeader` decoder userInfo key. + let challengeJson: [String: Any] = [ + "auth_session": authSession, + "authn_params_public_key": [ + "rp": ["id": relyingPartyId], + "user": ["id": userIdString, "name": userName], + "challenge": challengeString + ] + ] + + guard let jsonData = try? JSONSerialization.data(withJSONObject: challengeJson) else { + return nil + } + + let decoder = JSONDecoder() + // Matches Auth0.swift's internal `CodingUserInfoKey.locationHeaderKey`, + // whose raw value is "locationHeader". The decoder reads the last path + // component as the authentication method id. + if let locationHeaderKey = CodingUserInfoKey(rawValue: "locationHeader") { + decoder.userInfo[locationHeaderKey] = authenticationMethodId + } + return try? decoder.decode(PasskeyEnrollmentChallenge.self, from: jsonData) + } + + private static func reconstructPasskey( + from credentialMap: [String: Any]) -> NewPasskey? { + guard let credentialIdString = credentialMap["rawId"] as? String + ?? credentialMap["id"] as? String, + let credentialID = Data.fromBase64URLEncoded(credentialIdString), + let response = credentialMap["response"] as? [String: Any], + let clientDataString = response["clientDataJSON"] as? String, + let rawClientDataJSON = Data.fromBase64URLEncoded(clientDataString), + let attestationString = response["attestationObject"] as? String, + let rawAttestationObject = Data.fromBase64URLEncoded(attestationString) else { + return nil + } + + let attachment: ASAuthorizationPublicKeyCredentialAttachment = + (credentialMap["authenticatorAttachment"] as? String) == "crossPlatform" + ? .crossPlatform : .platform + + return ReconstructedNewPasskey( + credentialID: credentialID, + attachment: attachment, + rawClientDataJSON: rawClientDataJSON, + rawAttestationObject: rawAttestationObject + ) + } +} +#endif diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift new file mode 100644 index 000000000..815382645 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift @@ -0,0 +1,34 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct MyAccountEnrollPhoneMethodHandler: MethodHandler { + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let phoneNumber = arguments["phoneNumber"] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing("phoneNumber"))) + } + guard let typeString = arguments["type"] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing("type"))) + } + + let preferredMethod: PreferredAuthenticationMethod = typeString == "voice" ? .voice : .sms + + client + .authenticationMethods + .enrollPhone(phoneNumber: phoneNumber, preferredAuthenticationMethod: preferredMethod) + .start { + switch $0 { + case let .success(challenge): + callback(challenge.asDictionary()) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift new file mode 100644 index 000000000..0318e7814 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift @@ -0,0 +1,25 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct MyAccountEnrollPushMethodHandler: MethodHandler { + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + client + .authenticationMethods + .enrollPushNotification() + .start { + switch $0 { + case let .success(challenge): + callback(challenge.asDictionary()) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift new file mode 100644 index 000000000..0bbaefe50 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift @@ -0,0 +1,25 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct MyAccountEnrollRecoveryCodeMethodHandler: MethodHandler { + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + client + .authenticationMethods + .enrollRecoveryCode() + .start { + switch $0 { + case let .success(challenge): + callback(challenge.asDictionary()) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift new file mode 100644 index 000000000..307a3b31c --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift @@ -0,0 +1,25 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct MyAccountEnrollTotpMethodHandler: MethodHandler { + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + client + .authenticationMethods + .enrollTOTP() + .start { + switch $0 { + case let .success(challenge): + callback(challenge.asDictionary()) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountExtensions.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountExtensions.swift new file mode 100644 index 000000000..0f73e0391 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountExtensions.swift @@ -0,0 +1,151 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +extension FlutterError { + convenience init(from error: MyAccountError) { + let details: [String: Any] = [ + "_statusCode": error.statusCode, + "_title": error.title, + "_detail": error.detail, + "_errorFlags": [ + "isNetworkError": error.isNetworkError + ] + ] + self.init(code: error.code, + message: error.detail.isEmpty ? error.title : error.detail, + details: details) + } +} + +extension AuthenticationMethod { + func asDictionary() -> [String: Any?] { + return [ + "id": id, + "type": type, + "name": name, + "phone_number": phoneNumber, + "email": nil, + "totp_secret": nil, + "totp_uri": nil, + "preferred_authentication_method": preferredAuthenticationMethod, + "created_at": createdAt, + "last_auth_at": nil, + "confirmed": confirmed, + "usage": usage + ] + } +} + +extension PhoneEnrollmentChallenge { + func asDictionary() -> [String: Any?] { + return [ + "id": authenticationId, + "auth_session": authenticationSession, + "totp_secret": nil, + "totp_uri": nil, + "barcode_uri": nil, + "recovery_code": nil + ] + } +} + +extension EmailEnrollmentChallenge { + func asDictionary() -> [String: Any?] { + return [ + "id": authenticationId, + "auth_session": authenticationSession, + "totp_secret": nil, + "totp_uri": nil, + "barcode_uri": nil, + "recovery_code": nil + ] + } +} + +extension TOTPEnrollmentChallenge { + func asDictionary() -> [String: Any?] { + return [ + "id": authenticationId, + "auth_session": authenticationSession, + "totp_secret": authenticatorManualInputCode, + "totp_uri": authenticatorQRCodeURI, + "barcode_uri": authenticatorQRCodeURI, + "recovery_code": nil + ] + } +} + +extension PushEnrollmentChallenge { + func asDictionary() -> [String: Any?] { + return [ + "id": authenticationId, + "auth_session": authenticationSession, + "totp_secret": nil, + "totp_uri": nil, + "barcode_uri": authenticatorQRCodeURI, + "recovery_code": nil + ] + } +} + +extension RecoveryCodeEnrollmentChallenge { + func asDictionary() -> [String: Any?] { + return [ + "id": authenticationId, + "auth_session": authenticationSession, + "totp_secret": nil, + "totp_uri": nil, + "barcode_uri": nil, + "recovery_code": recoveryCode + ] + } +} + +#if PASSKEYS_PLATFORM +@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) +extension PasskeyEnrollmentChallenge { + func asDictionary() -> [String: Any?] { + // Forward the WebAuthn creation options in the flat shape the app's + // platform-authenticator ceremony consumes, plus the authentication + // method id needed to finish enrollment. + return [ + "authenticationMethodId": authenticationMethodId, + "authSession": authenticationSession, + "authParamsPublicKey": [ + "challenge": challengeData.base64URLEncodedString(), + "rpId": relyingPartyId, + "userId": userId.base64URLEncodedString(), + "userName": userName + ] + ] + } +} + +@available(iOS 16.6, macOS 13.5, visionOS 1.0, *) +extension PasskeyAuthenticationMethod { + func asDictionary() -> [String: Any?] { + let createdAtFormatter = ISO8601DateFormatter() + createdAtFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + + return [ + "id": id, + "type": type, + "identity_user_id": userIdentityId, + "user_agent": userAgent, + "key_id": credential.id, + "public_key": credential.publicKey.base64EncodedString(), + "user_handle": credential.userHandle.base64URLEncodedString(), + "credential_device_type": credential.deviceType.rawValue, + "credential_backed_up": credential.isBackedUp, + "aaguid": aaguid, + "relying_party_id": relyingPartyIdentifier, + "created_at": createdAtFormatter.string(from: createdAt) + ] + } +} +#endif diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift new file mode 100644 index 000000000..ac819216f --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift @@ -0,0 +1,29 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct MyAccountGetAuthMethodMethodHandler: MethodHandler { + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let id = arguments["id"] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing("id"))) + } + + client + .authenticationMethods + .getAuthenticationMethod(by: id) + .start { + switch $0 { + case let .success(method): + callback(method.asDictionary()) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift new file mode 100644 index 000000000..ccbd6dc55 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift @@ -0,0 +1,28 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct MyAccountGetAuthMethodsMethodHandler: MethodHandler { + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + let type = (arguments["type"] as? String) + .flatMap(AuthenticationMethodType.init(rawValue:)) + + client + .authenticationMethods + .getAuthenticationMethods(type: type) + .start { + switch $0 { + case let .success(methods): + callback(methods.map { $0.asDictionary() }) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift new file mode 100644 index 000000000..8f35c6ef5 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift @@ -0,0 +1,25 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct MyAccountGetFactorsMethodHandler: MethodHandler { + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + client + .authenticationMethods + .getFactors() + .start { + switch $0 { + case let .success(factors): + callback(factors.map { ["type": $0.type, "usage": $0.usage as Any] }) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountHandler.swift new file mode 100644 index 000000000..3371614c0 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountHandler.swift @@ -0,0 +1,111 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +typealias MyAccountClientProvider = (_ account: Account, _ userAgent: UserAgent, _ accessToken: String, _ useDPoP: Bool) -> MyAccount +typealias MyAccountMethodHandlerProvider = (_ method: MyAccountHandler.Method, _ client: MyAccount) -> MethodHandler + +public class MyAccountHandler: NSObject, FlutterPlugin { + enum Method: String, CaseIterable { + case getAuthenticationMethods = "myAccount#getAuthenticationMethods" + case getAuthenticationMethod = "myAccount#getAuthenticationMethod" + case deleteAuthenticationMethod = "myAccount#deleteAuthenticationMethod" + case getFactors = "myAccount#getFactors" + case enrollPasskeyChallenge = "myAccount#enrollPasskeyChallenge" + case enrollPasskey = "myAccount#enrollPasskey" + case enrollPhone = "myAccount#enrollPhone" + case enrollEmail = "myAccount#enrollEmail" + case enrollTotp = "myAccount#enrollTotp" + case enrollPush = "myAccount#enrollPush" + case enrollRecoveryCode = "myAccount#enrollRecoveryCode" + case verifyOtp = "myAccount#verifyOtp" + case confirmEnrollment = "myAccount#confirmEnrollment" + case updateAuthenticationMethod = "myAccount#updateAuthenticationMethod" + } + + private static let channelName = "auth0.com/auth0_flutter/my_account" + + public static func register(with registrar: FlutterPluginRegistrar) { + let handler = MyAccountHandler() + + #if os(iOS) + let channel = FlutterMethodChannel(name: MyAccountHandler.channelName, + binaryMessenger: registrar.messenger()) + #else + let channel = FlutterMethodChannel(name: MyAccountHandler.channelName, + binaryMessenger: registrar.messenger) + #endif + + registrar.addMethodCallDelegate(handler, channel: channel) + } + + var clientProvider: MyAccountClientProvider = { account, userAgent, accessToken, useDPoP in + var client = Auth0.myAccount(token: accessToken, domain: account.domain) + if useDPoP { + client = client.useDPoP() + } + return client + } + + var methodHandlerProvider: MyAccountMethodHandlerProvider = { method, client in + switch method { + case .getAuthenticationMethods: return MyAccountGetAuthMethodsMethodHandler(client: client) + case .getAuthenticationMethod: return MyAccountGetAuthMethodMethodHandler(client: client) + case .deleteAuthenticationMethod: return MyAccountDeleteAuthMethodMethodHandler(client: client) + case .getFactors: return MyAccountGetFactorsMethodHandler(client: client) + #if PASSKEYS_PLATFORM + case .enrollPasskeyChallenge: + if #available(iOS 16.6, macOS 13.5, visionOS 1.0, *) { + return MyAccountEnrollPasskeyChallengeMethodHandler(client: client) + } + return UnsupportedMethodHandler() + case .enrollPasskey: + if #available(iOS 16.6, macOS 13.5, visionOS 1.0, *) { + return MyAccountEnrollPasskeyMethodHandler(client: client) + } + return UnsupportedMethodHandler() + #else + case .enrollPasskeyChallenge, .enrollPasskey: + return UnsupportedMethodHandler() + #endif + case .enrollPhone: return MyAccountEnrollPhoneMethodHandler(client: client) + case .enrollEmail: return MyAccountEnrollEmailMethodHandler(client: client) + case .enrollTotp: return MyAccountEnrollTotpMethodHandler(client: client) + case .enrollPush: return MyAccountEnrollPushMethodHandler(client: client) + case .enrollRecoveryCode: return MyAccountEnrollRecoveryCodeMethodHandler(client: client) + case .verifyOtp: return MyAccountVerifyOtpMethodHandler(client: client) + case .confirmEnrollment: return MyAccountConfirmEnrollmentMethodHandler(client: client) + case .updateAuthenticationMethod: return MyAccountUpdateAuthMethodMethodHandler(client: client) + } + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + guard let arguments = call.arguments as? [String: Any] else { + return result(FlutterError(from: .argumentsMissing)) + } + guard let accountDictionary = arguments[Account.key] as? [String: String], + let account = Account(from: accountDictionary) else { + return result(FlutterError(from: .accountMissing)) + } + guard let userAgentDictionary = arguments[UserAgent.key] as? [String: String], + let userAgent = UserAgent(from: userAgentDictionary) else { + return result(FlutterError(from: .userAgentMissing)) + } + guard let method = Method(rawValue: call.method) else { + return result(FlutterMethodNotImplemented) + } + guard let accessToken = arguments["accessToken"] as? String else { + return result(FlutterError(from: .requiredArgumentMissing("accessToken"))) + } + + let useDPoP = arguments["useDPoP"] as? Bool ?? false + let client = clientProvider(account, userAgent, accessToken, useDPoP) + let methodHandler = methodHandlerProvider(method, client) + + methodHandler.handle(with: arguments, callback: result) + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift new file mode 100644 index 000000000..64389b8a8 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift @@ -0,0 +1,36 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct MyAccountUpdateAuthMethodMethodHandler: MethodHandler { + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let id = arguments["id"] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing("id"))) + } + + let name = arguments["name"] as? String + let preferredAuthenticationMethod = + (arguments["preferredAuthenticationMethod"] as? String) + .flatMap(PreferredAuthenticationMethod.init(rawValue:)) + + client + .authenticationMethods + .updateAuthenticationMethod(by: id, + name: name, + preferredAuthenticationMethod: preferredAuthenticationMethod) + .start { + switch $0 { + case let .success(method): + callback(method.asDictionary()) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift new file mode 100644 index 000000000..69ccbcf0c --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift @@ -0,0 +1,46 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct MyAccountVerifyOtpMethodHandler: MethodHandler { + let client: MyAccount + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let id = arguments["id"] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing("id"))) + } + guard let authSession = arguments["authSession"] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing("authSession"))) + } + guard let otp = arguments["otp"] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing("otp"))) + } + + guard let factorType = arguments["factorType"] as? String else { + return callback(FlutterError(from: .requiredArgumentMissing("factorType"))) + } + + let request: Request + switch factorType { + case "email": + request = client.authenticationMethods.confirmEmailEnrollment(id: id, authSession: authSession, otpCode: otp) + case "totp": + request = client.authenticationMethods.confirmTOTPEnrollment(id: id, authSession: authSession, otpCode: otp) + default: + request = client.authenticationMethods.confirmPhoneEnrollment(id: id, authSession: authSession, otpCode: otp) + } + + request.start { + switch $0 { + case let .success(method): + callback(method.asDictionary()) + case let .failure(error): + callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/Properties.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/Properties.swift new file mode 100644 index 000000000..a72a3658b --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/Properties.swift @@ -0,0 +1,41 @@ +enum CredentialsProperty: String, CaseIterable { + case accessToken + case idToken + case userProfile + case refreshToken + case expiresAt + case scopes + case tokenType +} + +enum SSOCredentialsProperty: String, CaseIterable { + case sessionTransferToken + case tokenType + case expiresIn + case idToken + case refreshToken +} + +enum UserInfoProperty: String, CaseIterable { + case sub + case name + case givenName = "given_name" + case familyName = "family_name" + case middleName = "middle_name" + case nickname + case preferredUsername = "preferred_username" + case profile + case picture + case website + case email + case emailVerified = "email_verified" + case gender + case birthdate + case zoneinfo + case locale + case phoneNumber = "phone_number" + case phoneNumberVerified = "phone_number_verified" + case address + case updatedAt = "updated_at" + case customClaims = "custom_claims" +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthExtensions.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthExtensions.swift new file mode 100644 index 000000000..6f706b998 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthExtensions.swift @@ -0,0 +1,29 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +extension FlutterError { + convenience init(from webAuthError: WebAuthError) { + var code: String + switch webAuthError { + case WebAuthError.noBundleIdentifier: code = "NO_BUNDLE_IDENTIFIER" + case WebAuthError.invalidInvitationURL: code = "INVALID_INVITATION_URL" + case WebAuthError.userCancelled: code = "USER_CANCELLED" + case WebAuthError.noAuthorizationCode: code = "NO_AUTHORIZATION_CODE" + case WebAuthError.pkceNotAllowed: code = "PKCE_NOT_ALLOWED" + case WebAuthError.idTokenValidationFailed: code = "ID_TOKEN_VALIDATION_FAILED" + case WebAuthError.transactionActiveAlready: code = "TRANSACTION_ACTIVE_ALREADY" + case WebAuthError.other: code = "OTHER" + default: code = "UNKNOWN" + } + var details = webAuthError.details + let isRetryable = (webAuthError.cause as? Auth0APIError)?.isRetryable ?? false + details["_isRetryable"] = isRetryable + self.init(code: code, message: String(describing: webAuthError), details: details) + } +} + diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthHandler.swift new file mode 100644 index 000000000..208ffd48e --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthHandler.swift @@ -0,0 +1,78 @@ +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +// MARK: - Providers + +typealias WebAuthClientProvider = (_ account: Account, _ userAgent: UserAgent) -> WebAuth +typealias WebAuthMethodHandlerProvider = (_ method: WebAuthHandler.Method, _ client: WebAuth) -> MethodHandler + +// MARK: - Web Auth Handler + +public class WebAuthHandler: NSObject, FlutterPlugin { + enum Method: String, CaseIterable { + case login = "webAuth#login" + case logout = "webAuth#logout" + } + + private static let channelName = "auth0.com/auth0_flutter/web_auth" + + public static func register(with registrar: FlutterPluginRegistrar) { + let handler = WebAuthHandler() + + #if os(iOS) + let channel = FlutterMethodChannel(name: WebAuthHandler.channelName, + binaryMessenger: registrar.messenger()) + #else + let channel = FlutterMethodChannel(name: WebAuthHandler.channelName, + binaryMessenger: registrar.messenger) + #endif + + registrar.addMethodCallDelegate(handler, channel: channel) + } + + var clientProvider: WebAuthClientProvider = { account, userAgent in + var client = Auth0.webAuth(clientId: account.clientId, domain: account.domain) + client.using(inLibrary: userAgent.name, version: userAgent.version) + return client + } + + var methodHandlerProvider: WebAuthMethodHandlerProvider = { method, client in + switch method { + case .login: return WebAuthLoginMethodHandler(client: client) + case .logout: return WebAuthLogoutMethodHandler(client: client) + } + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + + if call.method == "webAuth#cancel" { + WebAuthentication.cancel() + return + } + + guard let arguments = call.arguments as? [String: Any] else { + return result(FlutterError(from: .argumentsMissing)) + } + guard let accountDictionary = arguments[Account.key] as? [String: String], + let account = Account(from: accountDictionary) else { + return result(FlutterError(from: .accountMissing)) + } + guard let userAgentDictionary = arguments[UserAgent.key] as? [String: String], + let userAgent = UserAgent(from: userAgentDictionary) else { + return result(FlutterError(from: .userAgentMissing)) + } + guard let method = Method(rawValue: call.method) else { + return result(FlutterMethodNotImplemented) + } + + let client = clientProvider(account, userAgent) + let methodHandler = methodHandlerProvider(method, client) + + methodHandler.handle(with: arguments, callback: result) + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthLoginMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthLoginMethodHandler.swift new file mode 100644 index 000000000..b0898c8c4 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthLoginMethodHandler.swift @@ -0,0 +1,121 @@ +import Foundation +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +#if os(iOS) +typealias WebAuthProviderFunction = (UIModalPresentationStyle) -> WebAuthProvider +#endif + +struct WebAuthLoginMethodHandler: MethodHandler { + enum Argument: String { + case scopes + case parameters + case useHTTPS + case useEphemeralSession + case audience + case redirectUrl + case organizationId + case invitationUrl + case leeway + case useDPoP + case issuer + case maxAge + #if os(iOS) + case safariViewController + #endif + } + + let client: WebAuth + + #if os(iOS) + let safariProvider: WebAuthProviderFunction + + init(client: WebAuth, safariProvider: @escaping WebAuthProviderFunction = WebAuthentication.safariProvider) { + self.client = client + self.safariProvider = safariProvider + } + #else + init(client: WebAuth) { + self.client = client + } + #endif + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let useHTTPS = arguments[Argument.useHTTPS] as? Bool else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.useHTTPS.rawValue))) + } + guard let useEphemeralSession = arguments[Argument.useEphemeralSession] as? Bool else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.useEphemeralSession.rawValue))) + } + guard let scopes = arguments[Argument.scopes] as? [String] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.scopes.rawValue))) + } + guard let parameters = arguments[Argument.parameters] as? [String: String] else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.parameters.rawValue))) + } + + var webAuth = client + .scope(scopes.asSpaceSeparatedString) + .parameters(parameters) + + if useHTTPS { + webAuth = webAuth.useHTTPS() + } + + if useEphemeralSession { + webAuth = webAuth.useEphemeralSession() + } + + if let audience = arguments[Argument.audience] as? String { + webAuth = webAuth.audience(audience) + } + + if let redirectURL = arguments[Argument.redirectUrl] as? String, let url = URL(string: redirectURL) { + webAuth = webAuth.redirectURL(url) + } + + if let organizationId = arguments[Argument.organizationId] as? String { + webAuth = webAuth.organization(organizationId) + } + + if let invitationURL = arguments[Argument.invitationUrl] as? String, + let url = URL(string: invitationURL) { + webAuth = webAuth.invitationURL(url) + } + + if let leeway = arguments[Argument.leeway] as? Int { + webAuth = webAuth.leeway(leeway) + } + + if let issuer = arguments[Argument.issuer] as? String { + webAuth = webAuth.issuer(issuer) + } + + if let maxAge = arguments[Argument.maxAge] as? Int { + webAuth = webAuth.maxAge(maxAge) + } + + #if os(iOS) + if let safariViewControllerDictionary = arguments[SafariViewController.key] as? [String: Any?] { + let safariViewController = SafariViewController(from: safariViewControllerDictionary) + webAuth = webAuth.provider(self.safariProvider(safariViewController.presentationStyle)) + } + #endif + + if arguments[Argument.useDPoP.rawValue] as? Bool == true { + webAuth = webAuth.useDPoP() + } + + webAuth.start { + switch $0 { + case let .success(credentials): callback(result(from: credentials)) + case let .failure(error): callback(FlutterError(from: error)) + } + } + } +} \ No newline at end of file diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthLogoutMethodHandler.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthLogoutMethodHandler.swift new file mode 100644 index 000000000..af59de4e1 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthLogoutMethodHandler.swift @@ -0,0 +1,44 @@ +import Foundation +import Auth0 + +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + +struct WebAuthLogoutMethodHandler: MethodHandler { + enum Argument: String { + case useHTTPS + case returnTo + case federated // Add this + } + + let client: WebAuth + + func handle(with arguments: [String: Any], callback: @escaping FlutterResult) { + guard let useHTTPS = arguments[Argument.useHTTPS] as? Bool else { + return callback(FlutterError(from: .requiredArgumentMissing(Argument.useHTTPS.rawValue))) + } + + // Extract federated parameter, default to false if not provided + let federated = arguments[Argument.federated.rawValue] as? Bool ?? false + + var webAuth = client + + if useHTTPS { + webAuth = webAuth.useHTTPS() + } + + if let returnTo = arguments[Argument.returnTo] as? String, let url = URL(string: returnTo) { + webAuth = webAuth.redirectURL(url) + } + + webAuth.clearSession(federated: federated) { // Pass federated here + switch $0 { + case .success: callback(nil) + case let .failure(error): callback(FlutterError(from: error)) + } + } + } +} diff --git a/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthModels.swift b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthModels.swift new file mode 100644 index 000000000..58a64d003 --- /dev/null +++ b/auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter/WebAuth/WebAuthModels.swift @@ -0,0 +1,20 @@ +#if os(iOS) +import UIKit + +enum SafariViewControllerProperty: String, CaseIterable { + case presentationStyle +} + +struct SafariViewController { + var presentationStyle: UIModalPresentationStyle = UIModalPresentationStyle.fullScreen + + static let key = "safariViewController"; + + init(from dictionary: [String: Any?]) { + if let presentationStyle = dictionary[SafariViewControllerProperty.presentationStyle] as? Int, + let uiModalPresentationStyle = UIModalPresentationStyle(rawValue: presentationStyle) { + self.presentationStyle = uiModalPresentationStyle + } + } +} +#endif diff --git a/auth0_flutter/example/android/gradle.properties b/auth0_flutter/example/android/gradle.properties index 2d0b0d458..343c6caf4 100644 --- a/auth0_flutter/example/android/gradle.properties +++ b/auth0_flutter/example/android/gradle.properties @@ -1,4 +1,4 @@ -org.gradle.jvmargs=-Xmx1536M \ +org.gradle.jvmargs=-Xmx4G \ --add-exports=java.base/sun.nio.ch=ALL-UNNAMED \ --add-opens=java.base/java.lang=ALL-UNNAMED \ --add-opens=java.base/java.lang.reflect=ALL-UNNAMED \ diff --git a/auth0_flutter/example/ios/.gitignore b/auth0_flutter/example/ios/.gitignore index 7a7f9873a..27923469b 100644 --- a/auth0_flutter/example/ios/.gitignore +++ b/auth0_flutter/example/ios/.gitignore @@ -27,6 +27,9 @@ Flutter/flutter_export_environment.sh ServiceDefinitions.json Runner/GeneratedPluginRegistrant.* +# xcodebuild test result bundles (CI-generated artifacts) +*.xcresult/ + # Exceptions to above rules. !default.mode1v3 !default.mode2v3 diff --git a/auth0_flutter/example/ios/Gemfile b/auth0_flutter/example/ios/Gemfile deleted file mode 100644 index ac4948168..000000000 --- a/auth0_flutter/example/ios/Gemfile +++ /dev/null @@ -1,3 +0,0 @@ -source 'https://rubygems.org' - -gem 'slather' diff --git a/auth0_flutter/example/ios/Podfile b/auth0_flutter/example/ios/Podfile index 5657896c6..620e46eba 100644 --- a/auth0_flutter/example/ios/Podfile +++ b/auth0_flutter/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '14.0' +# platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -28,18 +28,12 @@ require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelpe flutter_ios_podfile_setup target 'Runner' do - platform :ios, '14.0' - use_frameworks! - use_modular_headers! flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do inherit! :search_paths end - - target 'RunnerUITests' end post_install do |installer| diff --git a/auth0_flutter/example/ios/Runner.xcodeproj/project.pbxproj b/auth0_flutter/example/ios/Runner.xcodeproj/project.pbxproj index 5793356ec..e74f399a0 100644 --- a/auth0_flutter/example/ios/Runner.xcodeproj/project.pbxproj +++ b/auth0_flutter/example/ios/Runner.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 06FCF69BF7F84D607295C71B /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C5483C34779CA72998DEA52 /* Pods_RunnerTests.framework */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 2D82163828F9A89300467FD1 /* AuthAPILoginWithOTPMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D82163728F9A89300467FD1 /* AuthAPILoginWithOTPMethodHandlerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; @@ -26,9 +27,6 @@ 5C4E65C5286D1CFB00141449 /* CredentialsManagerHasValidMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C4E65C4286D1CFB00141449 /* CredentialsManagerHasValidMethodHandlerTests.swift */; }; 5C4E65C7286D24A900141449 /* CredentialsManagerSaveMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C4E65C6286D24A900141449 /* CredentialsManagerSaveMethodHandlerTests.swift */; }; 5C4E65C9286D26D800141449 /* CredentialsManagerGetMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C4E65C8286D26D800141449 /* CredentialsManagerGetMethodHandlerTests.swift */; }; - A09B2E3F1D4C7891BA000002 /* CredentialsManagerSSOCredentialsMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A09B2E3F1D4C7891BA000001 /* CredentialsManagerSSOCredentialsMethodHandlerTests.swift */; }; - A0AC1D0F2E0000000000AC02 /* CredentialsManagerApiCredentialsMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AC1D0F2E0000000000AC01 /* CredentialsManagerApiCredentialsMethodHandlerTests.swift */; }; - A0AC1D0F2E0000000000AC04 /* CredentialsManagerClearApiCredentialsMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AC1D0F2E0000000000AC03 /* CredentialsManagerClearApiCredentialsMethodHandlerTests.swift */; }; 5C59DA6527FFCF0600365CDB /* AuthAPIHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C59DA6427FFCF0600365CDB /* AuthAPIHandlerTests.swift */; }; 5C59DA6727FFE75600365CDB /* AuthAPILoginUsernameOrEmailMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C59DA6627FFE75600365CDB /* AuthAPILoginUsernameOrEmailMethodHandlerTests.swift */; }; 5C59DA6928011D4F00365CDB /* AuthAPISignupMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C59DA6828011D4F00365CDB /* AuthAPISignupMethodHandlerTests.swift */; }; @@ -40,14 +38,16 @@ 5C59DA97280958FB00365CDB /* SmokeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C59DA96280958FB00365CDB /* SmokeTests.swift */; }; 5CA2853A29C14EBA008A06B8 /* AuthAPIMultifactorChallengeMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CA2853929C14EBA008A06B8 /* AuthAPIMultifactorChallengeMethodHandlerTests.swift */; }; 5CAAA4A2281A0C7D007666F1 /* ModelsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CAAA4A1281A0C7D007666F1 /* ModelsTests.swift */; }; - 6DAAFCA8609EA3C89D4C6CAC /* Pods_Runner_RunnerUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C8270E3F40357C2A1DB27BB8 /* Pods_Runner_RunnerUITests.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 9063679B5C726F419A174602 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63C12E1256775C12323CD98D /* Pods_RunnerTests.framework */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; + 82FCE04B4D34064CD03272F0 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22621E40BED0AB508F0967BC /* Pods_Runner.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; A09B2E3F1D4C7891BA000002 /* CredentialsManagerSSOCredentialsMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A09B2E3F1D4C7891BA000001 /* CredentialsManagerSSOCredentialsMethodHandlerTests.swift */; }; - A128A3E84540D9257B15491D /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03C97032096FE7868ACD2E52 /* Pods_Runner.framework */; }; + A0AC1D0F2E0000000000AC02 /* CredentialsManagerApiCredentialsMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AC1D0F2E0000000000AC01 /* CredentialsManagerApiCredentialsMethodHandlerTests.swift */; }; + A0AC1D0F2E0000000000AC04 /* CredentialsManagerClearApiCredentialsMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AC1D0F2E0000000000AC03 /* CredentialsManagerClearApiCredentialsMethodHandlerTests.swift */; }; + A1B2C3D42AECB46A00862998 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = A1B2C3D32AECB46A00862998 /* FlutterGeneratedPluginSwiftPackage */; }; B0CA00020000000000000001 /* MyAccountSpies.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA00010000000000000001 /* MyAccountSpies.swift */; }; B0CA00020000000000000002 /* MyAccountDeleteAuthMethodMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA00010000000000000002 /* MyAccountDeleteAuthMethodMethodHandlerTests.swift */; }; B0CA00020000000000000003 /* MyAccountEnrollEmailMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA00010000000000000003 /* MyAccountEnrollEmailMethodHandlerTests.swift */; }; @@ -100,14 +100,15 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 022D2524EC0626250560078D /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - 03C97032096FE7868ACD2E52 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0385195E6E4B40D5D2CAE9CF /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 15290EBC0E138D4CFE8691BF /* Pods-Runner-RunnerUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-RunnerUITests.debug.xcconfig"; path = "Target Support Files/Pods-Runner-RunnerUITests/Pods-Runner-RunnerUITests.debug.xcconfig"; sourceTree = ""; }; + 22621E40BED0AB508F0967BC /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2D82163728F9A89300467FD1 /* AuthAPILoginWithOTPMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPILoginWithOTPMethodHandlerTests.swift; sourceTree = ""; }; + 30E92729F56505552C6FEAB6 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 4548242A67B820DFE91ED1E6 /* Pods-Runner-RunnerUITests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-RunnerUITests.profile.xcconfig"; path = "Target Support Files/Pods-Runner-RunnerUITests/Pods-Runner-RunnerUITests.profile.xcconfig"; sourceTree = ""; }; + 3C5483C34779CA72998DEA52 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 50097CA0E4860ED2F61D15E4 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; 5C08DBC7288A7646000D2F37 /* CredentialsManagerExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialsManagerExtensionsTests.swift; sourceTree = ""; }; 5C328B4527F7822600451E70 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5C328B4727F7822600451E70 /* WebAuthHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebAuthHandlerTests.swift; sourceTree = ""; }; @@ -125,9 +126,6 @@ 5C4E65C4286D1CFB00141449 /* CredentialsManagerHasValidMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialsManagerHasValidMethodHandlerTests.swift; sourceTree = ""; }; 5C4E65C6286D24A900141449 /* CredentialsManagerSaveMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialsManagerSaveMethodHandlerTests.swift; sourceTree = ""; }; 5C4E65C8286D26D800141449 /* CredentialsManagerGetMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialsManagerGetMethodHandlerTests.swift; sourceTree = ""; }; - A09B2E3F1D4C7891BA000001 /* CredentialsManagerSSOCredentialsMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialsManagerSSOCredentialsMethodHandlerTests.swift; sourceTree = ""; }; - A0AC1D0F2E0000000000AC01 /* CredentialsManagerApiCredentialsMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialsManagerApiCredentialsMethodHandlerTests.swift; sourceTree = ""; }; - A0AC1D0F2E0000000000AC03 /* CredentialsManagerClearApiCredentialsMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialsManagerClearApiCredentialsMethodHandlerTests.swift; sourceTree = ""; }; 5C59DA6427FFCF0600365CDB /* AuthAPIHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPIHandlerTests.swift; sourceTree = ""; }; 5C59DA6627FFE75600365CDB /* AuthAPILoginUsernameOrEmailMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPILoginUsernameOrEmailMethodHandlerTests.swift; sourceTree = ""; }; 5C59DA6828011D4F00365CDB /* AuthAPISignupMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPISignupMethodHandlerTests.swift; sourceTree = ""; }; @@ -141,12 +139,12 @@ 5C5BFA8C2B96422A0078D945 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = ""; }; 5CA2853929C14EBA008A06B8 /* AuthAPIMultifactorChallengeMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPIMultifactorChallengeMethodHandlerTests.swift; sourceTree = ""; }; 5CAAA4A1281A0C7D007666F1 /* ModelsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelsTests.swift; sourceTree = ""; }; - 63C12E1256775C12323CD98D /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 784666492D4C4C64000A1A5F /* FlutterFramework */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterFramework; path = Flutter/ephemeral/Packages/.packages/FlutterFramework; sourceTree = ""; }; + 78DABEA22ED26510000E7860 /* auth0_flutter */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = auth0_flutter; path = ../../darwin/auth0_flutter; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 8296358B00146066F004BDD4 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - 95EAA98C7A171B7F08BB3510 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -154,12 +152,9 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 99BD47CB4C5EF89E894B6230 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - 9B5F0CE7EB2CCC504C7678ED /* Pods-Runner-RunnerUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-RunnerUITests.release.xcconfig"; path = "Target Support Files/Pods-Runner-RunnerUITests/Pods-Runner-RunnerUITests.release.xcconfig"; sourceTree = ""; }; A09B2E3F1D4C7891BA000001 /* CredentialsManagerSSOCredentialsMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialsManagerSSOCredentialsMethodHandlerTests.swift; sourceTree = ""; }; - C16443EA2BA08C71AE68B41B /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - C7412C9A0F502116EC6D51D0 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - C8270E3F40357C2A1DB27BB8 /* Pods_Runner_RunnerUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner_RunnerUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A0AC1D0F2E0000000000AC01 /* CredentialsManagerApiCredentialsMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialsManagerApiCredentialsMethodHandlerTests.swift; sourceTree = ""; }; + A0AC1D0F2E0000000000AC03 /* CredentialsManagerClearApiCredentialsMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialsManagerClearApiCredentialsMethodHandlerTests.swift; sourceTree = ""; }; B0CA00010000000000000001 /* MyAccountSpies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountSpies.swift; sourceTree = ""; }; B0CA00010000000000000002 /* MyAccountDeleteAuthMethodMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountDeleteAuthMethodMethodHandlerTests.swift; sourceTree = ""; }; B0CA00010000000000000003 /* MyAccountEnrollEmailMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountEnrollEmailMethodHandlerTests.swift; sourceTree = ""; }; @@ -175,6 +170,9 @@ B0CA0001000000000000000D /* MyAccountUpdateAuthMethodMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountUpdateAuthMethodMethodHandlerTests.swift; sourceTree = ""; }; B0CA0001000000000000000E /* MyAccountEnrollPasskeyChallengeMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountEnrollPasskeyChallengeMethodHandlerTests.swift; sourceTree = ""; }; B0CA0001000000000000000F /* MyAccountEnrollPasskeyMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountEnrollPasskeyMethodHandlerTests.swift; sourceTree = ""; }; + B53DC26EF5BF473819173843 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + ED10EF5476E15471E11081E4 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + F4387C1CC70C6144C6484B93 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; PK00000000000000000003 /* AuthAPIPasskeyLoginChallengeMethodHandlerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthAPIPasskeyLoginChallengeMethodHandlerTests.swift; sourceTree = ""; }; PK00000000000000000006 /* AuthAPIPasskeyExtensionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthAPIPasskeyExtensionsTests.swift; sourceTree = ""; }; PK10000000000000000003 /* AuthAPIPasskeySignupChallengeMethodHandlerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthAPIPasskeySignupChallengeMethodHandlerTests.swift; sourceTree = ""; }; @@ -186,7 +184,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9063679B5C726F419A174602 /* Pods_RunnerTests.framework in Frameworks */, + A1B2C3D42AECB46A00862998 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, + 06FCF69BF7F84D607295C71B /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -194,7 +193,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 6DAAFCA8609EA3C89D4C6CAC /* Pods_Runner_RunnerUITests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -202,19 +200,19 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A128A3E84540D9257B15491D /* Pods_Runner.framework in Frameworks */, + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, + 82FCE04B4D34064CD03272F0 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 0F723F8FF15DB736C737193B /* Frameworks */ = { + 580B3B91EC8E84DE36DB36EC /* Frameworks */ = { isa = PBXGroup; children = ( - 03C97032096FE7868ACD2E52 /* Pods_Runner.framework */, - C8270E3F40357C2A1DB27BB8 /* Pods_Runner_RunnerUITests.framework */, - 63C12E1256775C12323CD98D /* Pods_RunnerTests.framework */, + 22621E40BED0AB508F0967BC /* Pods_Runner.framework */, + 3C5483C34779CA72998DEA52 /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -293,9 +291,26 @@ path = UITests; sourceTree = ""; }; + 864738979C51BD93855BAF3A /* Pods */ = { + isa = PBXGroup; + children = ( + 0385195E6E4B40D5D2CAE9CF /* Pods-Runner.debug.xcconfig */, + 30E92729F56505552C6FEAB6 /* Pods-Runner.release.xcconfig */, + F4387C1CC70C6144C6484B93 /* Pods-Runner.profile.xcconfig */, + 50097CA0E4860ED2F61D15E4 /* Pods-RunnerTests.debug.xcconfig */, + B53DC26EF5BF473819173843 /* Pods-RunnerTests.release.xcconfig */, + ED10EF5476E15471E11081E4 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( + 78DABEA22ED26510000E7860 /* auth0_flutter */, + 784666492D4C4C64000A1A5F /* FlutterFramework */, + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, @@ -312,8 +327,8 @@ 5C328B4627F7822600451E70 /* Tests */, 5C59DA95280958FB00365CDB /* UITests */, 97C146EF1CF9000F007C117D /* Products */, - BA6CEC2369F1210E55591B7A /* Pods */, - 0F723F8FF15DB736C737193B /* Frameworks */, + 864738979C51BD93855BAF3A /* Pods */, + 580B3B91EC8E84DE36DB36EC /* Frameworks */, ); sourceTree = ""; }; @@ -343,22 +358,6 @@ path = Runner; sourceTree = ""; }; - BA6CEC2369F1210E55591B7A /* Pods */ = { - isa = PBXGroup; - children = ( - 99BD47CB4C5EF89E894B6230 /* Pods-Runner.debug.xcconfig */, - 8296358B00146066F004BDD4 /* Pods-Runner.release.xcconfig */, - C7412C9A0F502116EC6D51D0 /* Pods-Runner.profile.xcconfig */, - 15290EBC0E138D4CFE8691BF /* Pods-Runner-RunnerUITests.debug.xcconfig */, - 9B5F0CE7EB2CCC504C7678ED /* Pods-Runner-RunnerUITests.release.xcconfig */, - 4548242A67B820DFE91ED1E6 /* Pods-Runner-RunnerUITests.profile.xcconfig */, - 95EAA98C7A171B7F08BB3510 /* Pods-RunnerTests.debug.xcconfig */, - C16443EA2BA08C71AE68B41B /* Pods-RunnerTests.release.xcconfig */, - 022D2524EC0626250560078D /* Pods-RunnerTests.profile.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; B0CA000300000000000000A1 /* MyAccount */ = { isa = PBXGroup; children = ( @@ -388,7 +387,7 @@ isa = PBXNativeTarget; buildConfigurationList = 5C328B4E27F7822600451E70 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - 1A449D9969105E856D46DE8F /* [CP] Check Pods Manifest.lock */, + F3657A947D4D019FEC8C29B2 /* [CP] Check Pods Manifest.lock */, 5C328B4127F7822600451E70 /* Sources */, 5C328B4227F7822600451E70 /* Frameworks */, 5C328B4327F7822600451E70 /* Resources */, @@ -399,6 +398,9 @@ 5C328B4A27F7822600451E70 /* PBXTargetDependency */, ); name = RunnerTests; + packageProductDependencies = ( + A1B2C3D32AECB46A00862998 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Tests; productReference = 5C328B4527F7822600451E70 /* RunnerTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; @@ -407,11 +409,9 @@ isa = PBXNativeTarget; buildConfigurationList = 5C59DA9F280958FB00365CDB /* Build configuration list for PBXNativeTarget "RunnerUITests" */; buildPhases = ( - 81292840D1A9D2CDAE283D6F /* [CP] Check Pods Manifest.lock */, 5C59DA90280958FA00365CDB /* Sources */, 5C59DA91280958FA00365CDB /* Frameworks */, 5C59DA92280958FA00365CDB /* Resources */, - 951B8B461449D7B4FBBDC56A /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -427,20 +427,22 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 5CD19119BE250CBA8933F596 /* [CP] Check Pods Manifest.lock */, + 6CB688709F2751765277EB52 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - C562A93270F296E7E633658F /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( ); name = Runner; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Runner; productReference = 97C146EE1CF9000F007C117D /* Runner.app */; productType = "com.apple.product-type.application"; @@ -478,6 +480,9 @@ Base, ); mainGroup = 97C146E51CF9000F007C117D; + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; projectRoot = ""; @@ -518,28 +523,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 1A449D9969105E856D46DE8F /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -556,7 +539,7 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n"; }; - 5CD19119BE250CBA8933F596 /* [CP] Check Pods Manifest.lock */ = { + 6CB688709F2751765277EB52 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -578,45 +561,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 81292840D1A9D2CDAE283D6F /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-RunnerUITests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 951B8B461449D7B4FBBDC56A /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner-RunnerUITests/Pods-Runner-RunnerUITests-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner-RunnerUITests/Pods-Runner-RunnerUITests-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner-RunnerUITests/Pods-Runner-RunnerUITests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -632,21 +576,26 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; }; - C562A93270F296E7E633658F /* [CP] Embed Pods Frameworks */ = { + F3657A947D4D019FEC8C29B2 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - name = "[CP] Embed Pods Frameworks"; + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -818,7 +767,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 79ZXKC573P; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -846,7 +795,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 79ZXKC573P; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -860,7 +809,6 @@ SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/Runner"; }; name = Debug; }; @@ -876,7 +824,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 79ZXKC573P; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -887,7 +835,6 @@ SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/Runner"; }; name = Release; }; @@ -903,7 +850,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 79ZXKC573P; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -914,13 +861,11 @@ SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/Runner"; }; name = Profile; }; 5C59DA9C280958FB00365CDB /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 15290EBC0E138D4CFE8691BF /* Pods-Runner-RunnerUITests.debug.xcconfig */; buildSettings = { CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; @@ -930,7 +875,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 79ZXKC573P; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -950,7 +895,6 @@ }; 5C59DA9D280958FB00365CDB /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9B5F0CE7EB2CCC504C7678ED /* Pods-Runner-RunnerUITests.release.xcconfig */; buildSettings = { CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; @@ -960,7 +904,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 79ZXKC573P; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -977,7 +921,6 @@ }; 5C59DA9E280958FB00365CDB /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4548242A67B820DFE91ED1E6 /* Pods-Runner-RunnerUITests.profile.xcconfig */; buildSettings = { CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; @@ -987,7 +930,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 79ZXKC573P; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -1118,7 +1061,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 79ZXKC573P; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -1202,6 +1145,24 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; + A1B2C3D32AECB46A00862998 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 97C146E61CF9000F007C117D /* Project object */; } diff --git a/auth0_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/auth0_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..a2f52a521 --- /dev/null +++ b/auth0_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,32 @@ +{ + "pins" : [ + { + "identity" : "auth0.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/Auth0.swift", + "state" : { + "revision" : "b07565e7c859906815411d441a94e2c3c1f36085", + "version" : "2.22.0" + } + }, + { + "identity" : "jwtdecode.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/JWTDecode.swift", + "state" : { + "revision" : "36a5ce735a61c4bc119593f43ce2c027b4ca7392", + "version" : "3.3.0" + } + }, + { + "identity" : "simplekeychain", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/SimpleKeychain", + "state" : { + "revision" : "776c4a6db74d5c6c143974be91c383680d468630", + "version" : "1.3.0" + } + } + ], + "version" : 2 +} diff --git a/auth0_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/auth0_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 42f0dbb0c..d439f77a1 100644 --- a/auth0_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/auth0_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -5,6 +5,24 @@ + + + + + + + + + + Bool { - WebAuthentication.resume(with: url) - return super.application(application, open: url, options: options); - } } diff --git a/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPIExtensionsTests.swift b/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPIExtensionsTests.swift index c6ccb9a7e..283144119 100644 --- a/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPIExtensionsTests.swift +++ b/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPIExtensionsTests.swift @@ -1,6 +1,12 @@ import XCTest import Auth0 +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + @testable import auth0_flutter class AuthAPIExtensionsTests: XCTestCase { diff --git a/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPIHandlerTests.swift b/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPIHandlerTests.swift index 24d6d34ee..d76a6a273 100644 --- a/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPIHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPIHandlerTests.swift @@ -1,6 +1,12 @@ import XCTest import Auth0 +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + @testable import auth0_flutter class AuthAPIHandlerTests: XCTestCase { diff --git a/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandlerTests.swift index e7db3a60b..1cdfc2d75 100644 --- a/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandlerTests.swift @@ -4,6 +4,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + @available(iOS 16.6, macOS 13.5, visionOS 1.0, *) fileprivate typealias Argument = AuthAPIPasskeyCredentialExchangeMethodHandler.Argument diff --git a/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPISpies.swift b/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPISpies.swift index e46e669b9..4380599d4 100644 --- a/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPISpies.swift +++ b/auth0_flutter/example/ios/Tests/AuthAPI/AuthAPISpies.swift @@ -1,3 +1,4 @@ +import Foundation @testable import Auth0 fileprivate let mockCredentials = Credentials() diff --git a/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerExtensionsTests.swift b/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerExtensionsTests.swift index 3af6ade4e..938d6ed73 100644 --- a/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerExtensionsTests.swift +++ b/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerExtensionsTests.swift @@ -1,6 +1,12 @@ import XCTest import Auth0 +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + @testable import auth0_flutter class CredentialsManagerExtensionsTests: XCTestCase { diff --git a/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerGetMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerGetMethodHandlerTests.swift index 760907e8d..9891c4a9d 100644 --- a/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerGetMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerGetMethodHandlerTests.swift @@ -8,12 +8,13 @@ fileprivate typealias Argument = CredentialsManagerGetMethodHandler.Argument class CredentialsManagerGetMethodHandlerTests: XCTestCase { var spyAuthentication: SpyAuthentication! var spyStorage: SpyCredentialsStorage! + var credentialsManager: CredentialsManager! var sut: CredentialsManagerGetMethodHandler! override func setUpWithError() throws { spyAuthentication = SpyAuthentication() spyStorage = SpyCredentialsStorage() - let credentialsManager = CredentialsManager(authentication: spyAuthentication, storage: spyStorage) + credentialsManager = CredentialsManager(authentication: spyAuthentication, storage: spyStorage) sut = CredentialsManagerGetMethodHandler(credentialsManager: credentialsManager) } } @@ -48,9 +49,8 @@ extension CredentialsManagerGetMethodHandlerTests { refreshToken: "refreshToken", expiresIn: Date(timeIntervalSinceNow: -3600), scope: "foo bar") - let data = try? NSKeyedArchiver.archivedData(withRootObject: credentials, requiringSecureCoding: true) let expectation = self.expectation(description: "Produced credentials") - spyStorage.getEntryReturnValue = data + _ = credentialsManager.store(credentials: credentials) sut.handle(with: arguments(withKey: Argument.scopes, value: value)) { _ in XCTAssertEqual(self.spyAuthentication.arguments["scope"] as? String, value.asSpaceSeparatedString) expectation.fulfill() @@ -65,9 +65,8 @@ extension CredentialsManagerGetMethodHandlerTests { refreshToken: "refreshToken", expiresIn: Date(timeIntervalSinceNow: -3600), scope: "foo bar") - let data = try? NSKeyedArchiver.archivedData(withRootObject: credentials, requiringSecureCoding: true) let expectation = self.expectation(description: "Produced credentials") - spyStorage.getEntryReturnValue = data + _ = credentialsManager.store(credentials: credentials) sut.handle(with: arguments(withKey: Argument.scopes, value: [])) { _ in XCTAssertNil(self.spyAuthentication.arguments["scope"] as? String) expectation.fulfill() @@ -95,9 +94,8 @@ extension CredentialsManagerGetMethodHandlerTests { refreshToken: "refreshToken", expiresIn: Date(timeIntervalSinceNow: 3600), scope: "foo bar") - let data = try? NSKeyedArchiver.archivedData(withRootObject: credentials, requiringSecureCoding: true) let expectation = self.expectation(description: "Produced credentials") - spyStorage.getEntryReturnValue = data + _ = credentialsManager.store(credentials: credentials) sut.handle(with: arguments()) { result in assert(result: result, has: CredentialsProperty.allCases) expectation.fulfill() diff --git a/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerHandlerTests.swift b/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerHandlerTests.swift index 9ef09a77d..0cb320f2d 100644 --- a/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerHandlerTests.swift @@ -1,5 +1,11 @@ import XCTest +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + @testable import Auth0 @testable import auth0_flutter diff --git a/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerHasValidMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerHasValidMethodHandlerTests.swift index d98fade39..ce9b0d6bc 100644 --- a/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerHasValidMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerHasValidMethodHandlerTests.swift @@ -7,11 +7,12 @@ fileprivate typealias Argument = CredentialsManagerHasValidMethodHandler.Argumen class CredentialsManagerHasValidMethodHandlerTests: XCTestCase { var spy: SpyCredentialsStorage! + var credentialsManager: CredentialsManager! var sut: CredentialsManagerHasValidMethodHandler! override func setUpWithError() throws { spy = SpyCredentialsStorage() - let credentialsManager = CredentialsManager(authentication: SpyAuthentication(), storage: spy) + credentialsManager = CredentialsManager(authentication: SpyAuthentication(), storage: spy) sut = CredentialsManagerHasValidMethodHandler(credentialsManager: credentialsManager) } } @@ -40,9 +41,8 @@ extension CredentialsManagerHasValidMethodHandlerTests { func testProducesTrueWithValidCredentialsAndNoRefreshToken() { let credentials = Credentials(refreshToken: nil, expiresIn: Date(timeIntervalSinceNow: 3600)) - let data = try? NSKeyedArchiver.archivedData(withRootObject: credentials, requiringSecureCoding: true) let expectation = self.expectation(description: "Produced true") - spy.getEntryReturnValue = data + _ = credentialsManager.store(credentials: credentials) sut.handle(with: arguments()) { result in XCTAssertEqual(result as? Bool, true) expectation.fulfill() @@ -52,11 +52,8 @@ extension CredentialsManagerHasValidMethodHandlerTests { func testProducesTrueWithRefreshTokenAndInvalidCredentials() { let credentials = Credentials(refreshToken: "foo", expiresIn: Date(timeIntervalSinceNow: -3600)) - let data = try? NSKeyedArchiver.archivedData(withRootObject: credentials, requiringSecureCoding: true) let expectation = self.expectation(description: "Produced true") - let credentialsManager = CredentialsManager(authentication: SpyAuthentication(), storage: spy) - sut = CredentialsManagerHasValidMethodHandler(credentialsManager: credentialsManager) - spy.getEntryReturnValue = data + _ = credentialsManager.store(credentials: credentials) sut.handle(with: arguments()) { result in XCTAssertEqual(result as? Bool, true) expectation.fulfill() @@ -66,11 +63,8 @@ extension CredentialsManagerHasValidMethodHandlerTests { func testProducesTrueWithRefreshTokenAndValidCredentials() { let credentials = Credentials(refreshToken: "foo", expiresIn: Date(timeIntervalSinceNow: 3600)) - let data = try? NSKeyedArchiver.archivedData(withRootObject: credentials, requiringSecureCoding: true) let expectation = self.expectation(description: "Produced true") - let credentialsManager = CredentialsManager(authentication: SpyAuthentication(), storage: spy) - sut = CredentialsManagerHasValidMethodHandler(credentialsManager: credentialsManager) - spy.getEntryReturnValue = data + _ = credentialsManager.store(credentials: credentials) sut.handle(with: arguments()) { result in XCTAssertEqual(result as? Bool, true) expectation.fulfill() @@ -90,9 +84,8 @@ extension CredentialsManagerHasValidMethodHandlerTests { func testProducesFalseWithInvalidCredentialsAndNoRefreshToken() { let credentials = Credentials(refreshToken: nil, expiresIn: Date(timeIntervalSinceNow: -3600)) - let data = try? NSKeyedArchiver.archivedData(withRootObject: credentials, requiringSecureCoding: true) let expectation = self.expectation(description: "Produced false") - spy.getEntryReturnValue = data + _ = credentialsManager.store(credentials: credentials) sut.handle(with: arguments()) { result in XCTAssertEqual(result as? Bool, false) expectation.fulfill() diff --git a/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerSSOCredentialsMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerSSOCredentialsMethodHandlerTests.swift index f0a614a68..96062c72a 100644 --- a/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerSSOCredentialsMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerSSOCredentialsMethodHandlerTests.swift @@ -8,12 +8,13 @@ fileprivate typealias Argument = SSOCredentialsMethodHandler.Argument final class SSOCredentialsMethodHandlerTests: XCTestCase { var spyAuthentication: SpyAuthentication! var spyStorage: SpyCredentialsStorage! + var credentialsManager: CredentialsManager! var sut: SSOCredentialsMethodHandler! override func setUpWithError() throws { spyAuthentication = SpyAuthentication() spyStorage = SpyCredentialsStorage() - let credentialsManager = CredentialsManager(authentication: spyAuthentication, storage: spyStorage) + credentialsManager = CredentialsManager(authentication: spyAuthentication, storage: spyStorage) sut = SSOCredentialsMethodHandler(credentialsManager: credentialsManager) } } @@ -44,9 +45,8 @@ extension SSOCredentialsMethodHandlerTests { refreshToken: "refreshToken", expiresIn: Date(timeIntervalSinceNow: 3600), scope: "scope") - let data = try? NSKeyedArchiver.archivedData(withRootObject: credentials, requiringSecureCoding: true) let expectation = self.expectation(description: "SSO exchange was called") - spyStorage.getEntryReturnValue = data + _ = credentialsManager.store(credentials: credentials) sut.handle(with: arguments()) { _ in XCTAssertEqual(self.spyAuthentication.arguments["refreshToken"] as? String, "refreshToken") expectation.fulfill() @@ -61,9 +61,8 @@ extension SSOCredentialsMethodHandlerTests { refreshToken: "refreshToken", expiresIn: Date(timeIntervalSinceNow: 3600), scope: "scope") - let data = try? NSKeyedArchiver.archivedData(withRootObject: credentials, requiringSecureCoding: true) let expectation = self.expectation(description: "Produced SSO credentials") - spyStorage.getEntryReturnValue = data + _ = credentialsManager.store(credentials: credentials) sut.handle(with: arguments()) { result in let expectedKeys: [SSOCredentialsProperty] = [ .sessionTransferToken, .tokenType, .expiresIn, .idToken diff --git a/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerSpies.swift b/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerSpies.swift index ded4867a6..d8cf84755 100644 --- a/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerSpies.swift +++ b/auth0_flutter/example/ios/Tests/CredentialsManager/CredentialsManagerSpies.swift @@ -1,3 +1,4 @@ +import Foundation import Auth0 // MARK: - Auth0.swift Spies @@ -18,6 +19,7 @@ class SpyCredentialsStorage: CredentialsStorage { func setEntry(_ data: Data, forKey key: String) -> Bool { self.calledSetEntry = true + self.getEntryReturnValue = data return self.setEntryReturnValue } diff --git a/auth0_flutter/example/ios/Tests/Mocks.swift b/auth0_flutter/example/ios/Tests/Mocks.swift index 98c7ff565..736ef2396 100644 --- a/auth0_flutter/example/ios/Tests/Mocks.swift +++ b/auth0_flutter/example/ios/Tests/Mocks.swift @@ -113,7 +113,8 @@ class SpyPluginRegistrar: NSObject, FlutterPluginRegistrar { } func addApplicationDelegate(_ delegate: FlutterPlugin) {} - func addSceneDelegate(_ delegate: any FlutterSceneLifeCycleDelegate) {} + + func addSceneDelegate(_ delegate: FlutterSceneLifeCycleDelegate) {} func register(_ factory: FlutterPlatformViewFactory, withId: String, diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountConfirmEnrollmentMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountConfirmEnrollmentMethodHandlerTests.swift index ab6bf1662..5a9e501f5 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountConfirmEnrollmentMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountConfirmEnrollmentMethodHandlerTests.swift @@ -3,6 +3,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + class MyAccountConfirmEnrollmentMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! var sut: MyAccountConfirmEnrollmentMethodHandler! diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountDeleteAuthMethodMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountDeleteAuthMethodMethodHandlerTests.swift index d7419a54b..54d5a6854 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountDeleteAuthMethodMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountDeleteAuthMethodMethodHandlerTests.swift @@ -3,6 +3,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + class MyAccountDeleteAuthMethodMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! var sut: MyAccountDeleteAuthMethodMethodHandler! diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollEmailMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollEmailMethodHandlerTests.swift index d3748fcee..cb66b4241 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollEmailMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollEmailMethodHandlerTests.swift @@ -3,6 +3,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + class MyAccountEnrollEmailMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! var sut: MyAccountEnrollEmailMethodHandler! diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPasskeyChallengeMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPasskeyChallengeMethodHandlerTests.swift index bcc5b3d98..e82f594ba 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPasskeyChallengeMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPasskeyChallengeMethodHandlerTests.swift @@ -4,6 +4,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + @available(iOS 16.6, macOS 13.5, visionOS 1.0, *) class MyAccountEnrollPasskeyChallengeMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPasskeyMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPasskeyMethodHandlerTests.swift index 43aa3ba17..052e9fe06 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPasskeyMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPasskeyMethodHandlerTests.swift @@ -4,6 +4,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + @available(iOS 16.6, macOS 13.5, visionOS 1.0, *) class MyAccountEnrollPasskeyMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPhoneMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPhoneMethodHandlerTests.swift index 710603137..af707f2fa 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPhoneMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPhoneMethodHandlerTests.swift @@ -3,6 +3,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + class MyAccountEnrollPhoneMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! var sut: MyAccountEnrollPhoneMethodHandler! diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPushMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPushMethodHandlerTests.swift index 8b8135207..509aff9bc 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPushMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollPushMethodHandlerTests.swift @@ -3,6 +3,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + class MyAccountEnrollPushMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! var sut: MyAccountEnrollPushMethodHandler! diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollRecoveryCodeMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollRecoveryCodeMethodHandlerTests.swift index 7fb40d948..547815f9f 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollRecoveryCodeMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollRecoveryCodeMethodHandlerTests.swift @@ -3,6 +3,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + class MyAccountEnrollRecoveryCodeMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! var sut: MyAccountEnrollRecoveryCodeMethodHandler! diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollTotpMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollTotpMethodHandlerTests.swift index 162c85eec..773f9790a 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollTotpMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountEnrollTotpMethodHandlerTests.swift @@ -3,6 +3,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + class MyAccountEnrollTotpMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! var sut: MyAccountEnrollTotpMethodHandler! diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountGetAuthMethodMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountGetAuthMethodMethodHandlerTests.swift index 4f588fab7..ac90ea97f 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountGetAuthMethodMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountGetAuthMethodMethodHandlerTests.swift @@ -3,6 +3,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + class MyAccountGetAuthMethodMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! var sut: MyAccountGetAuthMethodMethodHandler! diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountGetAuthMethodsMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountGetAuthMethodsMethodHandlerTests.swift index 18932d5f2..274a000d5 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountGetAuthMethodsMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountGetAuthMethodsMethodHandlerTests.swift @@ -3,6 +3,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + class MyAccountGetAuthMethodsMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! var sut: MyAccountGetAuthMethodsMethodHandler! diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountGetFactorsMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountGetFactorsMethodHandlerTests.swift index f11db76c4..36e3a8a86 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountGetFactorsMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountGetFactorsMethodHandlerTests.swift @@ -3,6 +3,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + class MyAccountGetFactorsMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! var sut: MyAccountGetFactorsMethodHandler! diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountUpdateAuthMethodMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountUpdateAuthMethodMethodHandlerTests.swift index cea4852c3..635d5a127 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountUpdateAuthMethodMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountUpdateAuthMethodMethodHandlerTests.swift @@ -3,6 +3,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + class MyAccountUpdateAuthMethodMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! var sut: MyAccountUpdateAuthMethodMethodHandler! diff --git a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountVerifyOtpMethodHandlerTests.swift b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountVerifyOtpMethodHandlerTests.swift index 67de52498..6289cbd13 100644 --- a/auth0_flutter/example/ios/Tests/MyAccount/MyAccountVerifyOtpMethodHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/MyAccount/MyAccountVerifyOtpMethodHandlerTests.swift @@ -3,6 +3,12 @@ import Auth0 @testable import auth0_flutter +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + class MyAccountVerifyOtpMethodHandlerTests: XCTestCase { var spy: SpyMyAccountAuthenticationMethods! var sut: MyAccountVerifyOtpMethodHandler! diff --git a/auth0_flutter/example/ios/Tests/SwiftAuth0FlutterPluginTests.swift b/auth0_flutter/example/ios/Tests/SwiftAuth0FlutterPluginTests.swift index e75576b11..b848edb85 100644 --- a/auth0_flutter/example/ios/Tests/SwiftAuth0FlutterPluginTests.swift +++ b/auth0_flutter/example/ios/Tests/SwiftAuth0FlutterPluginTests.swift @@ -2,8 +2,8 @@ import XCTest @testable import auth0_flutter -class SwiftAuth0FlutterPluginTests: XCTestCase { - let sut = SwiftAuth0FlutterPlugin.self +class Auth0FlutterPluginTests: XCTestCase { + let sut = Auth0FlutterPlugin.self override func setUpWithError() throws { SpyFlutterPlugin.calledRegister = false @@ -12,7 +12,7 @@ class SwiftAuth0FlutterPluginTests: XCTestCase { // MARK: - Handler Registration -extension SwiftAuth0FlutterPluginTests { +extension Auth0FlutterPluginTests { func testRegistersWebAuthHandler() { sut.handlers = [SpyFlutterPlugin.self] sut.register(with: SpyPluginRegistrar()) diff --git a/auth0_flutter/example/ios/Tests/WebAuth/WebAuthExtensionsTests.swift b/auth0_flutter/example/ios/Tests/WebAuth/WebAuthExtensionsTests.swift index 4bef3c43c..f051792f0 100644 --- a/auth0_flutter/example/ios/Tests/WebAuth/WebAuthExtensionsTests.swift +++ b/auth0_flutter/example/ios/Tests/WebAuth/WebAuthExtensionsTests.swift @@ -1,6 +1,12 @@ import XCTest import Auth0 +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + @testable import auth0_flutter class WebAuthExtensionsTests: XCTestCase { diff --git a/auth0_flutter/example/ios/Tests/WebAuth/WebAuthHandlerTests.swift b/auth0_flutter/example/ios/Tests/WebAuth/WebAuthHandlerTests.swift index 8dc427b1f..43493ff56 100644 --- a/auth0_flutter/example/ios/Tests/WebAuth/WebAuthHandlerTests.swift +++ b/auth0_flutter/example/ios/Tests/WebAuth/WebAuthHandlerTests.swift @@ -1,6 +1,12 @@ import XCTest import Auth0 +#if os(iOS) +import Flutter +#else +import FlutterMacOS +#endif + @testable import auth0_flutter class WebAuthHandlerTests: XCTestCase { diff --git a/auth0_flutter/example/lib/example_app.dart b/auth0_flutter/example/lib/example_app.dart index 24f4aec72..4ac16cad3 100644 --- a/auth0_flutter/example/lib/example_app.dart +++ b/auth0_flutter/example/lib/example_app.dart @@ -61,7 +61,6 @@ class _ExampleAppState extends State { appCustomURL: 'auth0flutter://callback', authTimeout: const Duration(minutes: 5), ); - setState(() { _isLoggedIn = true; }); diff --git a/auth0_flutter/example/macos/.gitignore b/auth0_flutter/example/macos/.gitignore index 746adbb6b..188e2b9b6 100644 --- a/auth0_flutter/example/macos/.gitignore +++ b/auth0_flutter/example/macos/.gitignore @@ -5,3 +5,6 @@ # Xcode-related **/dgph **/xcuserdata/ + +# xcodebuild test result bundles (CI-generated artifacts) +*.xcresult/ diff --git a/auth0_flutter/example/macos/Podfile b/auth0_flutter/example/macos/Podfile index 7febb8001..ff5ddb3b8 100644 --- a/auth0_flutter/example/macos/Podfile +++ b/auth0_flutter/example/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '11.0' +platform :osx, '10.15' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -28,18 +28,11 @@ flutter_macos_podfile_setup target 'Runner' do use_frameworks! - use_modular_headers! flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do inherit! :search_paths end - - target 'RunnerUITests' do - inherit! :search_paths - flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) - end end post_install do |installer| diff --git a/auth0_flutter/example/macos/Runner.xcodeproj/project.pbxproj b/auth0_flutter/example/macos/Runner.xcodeproj/project.pbxproj index c198857b6..1086c3468 100644 --- a/auth0_flutter/example/macos/Runner.xcodeproj/project.pbxproj +++ b/auth0_flutter/example/macos/Runner.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 0103B7EA1132AC95205851B1 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42E90A8B7E56466926079940 /* Pods_Runner.framework */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; @@ -54,9 +55,31 @@ 5C13993C2B0EB5F3006DCE54 /* CredentialsManagerGetMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C1399212B0EB5F3006DCE54 /* CredentialsManagerGetMethodHandlerTests.swift */; }; 5C13993D2B0EB5F3006DCE54 /* CredentialsManagerHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C1399222B0EB5F3006DCE54 /* CredentialsManagerHandlerTests.swift */; }; 5CD8A5622B117A9900313321 /* SmokeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CD8A5612B117A9900313321 /* SmokeTests.swift */; }; - B7435027FDBEB9426DE3F945 /* Pods_RunnerUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 506E34AA72DE3EE89DA59AF3 /* Pods_RunnerUITests.framework */; }; - BED01AE0EC3CF9FFA874824D /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B73B6AA0238923E7DDDBEA3B /* Pods_RunnerTests.framework */; }; - C674941AB11928E11BF9C473 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B4109D16F63E569418468A57 /* Pods_Runner.framework */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; + 853B294B9A67C603C2508DFE /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6FD903E99CB6C89165AACEDF /* Pods_RunnerTests.framework */; }; + A09B2E3F1D4C7891BA000011 /* CredentialsManagerSSOCredentialsMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A09B2E3F1D4C7891BA000010 /* CredentialsManagerSSOCredentialsMethodHandlerTests.swift */; }; + A0AC1D0F2E0000000000AC12 /* CredentialsManagerApiCredentialsMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AC1D0F2E0000000000AC11 /* CredentialsManagerApiCredentialsMethodHandlerTests.swift */; }; + A0AC1D0F2E0000000000AC14 /* CredentialsManagerClearApiCredentialsMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AC1D0F2E0000000000AC13 /* CredentialsManagerClearApiCredentialsMethodHandlerTests.swift */; }; + B0CA00020000000000000101 /* MyAccountSpies.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA00010000000000000101 /* MyAccountSpies.swift */; }; + B0CA00020000000000000102 /* MyAccountDeleteAuthMethodMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA00010000000000000102 /* MyAccountDeleteAuthMethodMethodHandlerTests.swift */; }; + B0CA00020000000000000103 /* MyAccountEnrollEmailMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA00010000000000000103 /* MyAccountEnrollEmailMethodHandlerTests.swift */; }; + B0CA00020000000000000104 /* MyAccountEnrollPhoneMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA00010000000000000104 /* MyAccountEnrollPhoneMethodHandlerTests.swift */; }; + B0CA00020000000000000105 /* MyAccountEnrollPushMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA00010000000000000105 /* MyAccountEnrollPushMethodHandlerTests.swift */; }; + B0CA00020000000000000106 /* MyAccountEnrollRecoveryCodeMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA00010000000000000106 /* MyAccountEnrollRecoveryCodeMethodHandlerTests.swift */; }; + B0CA00020000000000000107 /* MyAccountEnrollTotpMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA00010000000000000107 /* MyAccountEnrollTotpMethodHandlerTests.swift */; }; + B0CA00020000000000000108 /* MyAccountGetAuthMethodMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA00010000000000000108 /* MyAccountGetAuthMethodMethodHandlerTests.swift */; }; + B0CA00020000000000000109 /* MyAccountGetAuthMethodsMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA00010000000000000109 /* MyAccountGetAuthMethodsMethodHandlerTests.swift */; }; + B0CA0002000000000000010A /* MyAccountGetFactorsMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA0001000000000000010A /* MyAccountGetFactorsMethodHandlerTests.swift */; }; + B0CA0002000000000000010B /* MyAccountVerifyOtpMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA0001000000000000010B /* MyAccountVerifyOtpMethodHandlerTests.swift */; }; + B0CA0002000000000000010C /* MyAccountConfirmEnrollmentMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA0001000000000000010C /* MyAccountConfirmEnrollmentMethodHandlerTests.swift */; }; + B0CA0002000000000000010D /* MyAccountUpdateAuthMethodMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA0001000000000000010D /* MyAccountUpdateAuthMethodMethodHandlerTests.swift */; }; + B0CA0002000000000000010E /* MyAccountEnrollPasskeyChallengeMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA0001000000000000010E /* MyAccountEnrollPasskeyChallengeMethodHandlerTests.swift */; }; + B0CA0002000000000000010F /* MyAccountEnrollPasskeyMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0CA0001000000000000010F /* MyAccountEnrollPasskeyMethodHandlerTests.swift */; }; + B1C2D3E42AECB46A00862999 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = B1C2D3E32AECB46A00862999 /* FlutterGeneratedPluginSwiftPackage */; }; + PK00000000000000000101 /* AuthAPIPasskeyLoginChallengeMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = PK00000000000000000103 /* AuthAPIPasskeyLoginChallengeMethodHandlerTests.swift */; }; + PK00000000000000000105 /* AuthAPIPasskeyExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = PK00000000000000000106 /* AuthAPIPasskeyExtensionsTests.swift */; }; + PK10000000000000000101 /* AuthAPIPasskeySignupChallengeMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = PK10000000000000000103 /* AuthAPIPasskeySignupChallengeMethodHandlerTests.swift */; }; + PK20000000000000000101 /* AuthAPIPasskeyCredentialExchangeMethodHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = PK20000000000000000102 /* AuthAPIPasskeyCredentialExchangeMethodHandlerTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -97,7 +120,9 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 27AD9A8283C773A4F8B6BA27 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 0D39FAC562F0E6F84339AE58 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 21DBF4BE5C5B1183C69F87D1 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 30C90C251A85CFCAF7F218D9 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; @@ -112,11 +137,7 @@ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 3A9C2FDF11E15DD5EF1ED910 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - 41C962BEC645340B9706DD39 /* Pods-RunnerUITests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerUITests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerUITests/Pods-RunnerUITests.profile.xcconfig"; sourceTree = ""; }; - 4A98190FD0F1B250B7F2E254 /* Pods-RunnerUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerUITests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerUITests/Pods-RunnerUITests.debug.xcconfig"; sourceTree = ""; }; - 506E34AA72DE3EE89DA59AF3 /* Pods_RunnerUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 58D6F3AE2B922A6E357195D0 /* Pods-RunnerUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerUITests.release.xcconfig"; path = "Target Support Files/Pods-RunnerUITests/Pods-RunnerUITests.release.xcconfig"; sourceTree = ""; }; + 42E90A8B7E56466926079940 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 5C1399032B0D3526006DCE54 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = ""; }; 5C1399052B0EB5F3006DCE54 /* Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = ""; }; 5C1399062B0EB5F3006DCE54 /* ExtensionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionsTests.swift; sourceTree = ""; }; @@ -147,14 +168,37 @@ 5C1399222B0EB5F3006DCE54 /* CredentialsManagerHandlerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CredentialsManagerHandlerTests.swift; sourceTree = ""; }; 5CD8A5552B1179EE00313321 /* RunnerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5CD8A5612B117A9900313321 /* SmokeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmokeTests.swift; sourceTree = ""; }; + 5D0A3A77C308FD33805CA99C /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 6FD903E99CB6C89165AACEDF /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 784666492D4C4C64000A1A5F /* FlutterFramework */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterFramework; path = ephemeral/Packages/.packages/FlutterFramework; sourceTree = ""; }; + 78DABEA22ED26510000E7860 /* auth0_flutter */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = auth0_flutter; path = ../../../darwin/auth0_flutter; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 7ED66A852229D3A45DA8B8F4 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - A5D53695EE5033B369D93BD9 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - ACE018A94DF310B8F853BF8B /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - B2F0D16F6C0B75F8D710F501 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - B4109D16F63E569418468A57 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - B73B6AA0238923E7DDDBEA3B /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - C6421E0A6040B142B4103AF6 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + A09B2E3F1D4C7891BA000010 /* CredentialsManagerSSOCredentialsMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialsManagerSSOCredentialsMethodHandlerTests.swift; sourceTree = ""; }; + A0AC1D0F2E0000000000AC11 /* CredentialsManagerApiCredentialsMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialsManagerApiCredentialsMethodHandlerTests.swift; sourceTree = ""; }; + A0AC1D0F2E0000000000AC13 /* CredentialsManagerClearApiCredentialsMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialsManagerClearApiCredentialsMethodHandlerTests.swift; sourceTree = ""; }; + B0CA00010000000000000101 /* MyAccountSpies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountSpies.swift; sourceTree = ""; }; + B0CA00010000000000000102 /* MyAccountDeleteAuthMethodMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountDeleteAuthMethodMethodHandlerTests.swift; sourceTree = ""; }; + B0CA00010000000000000103 /* MyAccountEnrollEmailMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountEnrollEmailMethodHandlerTests.swift; sourceTree = ""; }; + B0CA00010000000000000104 /* MyAccountEnrollPhoneMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountEnrollPhoneMethodHandlerTests.swift; sourceTree = ""; }; + B0CA00010000000000000105 /* MyAccountEnrollPushMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountEnrollPushMethodHandlerTests.swift; sourceTree = ""; }; + B0CA00010000000000000106 /* MyAccountEnrollRecoveryCodeMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountEnrollRecoveryCodeMethodHandlerTests.swift; sourceTree = ""; }; + B0CA00010000000000000107 /* MyAccountEnrollTotpMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountEnrollTotpMethodHandlerTests.swift; sourceTree = ""; }; + B0CA00010000000000000108 /* MyAccountGetAuthMethodMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountGetAuthMethodMethodHandlerTests.swift; sourceTree = ""; }; + B0CA00010000000000000109 /* MyAccountGetAuthMethodsMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountGetAuthMethodsMethodHandlerTests.swift; sourceTree = ""; }; + B0CA0001000000000000010A /* MyAccountGetFactorsMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountGetFactorsMethodHandlerTests.swift; sourceTree = ""; }; + B0CA0001000000000000010B /* MyAccountVerifyOtpMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountVerifyOtpMethodHandlerTests.swift; sourceTree = ""; }; + B0CA0001000000000000010C /* MyAccountConfirmEnrollmentMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountConfirmEnrollmentMethodHandlerTests.swift; sourceTree = ""; }; + B0CA0001000000000000010D /* MyAccountUpdateAuthMethodMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountUpdateAuthMethodMethodHandlerTests.swift; sourceTree = ""; }; + B0CA0001000000000000010E /* MyAccountEnrollPasskeyChallengeMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountEnrollPasskeyChallengeMethodHandlerTests.swift; sourceTree = ""; }; + B0CA0001000000000000010F /* MyAccountEnrollPasskeyMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountEnrollPasskeyMethodHandlerTests.swift; sourceTree = ""; }; + FF584AA0512B18AACE2C3C4C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + PK00000000000000000103 /* AuthAPIPasskeyLoginChallengeMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPIPasskeyLoginChallengeMethodHandlerTests.swift; sourceTree = ""; }; + PK00000000000000000106 /* AuthAPIPasskeyExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPIPasskeyExtensionsTests.swift; sourceTree = ""; }; + PK10000000000000000103 /* AuthAPIPasskeySignupChallengeMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPIPasskeySignupChallengeMethodHandlerTests.swift; sourceTree = ""; }; + PK20000000000000000102 /* AuthAPIPasskeyCredentialExchangeMethodHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPIPasskeyCredentialExchangeMethodHandlerTests.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -162,7 +206,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - BED01AE0EC3CF9FFA874824D /* Pods_RunnerTests.framework in Frameworks */, + B1C2D3E42AECB46A00862999 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, + 853B294B9A67C603C2508DFE /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -170,7 +215,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C674941AB11928E11BF9C473 /* Pods_Runner.framework in Frameworks */, + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, + 0103B7EA1132AC95205851B1 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -178,39 +224,12 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B7435027FDBEB9426DE3F945 /* Pods_RunnerUITests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 0A83CD3842B42E7E66FE5235 /* Frameworks */ = { - isa = PBXGroup; - children = ( - B4109D16F63E569418468A57 /* Pods_Runner.framework */, - B73B6AA0238923E7DDDBEA3B /* Pods_RunnerTests.framework */, - 506E34AA72DE3EE89DA59AF3 /* Pods_RunnerUITests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 1D5D4AA99FB925976AA6B2EB /* Pods */ = { - isa = PBXGroup; - children = ( - B2F0D16F6C0B75F8D710F501 /* Pods-Runner.debug.xcconfig */, - A5D53695EE5033B369D93BD9 /* Pods-Runner.release.xcconfig */, - C6421E0A6040B142B4103AF6 /* Pods-Runner.profile.xcconfig */, - 3A9C2FDF11E15DD5EF1ED910 /* Pods-RunnerTests.debug.xcconfig */, - 27AD9A8283C773A4F8B6BA27 /* Pods-RunnerTests.release.xcconfig */, - ACE018A94DF310B8F853BF8B /* Pods-RunnerTests.profile.xcconfig */, - 4A98190FD0F1B250B7F2E254 /* Pods-RunnerUITests.debug.xcconfig */, - 58D6F3AE2B922A6E357195D0 /* Pods-RunnerUITests.release.xcconfig */, - 41C962BEC645340B9706DD39 /* Pods-RunnerUITests.profile.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; 33BA886A226E78AF003329D5 /* Configs */ = { isa = PBXGroup; children = ( @@ -230,8 +249,8 @@ 5C1399042B0EB5F3006DCE54 /* Tests */, 5CD8A5562B1179EE00313321 /* UITests */, 33CC10EE2044A3C60003C045 /* Products */, - 1D5D4AA99FB925976AA6B2EB /* Pods */, - 0A83CD3842B42E7E66FE5235 /* Frameworks */, + C7919A111223B437ED9FBF70 /* Pods */, + 8CE186BA3D2E1C4481596FB8 /* Frameworks */, ); sourceTree = ""; }; @@ -259,6 +278,9 @@ 33CEB47122A05771004F2AC0 /* Flutter */ = { isa = PBXGroup; children = ( + 78DABEA22ED26510000E7860 /* auth0_flutter */, + 784666492D4C4C64000A1A5F /* FlutterFramework */, + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, @@ -291,6 +313,7 @@ 5C13990F2B0EB5F3006DCE54 /* AuthAPI */, 5C13991A2B0EB5F3006DCE54 /* SwiftAuth0FlutterPluginTests.swift */, 5C13991B2B0EB5F3006DCE54 /* CredentialsManager */, + B0CA000300000000000001A1 /* MyAccount */, ); name = Tests; path = ../ios/Tests; @@ -321,6 +344,10 @@ 5C1399172B0EB5F3006DCE54 /* AuthAPIResetPasswordMethodHandlerTests.swift */, 5C1399182B0EB5F3006DCE54 /* AuthAPISpies.swift */, 5C1399192B0EB5F3006DCE54 /* AuthAPIUserInfoMethodHandlerTests.swift */, + PK00000000000000000103 /* AuthAPIPasskeyLoginChallengeMethodHandlerTests.swift */, + PK00000000000000000106 /* AuthAPIPasskeyExtensionsTests.swift */, + PK10000000000000000103 /* AuthAPIPasskeySignupChallengeMethodHandlerTests.swift */, + PK20000000000000000102 /* AuthAPIPasskeyCredentialExchangeMethodHandlerTests.swift */, ); path = AuthAPI; sourceTree = ""; @@ -335,6 +362,9 @@ 5C1399202B0EB5F3006DCE54 /* CredentialsManagerClearMethodHandlerTests.swift */, 5C1399212B0EB5F3006DCE54 /* CredentialsManagerGetMethodHandlerTests.swift */, 5C1399222B0EB5F3006DCE54 /* CredentialsManagerHandlerTests.swift */, + A09B2E3F1D4C7891BA000010 /* CredentialsManagerSSOCredentialsMethodHandlerTests.swift */, + A0AC1D0F2E0000000000AC11 /* CredentialsManagerApiCredentialsMethodHandlerTests.swift */, + A0AC1D0F2E0000000000AC13 /* CredentialsManagerClearApiCredentialsMethodHandlerTests.swift */, ); path = CredentialsManager; sourceTree = ""; @@ -347,6 +377,51 @@ path = UITests; sourceTree = ""; }; + 8CE186BA3D2E1C4481596FB8 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 42E90A8B7E56466926079940 /* Pods_Runner.framework */, + 6FD903E99CB6C89165AACEDF /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + B0CA000300000000000001A1 /* MyAccount */ = { + isa = PBXGroup; + children = ( + B0CA00010000000000000101 /* MyAccountSpies.swift */, + B0CA00010000000000000102 /* MyAccountDeleteAuthMethodMethodHandlerTests.swift */, + B0CA00010000000000000103 /* MyAccountEnrollEmailMethodHandlerTests.swift */, + B0CA00010000000000000104 /* MyAccountEnrollPhoneMethodHandlerTests.swift */, + B0CA00010000000000000105 /* MyAccountEnrollPushMethodHandlerTests.swift */, + B0CA00010000000000000106 /* MyAccountEnrollRecoveryCodeMethodHandlerTests.swift */, + B0CA00010000000000000107 /* MyAccountEnrollTotpMethodHandlerTests.swift */, + B0CA00010000000000000108 /* MyAccountGetAuthMethodMethodHandlerTests.swift */, + B0CA00010000000000000109 /* MyAccountGetAuthMethodsMethodHandlerTests.swift */, + B0CA0001000000000000010A /* MyAccountGetFactorsMethodHandlerTests.swift */, + B0CA0001000000000000010B /* MyAccountVerifyOtpMethodHandlerTests.swift */, + B0CA0001000000000000010C /* MyAccountConfirmEnrollmentMethodHandlerTests.swift */, + B0CA0001000000000000010D /* MyAccountUpdateAuthMethodMethodHandlerTests.swift */, + B0CA0001000000000000010E /* MyAccountEnrollPasskeyChallengeMethodHandlerTests.swift */, + B0CA0001000000000000010F /* MyAccountEnrollPasskeyMethodHandlerTests.swift */, + ); + path = MyAccount; + sourceTree = ""; + }; + C7919A111223B437ED9FBF70 /* Pods */ = { + isa = PBXGroup; + children = ( + 21DBF4BE5C5B1183C69F87D1 /* Pods-Runner.debug.xcconfig */, + 5D0A3A77C308FD33805CA99C /* Pods-Runner.release.xcconfig */, + FF584AA0512B18AACE2C3C4C /* Pods-Runner.profile.xcconfig */, + 30C90C251A85CFCAF7F218D9 /* Pods-RunnerTests.debug.xcconfig */, + 0D39FAC562F0E6F84339AE58 /* Pods-RunnerTests.release.xcconfig */, + 7ED66A852229D3A45DA8B8F4 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -354,7 +429,7 @@ isa = PBXNativeTarget; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - 91148E742614B259D75019A1 /* [CP] Check Pods Manifest.lock */, + 07283CD29BFFA6E450AD531B /* [CP] Check Pods Manifest.lock */, 331C80D1294CF70F00263BE5 /* Sources */, 331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D3294CF70F00263BE5 /* Resources */, @@ -365,6 +440,9 @@ 331C80DA294CF71000263BE5 /* PBXTargetDependency */, ); name = RunnerTests; + packageProductDependencies = ( + B1C2D3E32AECB46A00862999 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = RunnerTests; productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; @@ -373,13 +451,12 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 82AEF7471165594BCED02754 /* [CP] Check Pods Manifest.lock */, + 11999AB9922BE4E868AF2FF0 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, - A5465F754C30546E6F4C48F0 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -387,6 +464,9 @@ 33CC11202044C79F0003C045 /* PBXTargetDependency */, ); name = Runner; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Runner; productReference = 33CC10ED2044A3C60003C045 /* example.app */; productType = "com.apple.product-type.application"; @@ -395,11 +475,9 @@ isa = PBXNativeTarget; buildConfigurationList = 5CD8A5602B1179EE00313321 /* Build configuration list for PBXNativeTarget "RunnerUITests" */; buildPhases = ( - FE5FAB3D07F982B1C53DFA3C /* [CP] Check Pods Manifest.lock */, 5CD8A5512B1179EE00313321 /* Sources */, 5CD8A5522B1179EE00313321 /* Frameworks */, 5CD8A5532B1179EE00313321 /* Resources */, - FA50A64EBD005709DC4A7419 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -453,6 +531,9 @@ Base, ); mainGroup = 33CC10E42044A3C60003C045; + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + ); productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -492,45 +573,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 3399D490228B24CF009A79C7 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; - }; - 33CC111E2044C6BF0003C045 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - Flutter/ephemeral/FlutterInputs.xcfilelist, - ); - inputPaths = ( - Flutter/ephemeral/tripwire, - ); - outputFileListPaths = ( - Flutter/ephemeral/FlutterOutputs.xcfilelist, - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; - }; - 82AEF7471165594BCED02754 /* [CP] Check Pods Manifest.lock */ = { + 07283CD29BFFA6E450AD531B /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -545,14 +588,14 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 91148E742614B259D75019A1 /* [CP] Check Pods Manifest.lock */ = { + 11999AB9922BE4E868AF2FF0 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -567,68 +610,50 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - A5465F754C30546E6F4C48F0 /* [CP] Embed Pods Frameworks */ = { + 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - FA50A64EBD005709DC4A7419 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RunnerUITests/Pods-RunnerUITests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + inputPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RunnerUITests/Pods-RunnerUITests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RunnerUITests/Pods-RunnerUITests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; }; - FE5FAB3D07F982B1C53DFA3C /* [CP] Check Pods Manifest.lock */ = { + 33CC111E2044C6BF0003C045 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", + Flutter/ephemeral/tripwire, ); - name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerUITests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; /* End PBXShellScriptBuildPhase section */ @@ -664,6 +689,28 @@ 5C13993D2B0EB5F3006DCE54 /* CredentialsManagerHandlerTests.swift in Sources */, 5C1399352B0EB5F3006DCE54 /* AuthAPIUserInfoMethodHandlerTests.swift in Sources */, 5C13993C2B0EB5F3006DCE54 /* CredentialsManagerGetMethodHandlerTests.swift in Sources */, + A09B2E3F1D4C7891BA000011 /* CredentialsManagerSSOCredentialsMethodHandlerTests.swift in Sources */, + A0AC1D0F2E0000000000AC12 /* CredentialsManagerApiCredentialsMethodHandlerTests.swift in Sources */, + A0AC1D0F2E0000000000AC14 /* CredentialsManagerClearApiCredentialsMethodHandlerTests.swift in Sources */, + PK00000000000000000101 /* AuthAPIPasskeyLoginChallengeMethodHandlerTests.swift in Sources */, + PK00000000000000000105 /* AuthAPIPasskeyExtensionsTests.swift in Sources */, + PK10000000000000000101 /* AuthAPIPasskeySignupChallengeMethodHandlerTests.swift in Sources */, + PK20000000000000000101 /* AuthAPIPasskeyCredentialExchangeMethodHandlerTests.swift in Sources */, + B0CA00020000000000000101 /* MyAccountSpies.swift in Sources */, + B0CA00020000000000000102 /* MyAccountDeleteAuthMethodMethodHandlerTests.swift in Sources */, + B0CA00020000000000000103 /* MyAccountEnrollEmailMethodHandlerTests.swift in Sources */, + B0CA00020000000000000104 /* MyAccountEnrollPhoneMethodHandlerTests.swift in Sources */, + B0CA00020000000000000105 /* MyAccountEnrollPushMethodHandlerTests.swift in Sources */, + B0CA00020000000000000106 /* MyAccountEnrollRecoveryCodeMethodHandlerTests.swift in Sources */, + B0CA00020000000000000107 /* MyAccountEnrollTotpMethodHandlerTests.swift in Sources */, + B0CA00020000000000000108 /* MyAccountGetAuthMethodMethodHandlerTests.swift in Sources */, + B0CA00020000000000000109 /* MyAccountGetAuthMethodsMethodHandlerTests.swift in Sources */, + B0CA0002000000000000010A /* MyAccountGetFactorsMethodHandlerTests.swift in Sources */, + B0CA0002000000000000010B /* MyAccountVerifyOtpMethodHandlerTests.swift in Sources */, + B0CA0002000000000000010C /* MyAccountConfirmEnrollmentMethodHandlerTests.swift in Sources */, + B0CA0002000000000000010D /* MyAccountUpdateAuthMethodMethodHandlerTests.swift in Sources */, + B0CA0002000000000000010E /* MyAccountEnrollPasskeyChallengeMethodHandlerTests.swift in Sources */, + B0CA0002000000000000010F /* MyAccountEnrollPasskeyMethodHandlerTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -720,46 +767,46 @@ /* Begin XCBuildConfiguration section */ 331C80DB294CF71000263BE5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3A9C2FDF11E15DD5EF1ED910 /* Pods-RunnerTests.debug.xcconfig */; + baseConfigurationReference = 30C90C251A85CFCAF7F218D9 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.auth0.example.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; }; name = Debug; }; 331C80DC294CF71000263BE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 27AD9A8283C773A4F8B6BA27 /* Pods-RunnerTests.release.xcconfig */; + baseConfigurationReference = 0D39FAC562F0E6F84339AE58 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.auth0.example.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; }; name = Release; }; 331C80DD294CF71000263BE5 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = ACE018A94DF310B8F853BF8B /* Pods-RunnerTests.profile.xcconfig */; + baseConfigurationReference = 7ED66A852229D3A45DA8B8F4 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.auth0.example.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; }; name = Profile; }; @@ -996,7 +1043,6 @@ }; 5CD8A55D2B1179EE00313321 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4A98190FD0F1B250B7F2E254 /* Pods-RunnerUITests.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -1030,7 +1076,6 @@ }; 5CD8A55E2B1179EE00313321 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 58D6F3AE2B922A6E357195D0 /* Pods-RunnerUITests.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -1062,7 +1107,6 @@ }; 5CD8A55F2B1179EE00313321 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 41C962BEC645340B9706DD39 /* Pods-RunnerUITests.profile.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -1146,6 +1190,24 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; + B1C2D3E32AECB46A00862999 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 33CC10E52044A3C60003C045 /* Project object */; } diff --git a/auth0_flutter/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/auth0_flutter/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..a2f52a521 --- /dev/null +++ b/auth0_flutter/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,32 @@ +{ + "pins" : [ + { + "identity" : "auth0.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/Auth0.swift", + "state" : { + "revision" : "b07565e7c859906815411d441a94e2c3c1f36085", + "version" : "2.22.0" + } + }, + { + "identity" : "jwtdecode.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/JWTDecode.swift", + "state" : { + "revision" : "36a5ce735a61c4bc119593f43ce2c027b4ca7392", + "version" : "3.3.0" + } + }, + { + "identity" : "simplekeychain", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/SimpleKeychain", + "state" : { + "revision" : "776c4a6db74d5c6c143974be91c383680d468630", + "version" : "1.3.0" + } + } + ], + "version" : 2 +} diff --git a/auth0_flutter/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/auth0_flutter/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 9449c3b76..aade325dc 100644 --- a/auth0_flutter/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/auth0_flutter/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -5,6 +5,24 @@ + + + + + + + + + + diff --git a/auth0_flutter/example/macos/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved b/auth0_flutter/example/macos/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..a2f52a521 --- /dev/null +++ b/auth0_flutter/example/macos/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,32 @@ +{ + "pins" : [ + { + "identity" : "auth0.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/Auth0.swift", + "state" : { + "revision" : "b07565e7c859906815411d441a94e2c3c1f36085", + "version" : "2.22.0" + } + }, + { + "identity" : "jwtdecode.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/JWTDecode.swift", + "state" : { + "revision" : "36a5ce735a61c4bc119593f43ce2c027b4ca7392", + "version" : "3.3.0" + } + }, + { + "identity" : "simplekeychain", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/SimpleKeychain", + "state" : { + "revision" : "776c4a6db74d5c6c143974be91c383680d468630", + "version" : "1.3.0" + } + } + ], + "version" : 2 +} diff --git a/auth0_flutter/example/macos/Runner/AppDelegate.swift b/auth0_flutter/example/macos/Runner/AppDelegate.swift index d53ef6437..b3c176141 100644 --- a/auth0_flutter/example/macos/Runner/AppDelegate.swift +++ b/auth0_flutter/example/macos/Runner/AppDelegate.swift @@ -1,9 +1,13 @@ import Cocoa import FlutterMacOS -@NSApplicationMain +@main class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } } diff --git a/auth0_flutter/example/pubspec.yaml b/auth0_flutter/example/pubspec.yaml index 3872ff416..6a7bf7546 100644 --- a/auth0_flutter/example/pubspec.yaml +++ b/auth0_flutter/example/pubspec.yaml @@ -57,8 +57,8 @@ flutter: # the material Icons class. uses-material-design: true - # assets: - # - .env + assets: + - .env # To add assets to your application, add an assets section, like this: # assets: diff --git a/auth0_flutter/ios/.gitignore b/auth0_flutter/ios/.gitignore index 55ff257cf..cafa1b5dd 100644 --- a/auth0_flutter/ios/.gitignore +++ b/auth0_flutter/ios/.gitignore @@ -12,10 +12,6 @@ build/ GeneratedPluginRegistrant.h GeneratedPluginRegistrant.m -# Swift Package Manager build cache -.build/ -.swiftpm/ - .generated/ *.pbxuser @@ -40,3 +36,9 @@ Icon? /Flutter/Generated.xcconfig /Flutter/ephemeral/ /Flutter/flutter_export_environment.sh + +# Swift Package Manager +.build/ +.swiftpm/ +Package.resolved +FlutterFramework/ diff --git a/auth0_flutter/ios/Classes/Auth0FlutterPlugin.h b/auth0_flutter/ios/Classes/Auth0FlutterPlugin.h deleted file mode 120000 index dc2c6689a..000000000 --- a/auth0_flutter/ios/Classes/Auth0FlutterPlugin.h +++ /dev/null @@ -1 +0,0 @@ -../../darwin/Classes/Auth0FlutterPlugin.h \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/Auth0FlutterPlugin.m b/auth0_flutter/ios/Classes/Auth0FlutterPlugin.m deleted file mode 120000 index 72d2585ac..000000000 --- a/auth0_flutter/ios/Classes/Auth0FlutterPlugin.m +++ /dev/null @@ -1 +0,0 @@ -../../darwin/Classes/Auth0FlutterPlugin.m \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/Auth0FlutterPlugin.swift b/auth0_flutter/ios/Classes/Auth0FlutterPlugin.swift new file mode 120000 index 000000000..185ca2b5d --- /dev/null +++ b/auth0_flutter/ios/Classes/Auth0FlutterPlugin.swift @@ -0,0 +1 @@ +../../../darwin/Classes/Auth0FlutterPlugin.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift index 3bb2c2d3d..f49acfa5e 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift index fef802a3d..93b8277cf 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIExtensions.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIExtensions.swift index 9d25c9150..2f3df6d3d 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIExtensions.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIExtensions.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIExtensions.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIHandler.swift index 0557daaa5..fdb6bb545 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift index e5cdc15e5..13942e1af 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift index 0f3d2dc45..674175d3e 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift index 854e8df59..a426cfd99 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift index 2e94fe6ca..182eae3b2 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift index b4f6ace64..ff9a6c0ee 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift index 6f0c0bd69..d683243ee 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift index d7be4d7d8..afb2b7140 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift index c3386515d..715c03f87 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift index dfbff772f..72e5afaaa 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift index 7fe1a8cb5..bcde3d63f 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift index 4a86309a1..ac18b63e5 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift index 03cf0823b..c467c2a81 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPISignupMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPISignupMethodHandler.swift index 48a322e53..2973a1dfb 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPISignupMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPISignupMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPISignupMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPISignupMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift index 79a16034a..f4ae7e771 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/AuthAPI/SSOExchangeMethodHandler.swift b/auth0_flutter/ios/Classes/AuthAPI/SSOExchangeMethodHandler.swift index 0e504cd09..6e2e23e42 120000 --- a/auth0_flutter/ios/Classes/AuthAPI/SSOExchangeMethodHandler.swift +++ b/auth0_flutter/ios/Classes/AuthAPI/SSOExchangeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/SSOExchangeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/SSOExchangeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift b/auth0_flutter/ios/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift index 227e0a9b5..4c16597c6 120000 --- a/auth0_flutter/ios/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift +++ b/auth0_flutter/ios/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift b/auth0_flutter/ios/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift index 547205039..9353cb299 120000 --- a/auth0_flutter/ios/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift +++ b/auth0_flutter/ios/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift index 4d72434d2..376f9cf9b 120000 --- a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift +++ b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerExtensions.swift b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerExtensions.swift index dc32193cd..c37f2fb84 120000 --- a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerExtensions.swift +++ b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerExtensions.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerExtensions.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift index 415149b7a..88c5037a0 120000 --- a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift +++ b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerHandler.swift b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerHandler.swift index c076e8590..a10cdc2e8 120000 --- a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerHandler.swift +++ b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift index 68fe975fe..955f2dfb4 120000 --- a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift +++ b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerModels.swift b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerModels.swift index 37fe0ae01..41daa8094 120000 --- a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerModels.swift +++ b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerModels.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerModels.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerModels.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift index 5ad277078..658cdfcdd 120000 --- a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift +++ b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift index 768751e32..4b2d2d57a 120000 --- a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift +++ b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift index 355099aac..c28d8f83c 120000 --- a/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift +++ b/auth0_flutter/ios/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift b/auth0_flutter/ios/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift index 21600818b..4ad619218 120000 --- a/auth0_flutter/ios/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift +++ b/auth0_flutter/ios/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/DPoP/DPoPClearKeyMethodHandler.swift b/auth0_flutter/ios/Classes/DPoP/DPoPClearKeyMethodHandler.swift index 2ee9bbc59..f7891a2a7 120000 --- a/auth0_flutter/ios/Classes/DPoP/DPoPClearKeyMethodHandler.swift +++ b/auth0_flutter/ios/Classes/DPoP/DPoPClearKeyMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/DPoP/DPoPClearKeyMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/DPoP/DPoPClearKeyMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/DPoP/DPoPGetHeadersMethodHandler.swift b/auth0_flutter/ios/Classes/DPoP/DPoPGetHeadersMethodHandler.swift index 21506d926..c6fe62027 120000 --- a/auth0_flutter/ios/Classes/DPoP/DPoPGetHeadersMethodHandler.swift +++ b/auth0_flutter/ios/Classes/DPoP/DPoPGetHeadersMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/DPoP/DPoPGetHeadersMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/DPoP/DPoPGetHeadersMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/DPoP/DPoPHandler.swift b/auth0_flutter/ios/Classes/DPoP/DPoPHandler.swift index 0ef26ea83..47d4c3a70 120000 --- a/auth0_flutter/ios/Classes/DPoP/DPoPHandler.swift +++ b/auth0_flutter/ios/Classes/DPoP/DPoPHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/DPoP/DPoPHandler.swift \ No newline at end of file +../../../../darwin/Classes/DPoP/DPoPHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/Extensions.swift b/auth0_flutter/ios/Classes/Extensions.swift index 865013982..723e4801c 120000 --- a/auth0_flutter/ios/Classes/Extensions.swift +++ b/auth0_flutter/ios/Classes/Extensions.swift @@ -1 +1 @@ -../../darwin/Classes/Extensions.swift \ No newline at end of file +../../../darwin/Classes/Extensions.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/HandlerError.swift b/auth0_flutter/ios/Classes/HandlerError.swift index d7136c2be..9d905ce58 120000 --- a/auth0_flutter/ios/Classes/HandlerError.swift +++ b/auth0_flutter/ios/Classes/HandlerError.swift @@ -1 +1 @@ -../../darwin/Classes/HandlerError.swift \ No newline at end of file +../../../darwin/Classes/HandlerError.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MethodHandler.swift b/auth0_flutter/ios/Classes/MethodHandler.swift index 49c766a2f..d10ee2f70 120000 --- a/auth0_flutter/ios/Classes/MethodHandler.swift +++ b/auth0_flutter/ios/Classes/MethodHandler.swift @@ -1 +1 @@ -../../darwin/Classes/MethodHandler.swift \ No newline at end of file +../../../darwin/Classes/MethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/Models.swift b/auth0_flutter/ios/Classes/Models.swift index 085296591..006985a57 120000 --- a/auth0_flutter/ios/Classes/Models.swift +++ b/auth0_flutter/ios/Classes/Models.swift @@ -1 +1 @@ -../../darwin/Classes/Models.swift \ No newline at end of file +../../../darwin/Classes/Models.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift index e8f526c6e..915a14eeb 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift index 2e3e8b4e0..6ee882429 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift index daf0f0fe6..6cc15ea2d 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift index a5cad86f0..ece33e6bc 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift index 2f1ce0c2d..5448cbb12 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift index d0505ff08..a38d975b4 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift index 75c6bbb10..1641b0815 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift index a0823fa59..b26895981 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift index 4728fd483..af0c5409e 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountExtensions.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountExtensions.swift index 69a6d0a97..5aee879e3 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountExtensions.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountExtensions.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountExtensions.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift index e1881a28b..a5e9d8a09 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift index 3038cdde9..93d285c26 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift index 57eb6990e..56b4d6971 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountHandler.swift index db33d385b..bada5039c 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift index b69f448c5..8c34ec2df 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift index 25a45bc22..0ea5b34dc 120000 --- a/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift +++ b/auth0_flutter/ios/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/Properties.swift b/auth0_flutter/ios/Classes/Properties.swift index 9f83511c3..67752eb94 120000 --- a/auth0_flutter/ios/Classes/Properties.swift +++ b/auth0_flutter/ios/Classes/Properties.swift @@ -1 +1 @@ -../../darwin/Classes/Properties.swift \ No newline at end of file +../../../darwin/Classes/Properties.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/SwiftAuth0FlutterPlugin.swift b/auth0_flutter/ios/Classes/SwiftAuth0FlutterPlugin.swift deleted file mode 120000 index 58c54251a..000000000 --- a/auth0_flutter/ios/Classes/SwiftAuth0FlutterPlugin.swift +++ /dev/null @@ -1 +0,0 @@ -../../darwin/Classes/SwiftAuth0FlutterPlugin.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/WebAuth/WebAuthExtensions.swift b/auth0_flutter/ios/Classes/WebAuth/WebAuthExtensions.swift index 750862a3c..8d2d714b1 120000 --- a/auth0_flutter/ios/Classes/WebAuth/WebAuthExtensions.swift +++ b/auth0_flutter/ios/Classes/WebAuth/WebAuthExtensions.swift @@ -1 +1 @@ -../../../darwin/Classes/WebAuth/WebAuthExtensions.swift \ No newline at end of file +../../../../darwin/Classes/WebAuth/WebAuthExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/WebAuth/WebAuthHandler.swift b/auth0_flutter/ios/Classes/WebAuth/WebAuthHandler.swift index 05c9ddd70..fd92711ab 120000 --- a/auth0_flutter/ios/Classes/WebAuth/WebAuthHandler.swift +++ b/auth0_flutter/ios/Classes/WebAuth/WebAuthHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/WebAuth/WebAuthHandler.swift \ No newline at end of file +../../../../darwin/Classes/WebAuth/WebAuthHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/WebAuth/WebAuthLoginMethodHandler.swift b/auth0_flutter/ios/Classes/WebAuth/WebAuthLoginMethodHandler.swift index b8baebc63..45a36ac71 120000 --- a/auth0_flutter/ios/Classes/WebAuth/WebAuthLoginMethodHandler.swift +++ b/auth0_flutter/ios/Classes/WebAuth/WebAuthLoginMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/WebAuth/WebAuthLoginMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/WebAuth/WebAuthLoginMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/WebAuth/WebAuthLogoutMethodHandler.swift b/auth0_flutter/ios/Classes/WebAuth/WebAuthLogoutMethodHandler.swift index 9f1cbb1d0..5c7921daf 120000 --- a/auth0_flutter/ios/Classes/WebAuth/WebAuthLogoutMethodHandler.swift +++ b/auth0_flutter/ios/Classes/WebAuth/WebAuthLogoutMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/WebAuth/WebAuthLogoutMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/WebAuth/WebAuthLogoutMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/ios/Classes/WebAuth/WebAuthModels.swift b/auth0_flutter/ios/Classes/WebAuth/WebAuthModels.swift index f98ec1472..b47a6d8ec 120000 --- a/auth0_flutter/ios/Classes/WebAuth/WebAuthModels.swift +++ b/auth0_flutter/ios/Classes/WebAuth/WebAuthModels.swift @@ -1 +1 @@ -../../../darwin/Classes/WebAuth/WebAuthModels.swift \ No newline at end of file +../../../../darwin/Classes/WebAuth/WebAuthModels.swift \ No newline at end of file diff --git a/auth0_flutter/macos/.gitignore b/auth0_flutter/macos/.gitignore index 55ff257cf..cafa1b5dd 100644 --- a/auth0_flutter/macos/.gitignore +++ b/auth0_flutter/macos/.gitignore @@ -12,10 +12,6 @@ build/ GeneratedPluginRegistrant.h GeneratedPluginRegistrant.m -# Swift Package Manager build cache -.build/ -.swiftpm/ - .generated/ *.pbxuser @@ -40,3 +36,9 @@ Icon? /Flutter/Generated.xcconfig /Flutter/ephemeral/ /Flutter/flutter_export_environment.sh + +# Swift Package Manager +.build/ +.swiftpm/ +Package.resolved +FlutterFramework/ diff --git a/auth0_flutter/macos/Classes/Auth0FlutterPlugin.h b/auth0_flutter/macos/Classes/Auth0FlutterPlugin.h deleted file mode 120000 index dc2c6689a..000000000 --- a/auth0_flutter/macos/Classes/Auth0FlutterPlugin.h +++ /dev/null @@ -1 +0,0 @@ -../../darwin/Classes/Auth0FlutterPlugin.h \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/Auth0FlutterPlugin.m b/auth0_flutter/macos/Classes/Auth0FlutterPlugin.m deleted file mode 120000 index 72d2585ac..000000000 --- a/auth0_flutter/macos/Classes/Auth0FlutterPlugin.m +++ /dev/null @@ -1 +0,0 @@ -../../darwin/Classes/Auth0FlutterPlugin.m \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/Auth0FlutterPlugin.swift b/auth0_flutter/macos/Classes/Auth0FlutterPlugin.swift new file mode 120000 index 000000000..185ca2b5d --- /dev/null +++ b/auth0_flutter/macos/Classes/Auth0FlutterPlugin.swift @@ -0,0 +1 @@ +../../../darwin/Classes/Auth0FlutterPlugin.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift index 3bb2c2d3d..f49acfa5e 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPICustomTokenExchangeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift index fef802a3d..93b8277cf 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIEmailPasswordlessLoginMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIExtensions.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIExtensions.swift index 9d25c9150..2f3df6d3d 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIExtensions.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIExtensions.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIExtensions.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIHandler.swift index 0557daaa5..fdb6bb545 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift index e5cdc15e5..13942e1af 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPILoginUsernameOrEmailMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift index 0f3d2dc45..674175d3e 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPILoginWithEmailMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift index 854e8df59..a426cfd99 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPILoginWithOTPMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift index 2e94fe6ca..182eae3b2 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPILoginWithPhoneNumberMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift index b4f6ace64..ff9a6c0ee 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIMultifactorChallengeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift index 6f0c0bd69..d683243ee 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIPasskeyCredentialExchangeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift index d7be4d7d8..afb2b7140 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIPasskeyExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift index c3386515d..715c03f87 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIPasskeyLoginChallengeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift index dfbff772f..72e5afaaa 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIPasskeySignupChallengeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift index 7fe1a8cb5..bcde3d63f 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift index 4a86309a1..ac18b63e5 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIRenewMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift index 03cf0823b..c467c2a81 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIResetPasswordMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPISignupMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPISignupMethodHandler.swift index 48a322e53..2973a1dfb 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPISignupMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPISignupMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPISignupMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPISignupMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift index 79a16034a..f4ae7e771 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/AuthAPIUserInfoMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/AuthAPI/SSOExchangeMethodHandler.swift b/auth0_flutter/macos/Classes/AuthAPI/SSOExchangeMethodHandler.swift index 0e504cd09..6e2e23e42 120000 --- a/auth0_flutter/macos/Classes/AuthAPI/SSOExchangeMethodHandler.swift +++ b/auth0_flutter/macos/Classes/AuthAPI/SSOExchangeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/AuthAPI/SSOExchangeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/AuthAPI/SSOExchangeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift b/auth0_flutter/macos/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift index 227e0a9b5..4c16597c6 120000 --- a/auth0_flutter/macos/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift +++ b/auth0_flutter/macos/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/ApiCredentialsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift b/auth0_flutter/macos/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift index 547205039..9353cb299 120000 --- a/auth0_flutter/macos/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift +++ b/auth0_flutter/macos/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/ClearApiCredentialsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift index 4d72434d2..376f9cf9b 120000 --- a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift +++ b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerClearMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerExtensions.swift b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerExtensions.swift index dc32193cd..c37f2fb84 120000 --- a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerExtensions.swift +++ b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerExtensions.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerExtensions.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift index 415149b7a..88c5037a0 120000 --- a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift +++ b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerGetMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerHandler.swift b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerHandler.swift index c076e8590..a10cdc2e8 120000 --- a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerHandler.swift +++ b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift index 68fe975fe..955f2dfb4 120000 --- a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift +++ b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerHasValidMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerModels.swift b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerModels.swift index 37fe0ae01..41daa8094 120000 --- a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerModels.swift +++ b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerModels.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerModels.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerModels.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift index 5ad277078..658cdfcdd 120000 --- a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift +++ b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerRenewMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift index 768751e32..4b2d2d57a 120000 --- a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift +++ b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerSaveMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift index 355099aac..c28d8f83c 120000 --- a/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift +++ b/auth0_flutter/macos/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/CredentialsManagerUserInfoMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift b/auth0_flutter/macos/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift index 21600818b..4ad619218 120000 --- a/auth0_flutter/macos/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift +++ b/auth0_flutter/macos/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/CredentialsManager/SSOCredentialsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/DPoP/DPoPClearKeyMethodHandler.swift b/auth0_flutter/macos/Classes/DPoP/DPoPClearKeyMethodHandler.swift index 2ee9bbc59..f7891a2a7 120000 --- a/auth0_flutter/macos/Classes/DPoP/DPoPClearKeyMethodHandler.swift +++ b/auth0_flutter/macos/Classes/DPoP/DPoPClearKeyMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/DPoP/DPoPClearKeyMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/DPoP/DPoPClearKeyMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/DPoP/DPoPGetHeadersMethodHandler.swift b/auth0_flutter/macos/Classes/DPoP/DPoPGetHeadersMethodHandler.swift index 21506d926..c6fe62027 120000 --- a/auth0_flutter/macos/Classes/DPoP/DPoPGetHeadersMethodHandler.swift +++ b/auth0_flutter/macos/Classes/DPoP/DPoPGetHeadersMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/DPoP/DPoPGetHeadersMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/DPoP/DPoPGetHeadersMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/DPoP/DPoPHandler.swift b/auth0_flutter/macos/Classes/DPoP/DPoPHandler.swift index 0ef26ea83..47d4c3a70 120000 --- a/auth0_flutter/macos/Classes/DPoP/DPoPHandler.swift +++ b/auth0_flutter/macos/Classes/DPoP/DPoPHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/DPoP/DPoPHandler.swift \ No newline at end of file +../../../../darwin/Classes/DPoP/DPoPHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/Extensions.swift b/auth0_flutter/macos/Classes/Extensions.swift index 865013982..723e4801c 120000 --- a/auth0_flutter/macos/Classes/Extensions.swift +++ b/auth0_flutter/macos/Classes/Extensions.swift @@ -1 +1 @@ -../../darwin/Classes/Extensions.swift \ No newline at end of file +../../../darwin/Classes/Extensions.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/HandlerError.swift b/auth0_flutter/macos/Classes/HandlerError.swift index d7136c2be..9d905ce58 120000 --- a/auth0_flutter/macos/Classes/HandlerError.swift +++ b/auth0_flutter/macos/Classes/HandlerError.swift @@ -1 +1 @@ -../../darwin/Classes/HandlerError.swift \ No newline at end of file +../../../darwin/Classes/HandlerError.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MethodHandler.swift b/auth0_flutter/macos/Classes/MethodHandler.swift index 49c766a2f..d10ee2f70 120000 --- a/auth0_flutter/macos/Classes/MethodHandler.swift +++ b/auth0_flutter/macos/Classes/MethodHandler.swift @@ -1 +1 @@ -../../darwin/Classes/MethodHandler.swift \ No newline at end of file +../../../darwin/Classes/MethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/Models.swift b/auth0_flutter/macos/Classes/Models.swift index 085296591..006985a57 120000 --- a/auth0_flutter/macos/Classes/Models.swift +++ b/auth0_flutter/macos/Classes/Models.swift @@ -1 +1 @@ -../../darwin/Classes/Models.swift \ No newline at end of file +../../../darwin/Classes/Models.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift index e8f526c6e..915a14eeb 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountConfirmEnrollmentMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift index 2e3e8b4e0..6ee882429 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountDeleteAuthMethodMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift index daf0f0fe6..6cc15ea2d 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollEmailMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift index a5cad86f0..ece33e6bc 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyChallengeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift index 2f1ce0c2d..5448cbb12 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPasskeyMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift index d0505ff08..a38d975b4 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPhoneMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift index 75c6bbb10..1641b0815 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollPushMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift index a0823fa59..b26895981 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollRecoveryCodeMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift index 4728fd483..af0c5409e 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountEnrollTotpMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountExtensions.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountExtensions.swift index 69a6d0a97..5aee879e3 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountExtensions.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountExtensions.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountExtensions.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift index e1881a28b..a5e9d8a09 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift index 3038cdde9..93d285c26 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountGetAuthMethodsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift index 57eb6990e..56b4d6971 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountGetFactorsMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountHandler.swift index db33d385b..bada5039c 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift index b69f448c5..8c34ec2df 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountUpdateAuthMethodMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift index 25a45bc22..0ea5b34dc 120000 --- a/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift +++ b/auth0_flutter/macos/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/MyAccountAPI/MyAccountVerifyOtpMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/Properties.swift b/auth0_flutter/macos/Classes/Properties.swift index 9f83511c3..67752eb94 120000 --- a/auth0_flutter/macos/Classes/Properties.swift +++ b/auth0_flutter/macos/Classes/Properties.swift @@ -1 +1 @@ -../../darwin/Classes/Properties.swift \ No newline at end of file +../../../darwin/Classes/Properties.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/SwiftAuth0FlutterPlugin.swift b/auth0_flutter/macos/Classes/SwiftAuth0FlutterPlugin.swift deleted file mode 120000 index 58c54251a..000000000 --- a/auth0_flutter/macos/Classes/SwiftAuth0FlutterPlugin.swift +++ /dev/null @@ -1 +0,0 @@ -../../darwin/Classes/SwiftAuth0FlutterPlugin.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/WebAuth/WebAuthExtensions.swift b/auth0_flutter/macos/Classes/WebAuth/WebAuthExtensions.swift index 750862a3c..8d2d714b1 120000 --- a/auth0_flutter/macos/Classes/WebAuth/WebAuthExtensions.swift +++ b/auth0_flutter/macos/Classes/WebAuth/WebAuthExtensions.swift @@ -1 +1 @@ -../../../darwin/Classes/WebAuth/WebAuthExtensions.swift \ No newline at end of file +../../../../darwin/Classes/WebAuth/WebAuthExtensions.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/WebAuth/WebAuthHandler.swift b/auth0_flutter/macos/Classes/WebAuth/WebAuthHandler.swift index 05c9ddd70..fd92711ab 120000 --- a/auth0_flutter/macos/Classes/WebAuth/WebAuthHandler.swift +++ b/auth0_flutter/macos/Classes/WebAuth/WebAuthHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/WebAuth/WebAuthHandler.swift \ No newline at end of file +../../../../darwin/Classes/WebAuth/WebAuthHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/WebAuth/WebAuthLoginMethodHandler.swift b/auth0_flutter/macos/Classes/WebAuth/WebAuthLoginMethodHandler.swift index b8baebc63..45a36ac71 120000 --- a/auth0_flutter/macos/Classes/WebAuth/WebAuthLoginMethodHandler.swift +++ b/auth0_flutter/macos/Classes/WebAuth/WebAuthLoginMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/WebAuth/WebAuthLoginMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/WebAuth/WebAuthLoginMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/WebAuth/WebAuthLogoutMethodHandler.swift b/auth0_flutter/macos/Classes/WebAuth/WebAuthLogoutMethodHandler.swift index 9f1cbb1d0..5c7921daf 120000 --- a/auth0_flutter/macos/Classes/WebAuth/WebAuthLogoutMethodHandler.swift +++ b/auth0_flutter/macos/Classes/WebAuth/WebAuthLogoutMethodHandler.swift @@ -1 +1 @@ -../../../darwin/Classes/WebAuth/WebAuthLogoutMethodHandler.swift \ No newline at end of file +../../../../darwin/Classes/WebAuth/WebAuthLogoutMethodHandler.swift \ No newline at end of file diff --git a/auth0_flutter/macos/Classes/WebAuth/WebAuthModels.swift b/auth0_flutter/macos/Classes/WebAuth/WebAuthModels.swift index f98ec1472..b47a6d8ec 120000 --- a/auth0_flutter/macos/Classes/WebAuth/WebAuthModels.swift +++ b/auth0_flutter/macos/Classes/WebAuth/WebAuthModels.swift @@ -1 +1 @@ -../../../darwin/Classes/WebAuth/WebAuthModels.swift \ No newline at end of file +../../../../darwin/Classes/WebAuth/WebAuthModels.swift \ No newline at end of file diff --git a/scripts/generate-symlinks.sh b/scripts/generate-symlinks.sh index 354f8d9cd..b245980e8 100755 --- a/scripts/generate-symlinks.sh +++ b/scripts/generate-symlinks.sh @@ -1,50 +1,80 @@ #!/bin/bash -# This script generates symlinks for every file inside the 'darwin' directory -# of the auth0_flutter package, to the 'ios' and 'macos' directories. -# It's meant to be run from the repository root. +# Generates symlinks so that CocoaPods consumers (ios/ and macos/) stay in +# sync with the canonical SPM source tree under darwin/auth0_flutter/Sources/. +# +# Layout produced: +# darwin/Classes/ -> ../../auth0_flutter/Sources/auth0_flutter/ +# ios/Classes/ -> ../../../darwin/Classes/ +# macos/Classes/ -> ../../../darwin/Classes/ +# +# Run from the repository root. set -euo pipefail repo_path=$(git rev-parse --show-toplevel) -if [ "$repo_path" != $PWD ]; then +if [ "$repo_path" != "$PWD" ]; then echo 'This script must be run from the repository root' exit 1 fi base_dir='auth0_flutter' -darwin_dir='auth0_flutter/darwin' -files=($(find "$darwin_dir" -type f -print)) -platforms=('ios' 'macos') +sources_dir='auth0_flutter/darwin/auth0_flutter/Sources/auth0_flutter' +darwin_classes_dir='auth0_flutter/darwin/Classes' -for platform in "${platforms[@]}"; do - rm -rf "$base_dir/$platform" -done +# Collect all real Swift/ObjC source files under Sources/auth0_flutter. +# Portable: bash 3.2 (macOS) does not have mapfile; use a while-read loop instead. +files=() +while IFS= read -r file; do + files+=("$file") +done < <(find "$sources_dir" -type f \( -name '*.swift' -o -name '*.h' -o -name '*.m' \)) + +if [ ${#files[@]} -eq 0 ]; then + echo "No source files found under $sources_dir" + exit 1 +fi + +# Rebuild darwin/Classes symlinks -> Sources +rm -rf "$darwin_classes_dir" for file in "${files[@]}"; do - for platform in "${platforms[@]}"; do - target_file=$(echo "$file" | sed "s/darwin/$platform/") - target_dir=$(dirname "$target_file") - - mkdir -p "$target_dir" - - case "$file" in - # If it's a .gitignore or Podspec file, copy it - (*'.gitignore' | *'.podspec') cp -v "$file" "$target_dir" ;; - # Else symlink it - (*) - # Calculate the relative path to the file from the symlink's - # location - file_subpath=${file#"$base_dir/"} - file_depth=$(echo "$file_subpath" | awk -F '/' '{print NF-1}') - file_relpath=$(printf '../%.0s' $(seq 1 $file_depth)) - - ln -sv "$file_relpath$file_subpath" "$target_file" ;; - esac - done + # rel path relative to sources_dir, e.g. AuthAPI/AuthAPIExtensions.swift + rel=${file#"$sources_dir/"} + + darwin_link="$darwin_classes_dir/$rel" + darwin_link_dir=$(dirname "$darwin_link") + mkdir -p "$darwin_link_dir" + + # Depth of the symlink inside darwin/Classes (e.g. AuthAPI/X.swift -> depth 2) + link_depth=$(echo "$darwin_link" | awk -F '/' '{print NF-1}') + # We need to go up (link_depth) levels then down into auth0_flutter/Sources/auth0_flutter/ + up=$(printf '../%.0s' $(seq 1 "$link_depth")) + ln -sf "${up}auth0_flutter/Sources/auth0_flutter/$rel" "$darwin_link" done -for platform in "${platforms[@]}"; do +# Rebuild ios/Classes and macos/Classes symlinks -> darwin/Classes +for platform in ios macos; do + platform_classes_dir="$base_dir/$platform/Classes" + rm -rf "$platform_classes_dir" + + for file in "${files[@]}"; do + rel=${file#"$sources_dir/"} + + platform_link="$platform_classes_dir/$rel" + platform_link_dir=$(dirname "$platform_link") + mkdir -p "$platform_link_dir" + + # Symlink ios/Classes/ -> ../../../darwin/Classes/ + # Depth of the link inside ios/Classes/ + link_depth=$(echo "$platform_link" | awk -F '/' '{print NF-1}') + up=$(printf '../%.0s' $(seq 1 "$link_depth")) + ln -sf "${up}darwin/Classes/$rel" "$platform_link" + done + git add "$base_dir/$platform" done + +git add "$darwin_classes_dir" + +echo "Symlinks regenerated successfully."