react-native-oauth-essentials 1.0.12 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/OauthEssentials.podspec +17 -2
  2. package/README.md +385 -361
  3. package/android/build.gradle +15 -10
  4. package/android/src/main/java/com/oauthessentials/CredentialError.kt +4 -1
  5. package/android/src/main/java/com/oauthessentials/CredentialFactory.kt +24 -2
  6. package/android/src/main/java/com/oauthessentials/CustomTabsActivity.kt +14 -1
  7. package/android/src/main/java/com/oauthessentials/OauthEssentialsModule.kt +445 -187
  8. package/app.plugin.js +1 -0
  9. package/ios/AppleIdRetriever.swift +25 -26
  10. package/ios/CredentialError.swift +3 -0
  11. package/ios/CredentialFactory.swift +38 -20
  12. package/ios/CredentialsType.swift +1 -0
  13. package/ios/GoogleIdRetriever.swift +132 -56
  14. package/ios/HybridRetriever.swift +12 -18
  15. package/ios/OauthEssentials.h +0 -3
  16. package/ios/OauthEssentials.mm +45 -2
  17. package/ios/OauthEssentialsModule.swift +266 -57
  18. package/ios/PasskeyRetriever.swift +31 -49
  19. package/ios/PasswordRetriever.swift +10 -30
  20. package/ios/RCTPromiseSettler.swift +125 -0
  21. package/jest/index.js +149 -0
  22. package/lib/module/NativeOauthEssentials.js +10 -1
  23. package/lib/module/NativeOauthEssentials.js.map +1 -1
  24. package/lib/module/errors.js +38 -0
  25. package/lib/module/errors.js.map +1 -0
  26. package/lib/module/index.js +432 -58
  27. package/lib/module/index.js.map +1 -1
  28. package/lib/module/oauth.js +97 -0
  29. package/lib/module/oauth.js.map +1 -0
  30. package/lib/module/platform.js +108 -0
  31. package/lib/module/platform.js.map +1 -0
  32. package/lib/module/types.js +46 -1
  33. package/lib/module/types.js.map +1 -1
  34. package/lib/typescript/src/NativeOauthEssentials.d.ts +70 -16
  35. package/lib/typescript/src/NativeOauthEssentials.d.ts.map +1 -1
  36. package/lib/typescript/src/errors.d.ts +18 -0
  37. package/lib/typescript/src/errors.d.ts.map +1 -0
  38. package/lib/typescript/src/index.d.ts +235 -40
  39. package/lib/typescript/src/index.d.ts.map +1 -1
  40. package/lib/typescript/src/oauth.d.ts +32 -0
  41. package/lib/typescript/src/oauth.d.ts.map +1 -0
  42. package/lib/typescript/src/platform.d.ts +39 -0
  43. package/lib/typescript/src/platform.d.ts.map +1 -0
  44. package/lib/typescript/src/types.d.ts +190 -2
  45. package/lib/typescript/src/types.d.ts.map +1 -1
  46. package/package.json +9 -5
  47. package/plugin/withOauthEssentials.js +291 -0
  48. package/src/NativeOauthEssentials.ts +91 -17
  49. package/src/errors.ts +49 -0
  50. package/src/index.tsx +587 -80
  51. package/src/oauth.ts +140 -0
  52. package/src/platform.ts +121 -0
  53. package/src/types.ts +200 -1
package/app.plugin.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./plugin/withOauthEssentials');
@@ -5,7 +5,10 @@ public class AppleIdRetriever: RCTPromiseSettler,
5
5
  ASAuthorizationControllerDelegate,
