diff --git a/A0Auth0.podspec b/A0Auth0.podspec index d8509b97..ae040b5d 100644 --- a/A0Auth0.podspec +++ b/A0Auth0.podspec @@ -9,7 +9,7 @@ Pod::Spec.new do |s| s.homepage = package['repository']['baseUrl'] s.license = package['license'] s.authors = package['author'] - s.platforms = { :ios => '13.0' } + s.platforms = { :ios => '13.0', :tvos => '14.0' } s.source = { :git => 'https://github.com/auth0/react-native-auth0.git', :tag => "v#{s.version}" } s.source_files = 'ios/**/*.{h,m,mm,swift}' diff --git a/README.md b/README.md index fe780745..aea86f4f 100644 --- a/README.md +++ b/README.md @@ -37,14 +37,25 @@ The following shows platform minimums for running projects with this SDK: | Platform | Minimum version | | -------- | :-------------: | | iOS | 13.0 | +| tvOS | 14.0 | | Android | 28 | +**iOS** + Our SDK requires a minimum iOS deployment target of 13.0. In your project's ios/Podfile, ensure your platform target is set to 13.0. ``` platform :ios, '13.0' ``` +**tvOS** + +Our SDK requires a minimum tvOS deployment target of 14.0. In your project's ios/Podfile, ensure your platform target is set to 14.0. + +``` +platform :tvos, '14.0' +``` + ### Installation First install the native library module: diff --git a/ios/NativeBridge.swift b/ios/NativeBridge.swift index 3f04481f..d5365390 100644 --- a/ios/NativeBridge.swift +++ b/ios/NativeBridge.swift @@ -37,6 +37,8 @@ public class NativeBridge: NSObject { self.domain = domain self.credentialsManager = CredentialsManager(authentication: auth0) super.init() + + #if os(iOS) if let localAuthenticationOptions = localAuthenticationOptions { if let title = localAuthenticationOptions["title"] as? String { var evaluationPolicy = LAPolicy.deviceOwnerAuthenticationWithBiometrics @@ -51,82 +53,95 @@ public class NativeBridge: NSObject { return } } + #endif + resolve(true) } @objc public func webAuth(state: String?, redirectUri: String, nonce: String?, audience: String?, scope: String?, connection: String?, maxAge: Int, organization: String?, invitationUrl: String?, leeway: Int, ephemeralSession: Bool, safariViewControllerPresentationStyle: Int, additionalParameters: [String: String], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { - let builder = Auth0.webAuth(clientId: self.clientId, domain: self.domain) - if let value = URL(string: redirectUri) { - let _ = builder.redirectURL(value) - } - if let value = state { - let _ = builder.state(value) - } - if let value = nonce { - let _ = builder.nonce(value) - } - if let value = audience { - let _ = builder.audience(value) - } - if let value = scope { - let _ = builder.scope(value) - } - if let value = connection { - let _ = builder.connection(value) - } - if(maxAge != 0) { - let _ = builder.maxAge(maxAge) - } - if let value = organization { - let _ = builder.organization(value) - } - if let value = invitationUrl, let invitationURL = URL(string: value) { - let _ = builder.invitationURL(invitationURL) - } - if(leeway != 0) { - let _ = builder.leeway(leeway) - } - if(ephemeralSession) { - let _ = builder.useEphemeralSession() - } - //Since we cannot have a null value here, the JS layer sends 99 if we have to ignore setting this value - if let presentationStyle = UIModalPresentationStyle(rawValue: safariViewControllerPresentationStyle), safariViewControllerPresentationStyle != 99 { - let _ = builder.provider(WebAuthentication.safariProvider(style: presentationStyle)) - } - let _ = builder - .parameters(additionalParameters) - builder.start { result in - switch result { - case .success(let credentials): - resolve(credentials.asDictionary()) - case .failure(let error): - reject(error.reactNativeErrorCode(), error.errorDescription, error) + #if os(tvOS) + reject("UNSUPPORTED_OPERATION", "webAuth is unsupported on tvOS", nil) + #else + let builder = Auth0.webAuth(clientId: self.clientId, domain: self.domain) + if let value = URL(string: redirectUri) { + let _ = builder.redirectURL(value) } - } - - } - - @objc public func webAuthLogout(federated: Bool, redirectUri: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { - let builder = Auth0.webAuth(clientId: self.clientId, domain: self.domain) - if let value = URL(string: redirectUri) { - let _ = builder.redirectURL(value) - } - builder.clearSession(federated: federated) { result in + if let value = state { + let _ = builder.state(value) + } + if let value = nonce { + let _ = builder.nonce(value) + } + if let value = audience { + let _ = builder.audience(value) + } + if let value = scope { + let _ = builder.scope(value) + } + if let value = connection { + let _ = builder.connection(value) + } + if(maxAge != 0) { + let _ = builder.maxAge(maxAge) + } + if let value = organization { + let _ = builder.organization(value) + } + if let value = invitationUrl, let invitationURL = URL(string: value) { + let _ = builder.invitationURL(invitationURL) + } + if(leeway != 0) { + let _ = builder.leeway(leeway) + } + if(ephemeralSession) { + let _ = builder.useEphemeralSession() + } + //Since we cannot have a null value here, the JS layer sends 99 if we have to ignore setting this value + if let presentationStyle = UIModalPresentationStyle(rawValue: safariViewControllerPresentationStyle), safariViewControllerPresentationStyle != 99 { + let _ = builder.provider(WebAuthentication.safariProvider(style: presentationStyle)) + } + let _ = builder + .parameters(additionalParameters) + builder.start { result in switch result { - case .success: - resolve(true) + case .success(let credentials): + resolve(credentials.asDictionary()) case .failure(let error): reject(error.reactNativeErrorCode(), error.errorDescription, error) } } + #endif + } + + @objc public func webAuthLogout(federated: Bool, redirectUri: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { + #if os(tvOS) + reject("UNSUPPORTED_OPERATION", "webAuthLogout is unsupported on tvOS", nil) + #else + let builder = Auth0.webAuth(clientId: self.clientId, domain: self.domain) + if let value = URL(string: redirectUri) { + let _ = builder.redirectURL(value) + } + builder.clearSession(federated: federated) { result in + switch result { + case .success: + resolve(true) + case .failure(let error): + reject(error.reactNativeErrorCode(), error.errorDescription, error) + } + } + #endif } @objc public func resumeWebAuth(url: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { - if let value = URL(string: url), WebAuthentication.resume(with: value) { - resolve(true) - } else { - reject("ERROR_PARSING_URL", "The callback url \(url) is invalid", nil) - } + #if os(tvOS) + reject("UNSUPPORTED_OPERATION", "resumeWebAuth is unsupported on tvOS", nil) + #else + if let value = URL(string: url), WebAuthentication.resume(with: value) { + resolve(true) + } else { + reject("ERROR_PARSING_URL", "The callback url \(url) is invalid", nil) + } + #endif } @objc public func saveCredentials(credentialsDict: [String: Any], resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { @@ -192,9 +207,11 @@ public class NativeBridge: NSObject { } @objc public func enableLocalAuthentication(title: String?, cancelTitle: String?, fallbackTitle: String?, evaluationPolicy: Int) { - let titleValue = title ?? "Please authenticate to continue" - let policyValue = self.convert(policyInt: evaluationPolicy) - self.credentialsManager.enableBiometrics(withTitle: titleValue, cancelTitle: cancelTitle, fallbackTitle: fallbackTitle, evaluationPolicy: policyValue) + #if os(iOS) + let titleValue = title ?? "Please authenticate to continue" + let policyValue = self.convert(policyInt: evaluationPolicy) + self.credentialsManager.enableBiometrics(withTitle: titleValue, cancelTitle: cancelTitle, fallbackTitle: fallbackTitle, evaluationPolicy: policyValue) + #endif } @objc public func getClientId() -> String { @@ -205,12 +222,14 @@ public class NativeBridge: NSObject { return domain } + #if os(iOS) func convert(policyInt: Int) -> LAPolicy { if (policyInt == 2) { return LAPolicy.deviceOwnerAuthentication } return LAPolicy.deviceOwnerAuthenticationWithBiometrics } + #endif } @@ -227,6 +246,7 @@ extension Credentials { } } +#if os(iOS) extension WebAuthError { func reactNativeErrorCode() -> String { var code: String @@ -247,6 +267,7 @@ extension WebAuthError { return code } } +#endif extension CredentialsManagerError { func reactNativeErrorCode() -> String { @@ -265,7 +286,7 @@ extension CredentialsManagerError { code = cause.code } else { code = "REVOKE_FAILED" - } + } case .largeMinTTL: code = "LARGE_MIN_TTL" default: code = "UNKNOWN" }