6
6
  ASAuthorizationControllerPresentationContextProviding {
7
7
 
8
- override init(
8
+ private var controller: ASAuthorizationController?
9
+
10
+ init(
11
+ options: NSDictionary,
9
12
  resolve: @escaping RCTPromiseResolveBlock,
10
13
  reject: @escaping RCTPromiseRejectBlock,
11
14
  emitEvent: ((String, NSDictionary) -> Void)?
@@ -13,49 +16,45 @@ public class AppleIdRetriever: RCTPromiseSettler,
13
16
  super.init(resolve: resolve, reject: reject, emitEvent: emitEvent)
14
17
 
15
18
  let controller = ASAuthorizationController(authorizationRequests: [
16
- ASAuthorizationAppleIDProvider().createRequest(),
19
+ AppleIdRetriever.createRequest(options: options),
17
20
  ])
18
-
19
21
  controller.delegate = self
20
22
  controller.presentationContextProvider = self
23
+ self.controller = controller
24
+ controller.performRequests()
25
+ }
21
26
 
22
- if #available(iOS 16.0, *) {
23
- controller.performRequests(options: .preferImmediatelyAvailableCredentials)
24
- } else {
25
- controller.performRequests()
27
+ /// Apple only returns the email and full name on the first sign in, and only when requested.
28
+ static func createRequest(options: NSDictionary?) -> ASAuthorizationAppleIDRequest {
29
+ let request = ASAuthorizationAppleIDProvider().createRequest()
30
+ request.requestedScopes = [.fullName, .email]
31
+ if let nonce = options?["nonce"] as? String {
32
+ request.nonce = nonce
26
33
  }
34
+ if let state = options?["state"] as? String {
35
+ request.state = state
36
+ }
37
+ return request
27
38
  }
28
39
 
29
40
  public func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
30
- return UIWindow()
41
+ return PresentationContext.anchor()
31
42
  }
32
43
 
33
44
  public func authorizationController(
34
45
  controller: ASAuthorizationController,
35
46
  didCompleteWithAuthorization authorization: ASAuthorization
36
47
  ) {
48
+ self.controller = nil
37
49
  if let appleIdCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
38
- let result = CredentialFactory.fromAppleId(appleIdCredential: appleIdCredential)
39
- self.resolve?(result)
40
- self.emitEvent?("onCredentialSuccess", result as NSDictionary)
41
- cleanup()
50
+ succeed(CredentialFactory.fromAppleId(appleIdCredential: appleIdCredential))
51
+ } else {
52
+ fail(.invalidResult, "Unexpected credential type")
42
53
  }
43
54
  }
44
55
 
45
56
  public func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
46
- let nsError = error as NSError
47
- if nsError.domain == ASAuthorizationError.errorDomain,
48
- nsError.code == ASAuthorizationError.canceled.rawValue {
49
-
50
- let result = CredentialFactory.fromCancelled()
51
- self.resolve?(result)
52
- self.emitEvent?("onCredentialSuccess", result as NSDictionary)
53
- } else {
54
- self.emitEvent?("onCredentialFailure", [
55
- "code": CredentialError.invalidResult.rawValue,
56
- "message": error.localizedDescription
57
- ])
58
- }
59
- cleanup()
57
+ self.controller = nil
58
+ finish(authorizationError: error)
60
59
  }
61
60
  }
@@ -3,4 +3,7 @@ public enum CredentialError: String {
3
3
  case invalidResult = "INVALID_RESULT_ERROR"
4
4
  case simultaneousCallError = "SIMULTANEOUS_CALL_ERROR"
5
5
  case notSupportedError = "NOT_SUPPORTED_ERROR"
6
+ case browserUnavailable = "BROWSER_UNAVAILABLE"
7
+ case noActivity = "NO_ACTIVITY_ERROR"
8
+ case configuration = "CONFIGURATION_ERROR"
6
9
  }
@@ -29,7 +29,8 @@ class CredentialFactory {
29
29
  "user": appleIdCredential.user,
30
30
  "email": appleIdCredential.email ?? "",
31
31
  "fullName": fullName,
32
- "likelyReal": appleIdCredential.realUserStatus == .likelyReal
32
+ "likelyReal": appleIdCredential.realUserStatus == .likelyReal,
33
+ "state": appleIdCredential.state ?? NSNull()
33
34
  ]
34
35
 
35
36
  let result: [String: Any] = [
@@ -54,12 +55,12 @@ class CredentialFactory {
54
55
  @available(iOS 16.0, *)
55
56
  public static func fromPasskeyRegistration(credential: ASAuthorizationPlatformPublicKeyCredentialRegistration) -> [String: Any] {
56
57
  let responseJson: [String: Any] = [
57
- "id": base64URLEncode(credential.credentialID),
58
- "rawId": base64URLEncode(credential.credentialID),
58
+ "id": credential.credentialID.base64URLEncodedString(),
59
+ "rawId": credential.credentialID.base64URLEncodedString(),
59
60
  "type": "public-key",
60
61
  "response": [
61
- "clientDataJSON": base64URLEncode(credential.rawClientDataJSON),
62
- "attestationObject": base64URLEncode(credential.rawAttestationObject ?? Data())
62
+ "clientDataJSON": credential.rawClientDataJSON.base64URLEncodedString(),
63
+ "attestationObject": (credential.rawAttestationObject ?? Data()).base64URLEncodedString()
63
64
  ]
64
65
  ]
65
66
 
@@ -80,14 +81,14 @@ class CredentialFactory {
80
81
  @available(iOS 16.0, *)
81
82
  public static func fromPasskeyAssertion(credential: ASAuthorizationPlatformPublicKeyCredentialAssertion) -> [String: Any] {
82
83
  let responseJson: [String: Any] = [
83
- "id": base64URLEncode(credential.credentialID),
84
- "rawId": base64URLEncode(credential.credentialID),
84
+ "id": credential.credentialID.base64URLEncodedString(),
85
+ "rawId": credential.credentialID.base64URLEncodedString(),
85
86
  "type": "public-key",
86
87
  "response": [
87
- "clientDataJSON": base64URLEncode(credential.rawClientDataJSON),
88
- "authenticatorData": base64URLEncode(credential.rawAuthenticatorData),
89
- "signature": base64URLEncode(credential.signature),
90
- "userHandle": base64URLEncode(credential.userID)
88
+ "clientDataJSON": credential.rawClientDataJSON.base64URLEncodedString(),
89
+ "authenticatorData": credential.rawAuthenticatorData.base64URLEncodedString(),
90
+ "signature": credential.signature.base64URLEncodedString(),
91
+ "userHandle": credential.userID.base64URLEncodedString()
91
92
  ]
92
93
  ]
93
94
 
@@ -105,14 +106,7 @@ class CredentialFactory {
105
106
  ]
106
107
  }
107
108
 
108
- private static func base64URLEncode(_ data: Data) -> String {
109
- return data.base64EncodedString()
110
- .replacingOccurrences(of: "+", with: "-")
111
- .replacingOccurrences(of: "/", with: "_")
112
- .replacingOccurrences(of: "=", with: "")
113
- }
114
-
115
- public static func fromGoogleId(user: GIDGoogleUser) -> [String: Any] {
109
+ public static func fromGoogleId(user: GIDGoogleUser, serverAuthCode: String?) -> [String: Any] {
116
110
  let profile = user.profile
117
111
  let data: [String: Any] = [
118
112
  "idToken": user.idToken?.tokenString ?? "",
@@ -121,7 +115,10 @@ class CredentialFactory {
121
115
  "givenName": profile?.givenName ?? "",
122
116
  "familyName": profile?.familyName ?? "",
123
117
  "profilePictureUri": profile?.imageURL(withDimension: 200)?.absoluteString ?? "",
124
- "email": profile?.email ?? ""
118
+ "email": profile?.email ?? "",
119
+ "accessToken": user.accessToken.tokenString,
120
+ "serverAuthCode": serverAuthCode ?? NSNull(),
121
+ "grantedScopes": user.grantedScopes ?? []
125
122
  ]
126
123
 
127
124
  let result: [String: Any] = [
@@ -131,3 +128,24 @@ class CredentialFactory {
131
128
  return result
132
129
  }
133
130
  }
131
+
132
+ /// base64url without padding (RFC 4648 §5), used by WebAuthn and PKCE.
133
+ extension Data {
134
+ func base64URLEncodedString() -> String {
135
+ return base64EncodedString()
136
+ .replacingOccurrences(of: "+", with: "-")
137
+ .replacingOccurrences(of: "/", with: "_")
138
+ .replacingOccurrences(of: "=", with: "")
139
+ }
140
+
141
+ init?(base64URLEncoded string: String) {
142
+ var base64 = string
143
+ .replacingOccurrences(of: "-", with: "+")
144
+ .replacingOccurrences(of: "_", with: "/")
145
+ let remainder = base64.count % 4
146
+ if remainder > 0 {
147
+ base64.append(String(repeating: "=", count: 4 - remainder))
148
+ }
149
+ self.init(base64Encoded: base64)
150
+ }
151
+ }
@@ -4,4 +4,5 @@ public enum CredentialsType: String {
4
4
  case appleId = "APPLE_ID"
5
5
  case cancelled = "CANCELLED"
6
6
  case passkey = "PASSKEY"
7
+ case redirect = "REDIRECT"
7
8
  }
@@ -1,83 +1,159 @@
1
1
  import GoogleSignIn
2
2
  import React
3
3
 
4
+ /// Must be created on the main thread: GIDSignIn presents ASWebAuthenticationSession synchronously.
4
5
  public class GoogleIdRetriever: RCTPromiseSettler {
5
6
 
6
7
  init(
7
8
  clientId: String,
8
9
  options: NSDictionary,
10
+ silent: Bool,
9
11
  resolve: @escaping RCTPromiseResolveBlock,
10
12
  reject: @escaping RCTPromiseRejectBlock,
11
13
  emitEvent: ((String, NSDictionary) -> Void)?
12
14
  ) {
13
15
  super.init(resolve: resolve, reject: reject, emitEvent: emitEvent)
14
- performGoogleSignIn(clientId:clientId, options: options)
15
- }
16
16
 
17
- private func performGoogleSignIn(clientId: String, options: NSDictionary) {
18
- var rootVC: UIViewController?
19
- DispatchQueue.main.sync {
20
- if #available(iOS 13.0, *) {
21
- rootVC = UIApplication.shared.connectedScenes
22
- .compactMap { $0 as? UIWindowScene }
23
- .flatMap { $0.windows }
24
- .first { $0.isKeyWindow }?
25
- .rootViewController
26
- } else {
27
- rootVC = UIApplication.shared.keyWindow?.rootViewController
28
- }
17
+ // GIDSignIn raises an NSException (crashing the app) for a missing client id or, in the
18
+ // interactive flow only, URL scheme, so they are validated here and reported as
19
+ // CONFIGURATION_ERROR instead.
20
+ guard let clientId = Self.resolveClientId(clientId) else {
21
+ fail(
22
+ .configuration,
23
+ "Missing Google iOS client id: pass { iosClientId }, set GIDClientID in Info.plist (the Expo "
24
+ + "plugin does it) or add the Firebase GoogleService-Info.plist to the app target"
25
+ )
26
+ return
29
27
  }
30
-
31
- guard let rootVC = rootVC else {
32
- self.reject?(
33
- CredentialError.noSignInAvailable.rawValue,
34
- "No root view controller available",
35
- nil
28
+ let scheme = Self.urlScheme(for: clientId)
29
+ guard silent || Self.registeredUrlSchemes().contains(scheme) else {
30
+ fail(
31
+ .configuration,
32
+ "Info.plist is missing the URL scheme \"\(scheme)\" required by Google Sign-In. Add it to "
33
+ + "CFBundleURLTypes > CFBundleURLSchemes (it is REVERSED_CLIENT_ID in GoogleService-Info.plist; "
34
+ + "the Expo config plugin adds it). "
35
+ + "\(clientId) must be the iOS client id; web client ids go in serverClientId."
36
36
  )
37
- self.emitEvent?("onCredentialFailure", [
38
- "code": CredentialError.noSignInAvailable.rawValue,
39
- "message": "No root view controller available"
40
- ])
37
+ return
38
+ }
39
+
40
+ GIDSignIn.sharedInstance.configuration = GIDConfiguration(
41
+ clientID: clientId,
42
+ serverClientID: options["serverClientId"] as? String ?? Self.infoPlistString("GIDServerClientID"),
43
+ hostedDomain: options["hostedDomain"] as? String,
44
+ openIDRealm: nil
45
+ )
46
+
47
+ if silent {
48
+ restorePreviousSignIn()
49
+ } else {
50
+ performGoogleSignIn(options: options)
51
+ }
52
+ }
41
53
 
42
- self.cleanup()
54
+ private func performGoogleSignIn(options: NSDictionary) {
55
+ whenBrowserCanOpen("Google Sign-In") { presenter in
56
+ GIDSignIn.sharedInstance.signIn(
57
+ withPresenting: presenter,
58
+ hint: options["hint"] as? String,
59
+ additionalScopes: options["scopes"] as? [String],
60
+ nonce: options["nonce"] as? String
61
+ ) { result, error in
62
+ self.handle(user: result?.user, serverAuthCode: result?.serverAuthCode, error: error)
63
+ }
64
+ }
65
+ }
66
+
67
+ private func restorePreviousSignIn() {
68
+ guard GIDSignIn.sharedInstance.hasPreviousSignIn() else {
69
+ fail(.noSignInAvailable, "No previous Google sign in to restore")
43
70
  return
44
71
  }
45
72
 
46
- GIDSignIn.sharedInstance.configuration = GIDConfiguration(clientID: clientId)
47
- GIDSignIn.sharedInstance.signIn(withPresenting: rootVC) { result, error in
48
-
49
- if let error = error {
50
- let nsError = error as NSError
51
- if nsError.code == GIDSignInError.canceled.rawValue {
52
- let result = CredentialFactory.fromCancelled()
53
- self.resolve?(result)
54
- self.emitEvent?("onCredentialSuccess", result as NSDictionary)
55
- } else {
56
- self.reject?(CredentialError.invalidResult.rawValue, error.localizedDescription, error)
57
- self.emitEvent?("onCredentialFailure", [
58
- "code": CredentialError.invalidResult.rawValue,
59
- "message": error.localizedDescription
60
- ])
61
- }
62
- self.cleanup()
73
+ GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in
74
+ if let error = error as NSError?,
75
+ error.domain == kGIDSignInErrorDomain,
76
+ error.code == GIDSignInError.hasNoAuthInKeychain.rawValue {
77
+ self.fail(.noSignInAvailable, "No previous Google sign in to restore", error)
63
78
  return
64
79
  }
65
-
66
- guard let user = result?.user else {
67
- self.reject?(CredentialError.invalidResult.rawValue, "No user returned", nil)
68
- self.emitEvent?("onCredentialFailure", [
69
- "code": CredentialError.invalidResult.rawValue,
70
- "message": "No user returned"
71
- ])
72
-
73
- self.cleanup()
74
- return
80
+ self.handle(user: user, serverAuthCode: nil, error: error)
81
+ }
82
+ }
83
+
84
+ private func handle(user: GIDGoogleUser?, serverAuthCode: String?, error: Error?) {
85
+ if let error = error {
86
+ let nsError = error as NSError
87
+ if nsError.domain == kGIDSignInErrorDomain,
88
+ nsError.code == GIDSignInError.canceled.rawValue {
89
+ succeed(CredentialFactory.fromCancelled())
90
+ } else if Self.isBrowserUnavailable(nsError) {
91
+ fail(.browserUnavailable, error.localizedDescription, error)
92
+ } else {
93
+ fail(.invalidResult, error.localizedDescription, error)
75
94
  }
95
+ return
96
+ }
97
+
98
+ guard let user = user else {
99
+ fail(.invalidResult, "No user returned")
100
+ return
101
+ }
102
+
103
+ succeed(CredentialFactory.fromGoogleId(user: user, serverAuthCode: serverAuthCode))
104
+ }
105
+
106
+ /// The client id passed from JS or, when it is empty, GIDClientID from Info.plist, then CLIENT_ID
107
+ /// from the Firebase GoogleService-Info.plist.
108
+ private static func resolveClientId(_ clientId: String) -> String? {
109
+ let trimmed = clientId.trimmingCharacters(in: .whitespacesAndNewlines)
110
+ if !trimmed.isEmpty {
111
+ return trimmed
112
+ }
113
+ return infoPlistString("GIDClientID") ?? googleServiceInfoString("CLIENT_ID")
114
+ }
115
+
116
+ private static func infoPlistString(_ key: String) -> String? {
117
+ return nonEmpty(Bundle.main.object(forInfoDictionaryKey: key) as? String)
118
+ }
119
+
120
+ private static func googleServiceInfoString(_ key: String) -> String? {
121
+ guard let path = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist"),
122
+ let values = NSDictionary(contentsOfFile: path) else {
123
+ return nil
124
+ }
125
+ return nonEmpty(values[key] as? String)
126
+ }
127
+
128
+ private static func nonEmpty(_ value: String?) -> String? {
129
+ guard let value = value?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else {
130
+ return nil
131
+ }
132
+ return value
133
+ }
134
+
135
+ /// Same rule as GIDSignInCallbackSchemes: the reversed client id, lowercased.
136
+ private static func urlScheme(for clientId: String) -> String {
137
+ return clientId.split(separator: ".").reversed().joined(separator: ".").lowercased()
138
+ }
139
+
140
+ private static func registeredUrlSchemes() -> Set<String> {
141
+ let urlTypes = Bundle.main.object(forInfoDictionaryKey: "CFBundleURLTypes") as? [[String: Any]] ?? []
142
+ let schemes = urlTypes.flatMap { $0["CFBundleURLSchemes"] as? [String] ?? [] }
143
+ return Set(schemes.map { $0.lowercased() })
144
+ }
76
145
 
77
- let result = CredentialFactory.fromGoogleId(user: user)
78
- self.resolve?(result)
79
- self.emitEvent?("onCredentialSuccess", result as NSDictionary)
80
- self.cleanup()
146
+ /// Fallback for the causes `whenBrowserCanOpen` does not catch. GIDSignIn reports a failed
147
+ /// ASWebAuthenticationSession start as an unknown error that only keeps AppAuth's (not localized)
148
+ /// "Unable to open Safari." message (OIDErrorCodeSafariOpenError = -9).
149
+ private static func isBrowserUnavailable(_ error: NSError) -> Bool {
150
+ if let underlying = error.userInfo[NSUnderlyingErrorKey] as? NSError,
151
+ underlying.domain == "org.openid.appauth.general",
152
+ underlying.code == -9 {
153
+ return true
81
154
  }
155
+ return error.domain == kGIDSignInErrorDomain
156
+ && error.code == GIDSignInError.unknown.rawValue
157
+ && error.localizedDescription.contains("Unable to open Safari")
82
158
  }
83
159
  }
@@ -5,6 +5,8 @@ public class HybridRetriever: RCTPromiseSettler,
5
5
  ASAuthorizationControllerDelegate,
6
6
  ASAuthorizationControllerPresentationContextProviding {
7
7
 
8
+ private var controller: ASAuthorizationController?
9
+
8
10
  init(
9
11
  clientId: String,
10
12
  options: NSDictionary,
@@ -15,12 +17,13 @@ ASAuthorizationControllerPresentationContextProviding {
15
17
  super.init(resolve: resolve, reject: reject, emitEvent: emitEvent)
16
18
 
17
19
  let controller = ASAuthorizationController(authorizationRequests: [
18
- ASAuthorizationAppleIDProvider().createRequest(),
20
+ AppleIdRetriever.createRequest(options: options),
19
21
  ASAuthorizationPasswordProvider().createRequest()
20
22
  ])
21
23
 
22
24
  controller.delegate = self
23
25
  controller.presentationContextProvider = self
26
+ self.controller = controller
24
27
 
25
28
  if #available(iOS 16.0, *) {
26
29
  controller.performRequests(options: .preferImmediatelyAvailableCredentials)
@@ -30,35 +33,26 @@ ASAuthorizationControllerPresentationContextProviding {
30
33
  }
31
34
 
32
35
  public func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
33
- return UIWindow()
36
+ return PresentationContext.anchor()
34
37
  }
35
38
 
36
39
  public func authorizationController(
37
40
  controller: ASAuthorizationController,
38
41
  didCompleteWithAuthorization authorization: ASAuthorization
39
42
  ) {
43
+ self.controller = nil
40
44
  if let appleIdCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
41
- let result = CredentialFactory.fromAppleId(appleIdCredential: appleIdCredential)
42
- self.resolve?(result)
43
- self.emitEvent?("onCredentialSuccess", result as NSDictionary)
45
+ succeed(CredentialFactory.fromAppleId(appleIdCredential: appleIdCredential))
44
46
  }
45
47
  else if let credential = authorization.credential as? ASPasswordCredential {
46
- let result = CredentialFactory.fromPassword(credential: credential)
47
- self.resolve?(result)
48
- self.emitEvent?("onCredentialSuccess", result as NSDictionary)
48
+ succeed(CredentialFactory.fromPassword(credential: credential))
49
+ } else {
50
+ fail(.invalidResult, "Unexpected credential type")
49
51
  }
50
- cleanup()
51
52
  }
52
53
 
53
54
  public func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
54
- self.reject?(
55
- CredentialError.invalidResult.rawValue,
56
- error.localizedDescription,
57
- error
58
- )
59
- self.emitEvent?("onCredentialFailure", [
60
- "code": CredentialError.invalidResult.rawValue,
61
- "message": error.localizedDescription
62
- ])
55
+ self.controller = nil
56
+ finish(authorizationError: error)
63
57
  }
64
58
  }
@@ -2,7 +2,4 @@
2
2
 
3
3
  @interface OauthEssentials : NativeOauthEssentialsSpecBase <NativeOauthEssentialsSpec>
4
4
 
5
- - (void)emitOnCredentialSuccess:(NSDictionary *)value;
6
- - (void)emitOnCredentialFailure:(NSDictionary *)value;
7
-
8
5
  @end
@@ -17,7 +17,9 @@
17
17
  initOnCredentialSuccess:^(NSDictionary * _Nonnull value) {
18
18
  [weakSelf emitOnCredentialSuccess:value];
19
19
  } onCredentialFailure:^(NSDictionary * _Nonnull value) {
20
- [weakSelf emitOnCredentialSuccess:value];
20
+ [weakSelf emitOnCredentialFailure:value];
21
+ } onAppleIdCredentialRevoked:^(NSDictionary * _Nonnull value) {
22
+ [weakSelf emitOnAppleIdCredentialRevoked:value];
21
23
  }];
22
24
  }
23
25
  return self;
@@ -52,6 +54,23 @@
52
54
  rejecter:reject];
53
55
  }
54
56
 
57
+ - (void)googleSilentSignIn:(NSString *)clientId
58
+ options:(NSDictionary *)options
59
+ resolve:(RCTPromiseResolveBlock)resolve
60
+ reject:(RCTPromiseRejectBlock)reject
61
+ {
62
+ [_sModule googleSilentSignIn:clientId
63
+ options:options
64
+ resolver:resolve
65
+ rejecter:reject];
66
+ }
67
+
68
+ - (void)signOut:(RCTPromiseResolveBlock)resolve
69
+ reject:(RCTPromiseRejectBlock)reject
70
+ {
71
+ [_sModule signOut:resolve rejecter:reject];
72
+ }
73
+
55
74
  - (void)passwordSignIn:(NSString *)username
56
75
  password:(NSString *)password
57
76
  resolve:(RCTPromiseResolveBlock)resolve
@@ -80,9 +99,16 @@
80
99
  }
81
100
 
82
101
  - (void)appleSignIn:(NSString *)webAndroidUrl
102
+ options:(NSDictionary *)options
83
103
  resolve:(RCTPromiseResolveBlock)resolve
84
104
  reject:(RCTPromiseRejectBlock)reject {
85
- [_sModule appleSignIn:webAndroidUrl resolver:resolve rejecter:reject];
105
+ [_sModule appleSignIn:webAndroidUrl options:options resolver:resolve rejecter:reject];
106
+ }
107
+
108
+ - (void)getAppleIdCredentialState:(NSString *)userId
109
+ resolve:(RCTPromiseResolveBlock)resolve
110
+ reject:(RCTPromiseRejectBlock)reject {
111
+ [_sModule getAppleIdCredentialState:userId resolver:resolve rejecter:reject];
86
112
  }
87
113
 
88
114
  - (void)createPassKey:(NSDictionary *)options
@@ -97,6 +123,23 @@
97
123
  [_sModule getPassKey:options resolver:resolve rejecter:reject];
98
124
  }
99
125
 
126
+ - (void)cancelPassKeyAutoFill:(RCTPromiseResolveBlock)resolve
127
+ reject:(RCTPromiseRejectBlock)reject {
128
+ [_sModule cancelPassKeyAutoFill:resolve rejecter:reject];
129
+ }
130
+
131
+ - (void)generatePkce:(RCTPromiseResolveBlock)resolve
132
+ reject:(RCTPromiseRejectBlock)reject {
133
+ [_sModule generatePkce:resolve rejecter:reject];
134
+ }
135
+
136
+ - (void)openAuthSession:(NSString *)url
137
+ options:(NSDictionary *)options
138
+ resolve:(RCTPromiseResolveBlock)resolve
139
+ reject:(RCTPromiseRejectBlock)reject {
140
+ [_sModule openAuthSession:url options:options resolver:resolve rejecter:reject];
141
+ }
142
+
100
143
  - (facebook::react::ModuleConstants<JS::NativeOauthEssentials::Constants>) constantsToExport {
101
144
  return (facebook::react::ModuleConstants<JS::NativeOauthEssentials::Constants>)[_sModule getConstants];
102
145
  }