react-native-authsignal 0.4.5 → 1.0.1

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 (74) hide show
  1. package/android/build.gradle +2 -3
  2. package/android/gradle/wrapper/gradle-wrapper.properties +2 -1
  3. package/android/gradle.properties +2 -2
  4. package/android/src/main/java/com/authsignal/react/AuthsignalEmailModule.java +133 -0
  5. package/android/src/main/java/com/authsignal/react/AuthsignalModule.java +10 -2
  6. package/android/src/main/java/com/authsignal/react/AuthsignalPackage.java +4 -1
  7. package/android/src/main/java/com/authsignal/react/AuthsignalPasskeyModule.java +8 -6
  8. package/android/src/main/java/com/authsignal/react/AuthsignalPushModule.java +3 -1
  9. package/android/src/main/java/com/authsignal/react/AuthsignalSMSModule.java +133 -0
  10. package/android/src/main/java/com/authsignal/react/AuthsignalTOTPModule.java +112 -0
  11. package/ios/Authsignal.xcodeproj/project.pbxproj +16 -4
  12. package/ios/AuthsignalEmailModule.m +22 -0
  13. package/ios/AuthsignalEmailModule.swift +109 -0
  14. package/ios/AuthsignalModule.m +9 -63
  15. package/ios/AuthsignalModule.swift +87 -0
  16. package/ios/AuthsignalPasskeyModule.m +1 -1
  17. package/ios/AuthsignalPasskeyModule.swift +11 -9
  18. package/ios/AuthsignalPushModule.m +1 -1
  19. package/ios/AuthsignalPushModule.swift +9 -7
  20. package/ios/AuthsignalSMSModule.m +22 -0
  21. package/ios/AuthsignalSMSModule.swift +109 -0
  22. package/ios/AuthsignalTOTPModule.m +18 -0
  23. package/ios/AuthsignalTOTPModule.swift +82 -0
  24. package/lib/commonjs/email.js +80 -0
  25. package/lib/commonjs/email.js.map +1 -0
  26. package/lib/commonjs/error.js +18 -0
  27. package/lib/commonjs/error.js.map +1 -1
  28. package/lib/commonjs/index.js +27 -0
  29. package/lib/commonjs/index.js.map +1 -1
  30. package/lib/commonjs/passkey.js +4 -4
  31. package/lib/commonjs/passkey.js.map +1 -1
  32. package/lib/commonjs/sms.js +80 -0
  33. package/lib/commonjs/sms.js.map +1 -0
  34. package/lib/commonjs/totp.js +68 -0
  35. package/lib/commonjs/totp.js.map +1 -0
  36. package/lib/module/email.js +73 -0
  37. package/lib/module/email.js.map +1 -0
  38. package/lib/module/error.js +17 -0
  39. package/lib/module/error.js.map +1 -1
  40. package/lib/module/index.js +27 -0
  41. package/lib/module/index.js.map +1 -1
  42. package/lib/module/passkey.js +4 -4
  43. package/lib/module/passkey.js.map +1 -1
  44. package/lib/module/sms.js +73 -0
  45. package/lib/module/sms.js.map +1 -0
  46. package/lib/module/totp.js +61 -0
  47. package/lib/module/totp.js.map +1 -0
  48. package/lib/typescript/email.d.ts +22 -0
  49. package/lib/typescript/email.d.ts.map +1 -0
  50. package/lib/typescript/error.d.ts +9 -0
  51. package/lib/typescript/error.d.ts.map +1 -1
  52. package/lib/typescript/index.d.ts +8 -0
  53. package/lib/typescript/index.d.ts.map +1 -1
  54. package/lib/typescript/passkey.d.ts +3 -3
  55. package/lib/typescript/passkey.d.ts.map +1 -1
  56. package/lib/typescript/push.d.ts +1 -1
  57. package/lib/typescript/sms.d.ts +22 -0
  58. package/lib/typescript/sms.d.ts.map +1 -0
  59. package/lib/typescript/totp.d.ts +22 -0
  60. package/lib/typescript/totp.d.ts.map +1 -0
  61. package/lib/typescript/types.d.ts +10 -2
  62. package/lib/typescript/types.d.ts.map +1 -1
  63. package/package.json +1 -1
  64. package/react-native-authsignal.podspec +1 -1
  65. package/src/email.ts +94 -0
  66. package/src/error.ts +19 -0
  67. package/src/index.tsx +17 -0
  68. package/src/passkey.ts +5 -5
  69. package/src/push.ts +1 -1
  70. package/src/sms.ts +96 -0
  71. package/src/totp.ts +83 -0
  72. package/src/types.ts +12 -2
  73. package/yarn.lock +109 -83
  74. package/ios/AuthsignalModule.h +0 -11
@@ -0,0 +1,109 @@
1
+ import Security
2
+ import Foundation
3
+ import Authsignal
4
+
5
+ @objc(AuthsignalEmailModule)
6
+ class AuthsignalEmailModule: NSObject {
7
+ var authsignal: AuthsignalEmail?
8
+
9
+ @objc static func requiresMainQueueSetup() -> Bool {
10
+ return true
11
+ }
12
+
13
+ @objc func initialize(
14
+ _ tenantID: NSString,
15
+ withBaseURL baseURL: NSString,
16
+ resolver resolve: @escaping RCTPromiseResolveBlock,
17
+ rejecter reject: @escaping RCTPromiseRejectBlock
18
+ ) -> Void {
19
+ self.authsignal = AuthsignalEmail(tenantID: tenantID as String, baseURL: baseURL as String)
20
+
21
+ resolve(nil)
22
+ }
23
+
24
+ @objc func enroll(
25
+ _ email: NSString,
26
+ resolver resolve: @escaping RCTPromiseResolveBlock,
27
+ rejecter reject: @escaping RCTPromiseRejectBlock
28
+ ) -> Void {
29
+ if (authsignal == nil) {
30
+ resolve(nil)
31
+ return
32
+ }
33
+
34
+ let emailStr = email as String
35
+
36
+ Task.init {
37
+ let response = await authsignal!.enroll(email: emailStr)
38
+
39
+ if (response.errorCode == "TOKEN_NOT_SET") {
40
+ reject("tokenNotSetError", "TOKEN_NOT_SET", nil)
41
+ } else if (response.error != nil) {
42
+ reject("enrollError", response.error, nil)
43
+ } else {
44
+ let enrollResponse: [String: String?] = [
45
+ "userAuthenticatorId": response.data!.userAuthenticatorId,
46
+ ]
47
+
48
+ resolve(enrollResponse)
49
+ }
50
+ }
51
+ }
52
+
53
+ @objc func challenge(
54
+ _ resolve: @escaping RCTPromiseResolveBlock,
55
+ rejecter reject: @escaping RCTPromiseRejectBlock
56
+ ) -> Void {
57
+ if (authsignal == nil) {
58
+ resolve(nil)
59
+ return
60
+ }
61
+
62
+ Task.init {
63
+ let response = await authsignal!.challenge()
64
+
65
+ if (response.errorCode == "TOKEN_NOT_SET") {
66
+ reject("tokenNotSetError", "TOKEN_NOT_SET", nil)
67
+ } else if (response.error != nil) {
68
+ reject("challengeError", response.error, nil)
69
+ } else {
70
+ let challengeResponse: [String: String?] = [
71
+ "challengeId": response.data!.challengeId,
72
+ ]
73
+
74
+ resolve(challengeResponse)
75
+ }
76
+ }
77
+ }
78
+
79
+ @objc func verify(
80
+ _ code: NSString,
81
+ resolver resolve: @escaping RCTPromiseResolveBlock,
82
+ rejecter reject: @escaping RCTPromiseRejectBlock
83
+ ) -> Void {
84
+ if (authsignal == nil) {
85
+ resolve(nil)
86
+ return
87
+ }
88
+
89
+ let codeStr = code as String
90
+
91
+ Task.init {
92
+ let response = await authsignal!.verify(code: codeStr)
93
+
94
+ if (response.errorCode == "TOKEN_NOT_SET") {
95
+ reject("tokenNotSetError", "TOKEN_NOT_SET", nil)
96
+ } else if (response.error != nil) {
97
+ reject("verifyError", response.error, nil)
98
+ } else {
99
+ let verifyResponse: [String: Any?] = [
100
+ "isVerified": response.data!.isVerified,
101
+ "token": response.data!.token,
102
+ "failureReason": response.data!.failureReason,
103
+ ]
104
+
105
+ resolve(verifyResponse)
106
+ }
107
+ }
108
+ }
109
+ }
@@ -1,68 +1,14 @@
1
- #import "AuthsignalModule.h"
2
- #import <React/RCTConvert.h>
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <Foundation/Foundation.h>
3
3
 
4
- @interface AuthsignalModule ()
5
- @property (strong, nonatomic) NSObject *session;
6
- @end
7
-
8
- @implementation AuthsignalModule
9
-
10
- RCT_EXPORT_MODULE();
4
+ @interface RCT_EXTERN_MODULE(AuthsignalModule, NSObject)
11
5
 
12
- - (dispatch_queue_t)methodQueue
13
- {
14
- return dispatch_get_main_queue();
15
- }
6
+ RCT_EXTERN_METHOD(launch:(NSString)url
7
+ resolver:(RCTPromiseResolveBlock)resolve
8
+ rejecter:(RCTPromiseRejectBlock)reject)
16
9
 
17
- RCT_EXPORT_METHOD(launch:(NSString *)url resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
18
- {
19
- NSURL *authUrl = [RCTConvert NSURL:url];
20
- NSString *scheme = @"authsignal";
21
-
22
- ASWebAuthenticationSession* authenticationSession = [[ASWebAuthenticationSession alloc] initWithURL:authUrl
23
- callbackURLScheme:scheme
24
- completionHandler:^(NSURL * _Nullable callbackURL,
25
- NSError * _Nullable error) {
26
- if (callbackURL) {
27
- NSURLComponents *components = [[NSURLComponents alloc] initWithString:callbackURL.absoluteString];
28
- NSString *token;
29
-
30
- for (NSURLQueryItem *item in components.queryItems) {
31
- if ([item.name isEqualToString:@"token"]) {
32
- token = item.value;
33
- }
34
- }
35
-
36
- resolve(token);
37
- } else if (error) {
38
- if ([[error domain] isEqualToString:ASWebAuthenticationSessionErrorDomain] &&
39
- [error code] == ASWebAuthenticationSessionErrorCodeCanceledLogin) {
40
- resolve(nil);
41
- } else {
42
- reject(@"AS_ERROR", error.description, nil);
43
- }
44
- }
45
-
46
- self.session = nil;
47
- }];
48
-
49
- #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
50
- if (@available(iOS 13, *)) {
51
- authenticationSession.presentationContextProvider = self;
52
- authenticationSession.prefersEphemeralWebBrowserSession = NO;
53
- }
54
- #endif
55
-
56
- self.session = authenticationSession;
57
-
58
- [(ASWebAuthenticationSession*) self.session start];
59
- }
60
-
61
- #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
62
- - (ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:(ASWebAuthenticationSession *)session API_AVAILABLE(ios(13.0)){
63
- return UIApplication.sharedApplication.keyWindow;
64
- }
65
- #endif
10
+ RCT_EXTERN_METHOD(setToken:(NSString)token
11
+ resolver:(RCTPromiseResolveBlock)resolve
12
+ rejecter:(RCTPromiseRejectBlock)reject)
66
13
 
67
14
  @end
68
-
@@ -0,0 +1,87 @@
1
+ import AuthenticationServices
2
+ import Authsignal
3
+ import Foundation
4
+ import React
5
+ import Security
6
+
7
+ @objc(AuthsignalModule)
8
+ class AuthsignalModule: NSObject, ASWebAuthenticationPresentationContextProviding {
9
+ var session: ASWebAuthenticationSession?
10
+
11
+ @objc static func requiresMainQueueSetup() -> Bool {
12
+ return true
13
+ }
14
+
15
+ @objc func methodQueue() -> DispatchQueue {
16
+ return DispatchQueue.main
17
+ }
18
+
19
+ @objc func launch(
20
+ _ url: NSString,
21
+ resolver resolve: @escaping RCTPromiseResolveBlock,
22
+ rejecter reject: @escaping RCTPromiseRejectBlock
23
+ ) -> Void {
24
+ let scheme = "authsignal"
25
+ let urlStr = url as String?
26
+
27
+ guard let authUrl = URL(string: urlStr!) else {
28
+ reject("AS_ERROR", "Invalid URL", nil)
29
+
30
+ return
31
+ }
32
+
33
+ let authenticationSession = ASWebAuthenticationSession(url: authUrl, callbackURLScheme: scheme) { callbackURL, error in
34
+ if let error {
35
+ if self.isCanceledLoginError(error) {
36
+ resolve(nil)
37
+ } else {
38
+ reject("AS_ERROR", error.localizedDescription, nil)
39
+ }
40
+ } else if let callbackURL = callbackURL {
41
+ let components = URLComponents(string: callbackURL.absoluteString)
42
+ var token: String?
43
+
44
+ for item in components?.queryItems ?? [] {
45
+ if item.name == "token" {
46
+ token = item.value
47
+
48
+ TokenCache.shared.token = item.value
49
+ }
50
+ }
51
+
52
+ resolve(token)
53
+ }
54
+
55
+ self.session = nil
56
+ }
57
+
58
+ #if os(iOS) && swift(>=5.1)
59
+ if #available(iOS 13, *) {
60
+ authenticationSession.presentationContextProvider = self
61
+ authenticationSession.prefersEphemeralWebBrowserSession = false
62
+ }
63
+ #endif
64
+
65
+ self.session = authenticationSession
66
+
67
+ self.session?.start()
68
+ }
69
+
70
+ @objc func setToken(
71
+ _ token: NSString,
72
+ resolver resolve: @escaping RCTPromiseResolveBlock,
73
+ rejecter reject: @escaping RCTPromiseRejectBlock
74
+ ) -> Void {
75
+ TokenCache.shared.token = token as String
76
+
77
+ resolve("token_set")
78
+ }
79
+
80
+ private func isCanceledLoginError(_ error: Error) -> Bool {
81
+ (error as NSError).code == ASWebAuthenticationSessionError.canceledLogin.rawValue
82
+ }
83
+
84
+ func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
85
+ return UIApplication.shared.keyWindow!
86
+ }
87
+ }
@@ -9,7 +9,7 @@ RCT_EXTERN_METHOD(initialize:(NSString)tenantID
9
9
  rejecter:(RCTPromiseRejectBlock)reject)
10
10
 
11
11
  RCT_EXTERN_METHOD(signUp:(NSString)token
12
- withUserName:(NSString)userName
12
+ withUsername:(NSString)username
13
13
  withDisplayName:(NSString)displayName
14
14
  resolver:(RCTPromiseResolveBlock)resolve
15
15
  rejecter:(RCTPromiseRejectBlock)reject)
@@ -22,8 +22,8 @@ class AuthsignalPasskeyModule: NSObject {
22
22
  }
23
23
 
24
24
  @objc func signUp(
25
- _ token: NSString,
26
- withUserName userName: NSString?,
25
+ _ token: NSString?,
26
+ withUsername username: NSString?,
27
27
  withDisplayName displayName: NSString?,
28
28
  resolver resolve: @escaping RCTPromiseResolveBlock,
29
29
  rejecter reject: @escaping RCTPromiseRejectBlock
@@ -33,14 +33,16 @@ class AuthsignalPasskeyModule: NSObject {
33
33
  return
34
34
  }
35
35
 
36
- let tokenStr = token as String
37
- let userNameStr = userName as String?
36
+ let tokenStr = token as String?
37
+ let usernameStr = username as String?
38
38
  let displayNameStr = displayName as String?
39
39
 
40
40
  Task.init {
41
- let response = await authsignal!.signUp(token: tokenStr, userName: userNameStr, displayName: displayNameStr)
41
+ let response = await authsignal!.signUp(token: tokenStr, username: usernameStr, displayName: displayNameStr)
42
42
 
43
- if (response.error != nil) {
43
+ if (response.errorCode == "TOKEN_NOT_SET") {
44
+ reject("tokenNotSetError", "TOKEN_NOT_SET", nil)
45
+ } else if (response.error != nil) {
44
46
  reject("signUpError", response.error, nil)
45
47
  } else {
46
48
  let signUpResponse: [String: String?] = [
@@ -76,7 +78,7 @@ class AuthsignalPasskeyModule: NSObject {
76
78
  preferImmediatelyAvailableCredentials: preferImmediatelyAvailableCredentials
77
79
  )
78
80
 
79
- if (response.errorCode == .canceled) {
81
+ if (response.errorCode == "SIGN_IN_CANCELED") {
80
82
  reject("signInCanceled", "SIGN_IN_CANCELED", nil)
81
83
  } else if (response.error != nil) {
82
84
  reject("signInError", response.error, nil)
@@ -86,8 +88,8 @@ class AuthsignalPasskeyModule: NSObject {
86
88
  "token": response.data!.token,
87
89
  "userId": response.data!.userId,
88
90
  "userAuthenticatorId": response.data!.userAuthenticatorId,
89
- "userName": response.data!.userName,
90
- "userDisplayName": response.data!.userDisplayName,
91
+ "username": response.data!.username,
92
+ "displayName": response.data!.displayName,
91
93
  ]
92
94
 
93
95
  resolve(signInResponse)
@@ -21,7 +21,7 @@ RCT_EXTERN_METHOD(removeCredential:(RCTPromiseResolveBlock)resolve
21
21
  RCT_EXTERN_METHOD(getChallenge:(RCTPromiseResolveBlock)resolve
22
22
  rejecter:(RCTPromiseRejectBlock)reject)
23
23
 
24
- RCT_EXTERN_METHOD(updateChallenge:(NSString)challengeID
24
+ RCT_EXTERN_METHOD(updateChallenge:(NSString)challengeId
25
25
  withApproval:(BOOL)approved
26
26
  withVerificationCode:(NSString)verificationCode
27
27
  resolver:(RCTPromiseResolveBlock)resolve
@@ -37,7 +37,7 @@ class AuthsignalPushModule: NSObject {
37
37
  reject("getCredential error", error, nil)
38
38
  } else if let data = response.data {
39
39
  let credential: [String: String?] = [
40
- "credentialID": response.data!.credentialID,
40
+ "credentialId": response.data!.credentialId,
41
41
  "createdAt": response.data!.createdAt,
42
42
  "lastAuthenticatedAt": response.data!.lastAuthenticatedAt,
43
43
  ]
@@ -50,7 +50,7 @@ class AuthsignalPushModule: NSObject {
50
50
  }
51
51
 
52
52
  @objc func addCredential(
53
- _ token: NSString,
53
+ _ token: NSString?,
54
54
  resolver resolve: @escaping RCTPromiseResolveBlock,
55
55
  rejecter reject: @escaping RCTPromiseRejectBlock
56
56
  ) -> Void {
@@ -59,12 +59,14 @@ class AuthsignalPushModule: NSObject {
59
59
  return
60
60
  }
61
61
 
62
- let tokenStr = token as String
62
+ let tokenStr = token as String?
63
63
 
64
64
  Task.init {
65
65
  let response = await authsignal.addCredential(token: tokenStr)
66
66
 
67
- if let error = response.error {
67
+ if (response.errorCode == "TOKEN_NOT_SET") {
68
+ reject("tokenNotSetError", "TOKEN_NOT_SET", nil)
69
+ } else if let error = response.error {
68
70
  reject("addCredential error", error, nil)
69
71
  } else {
70
72
  resolve(response.data)
@@ -113,7 +115,7 @@ class AuthsignalPushModule: NSObject {
113
115
  }
114
116
 
115
117
  @objc func updateChallenge(
116
- _ challengeID: NSString,
118
+ _ challengeId: NSString,
117
119
  withApproval approved: Bool,
118
120
  withVerificationCode verificationCode: NSString,
119
121
  resolver resolve: @escaping RCTPromiseResolveBlock,
@@ -124,13 +126,13 @@ class AuthsignalPushModule: NSObject {
124
126
  return
125
127
  }
126
128
 
127
- let challenge = challengeID as String
129
+ let challenge = challengeId as String
128
130
  let approval = approved as Bool
129
131
  let code = verificationCode as String?
130
132
 
131
133
  Task.init {
132
134
  let response = await authsignal.updateChallenge(
133
- challengeID: challenge,
135
+ challengeId: challenge,
134
136
  approved: approval,
135
137
  verificationCode: code
136
138
  )
@@ -0,0 +1,22 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <Foundation/Foundation.h>
3
+
4
+ @interface RCT_EXTERN_MODULE(AuthsignalSMSModule, NSObject)
5
+
6
+ RCT_EXTERN_METHOD(initialize:(NSString)tenantID
7
+ withBaseURL:(NSString)baseURL
8
+ resolver:(RCTPromiseResolveBlock)resolve
9
+ rejecter:(RCTPromiseRejectBlock)reject)
10
+
11
+ RCT_EXTERN_METHOD(enroll:(NSString)phoneNumber
12
+ resolver:(RCTPromiseResolveBlock)resolve
13
+ rejecter:(RCTPromiseRejectBlock)reject)
14
+
15
+ RCT_EXTERN_METHOD(challenge:(RCTPromiseResolveBlock)resolve
16
+ rejecter:(RCTPromiseRejectBlock)reject)
17
+
18
+ RCT_EXTERN_METHOD(verify:(NSString)code
19
+ resolver:(RCTPromiseResolveBlock)resolve
20
+ rejecter:(RCTPromiseRejectBlock)reject)
21
+
22
+ @end
@@ -0,0 +1,109 @@
1
+ import Security
2
+ import Foundation
3
+ import Authsignal
4
+
5
+ @objc(AuthsignalSMSModule)
6
+ class AuthsignalSMSModule: NSObject {
7
+ var authsignal: AuthsignalSMS?
8
+
9
+ @objc static func requiresMainQueueSetup() -> Bool {
10
+ return true
11
+ }
12
+
13
+ @objc func initialize(
14
+ _ tenantID: NSString,
15
+ withBaseURL baseURL: NSString,
16
+ resolver resolve: @escaping RCTPromiseResolveBlock,
17
+ rejecter reject: @escaping RCTPromiseRejectBlock
18
+ ) -> Void {
19
+ self.authsignal = AuthsignalSMS(tenantID: tenantID as String, baseURL: baseURL as String)
20
+
21
+ resolve(nil)
22
+ }
23
+
24
+ @objc func enroll(
25
+ _ phoneNumber: NSString,
26
+ resolver resolve: @escaping RCTPromiseResolveBlock,
27
+ rejecter reject: @escaping RCTPromiseRejectBlock
28
+ ) -> Void {
29
+ if (authsignal == nil) {
30
+ resolve(nil)
31
+ return
32
+ }
33
+
34
+ let phoneNumberStr = phoneNumber as String
35
+
36
+ Task.init {
37
+ let response = await authsignal!.enroll(phoneNumber: phoneNumberStr)
38
+
39
+ if (response.errorCode == "TOKEN_NOT_SET") {
40
+ reject("tokenNotSetError", "TOKEN_NOT_SET", nil)
41
+ } else if (response.error != nil) {
42
+ reject("enrollError", response.error, nil)
43
+ } else {
44
+ let enrollResponse: [String: String?] = [
45
+ "userAuthenticatorId": response.data!.userAuthenticatorId,
46
+ ]
47
+
48
+ resolve(enrollResponse)
49
+ }
50
+ }
51
+ }
52
+
53
+ @objc func challenge(
54
+ _ resolve: @escaping RCTPromiseResolveBlock,
55
+ rejecter reject: @escaping RCTPromiseRejectBlock
56
+ ) -> Void {
57
+ if (authsignal == nil) {
58
+ resolve(nil)
59
+ return
60
+ }
61
+
62
+ Task.init {
63
+ let response = await authsignal!.challenge()
64
+
65
+ if (response.errorCode == "TOKEN_NOT_SET") {
66
+ reject("tokenNotSetError", "TOKEN_NOT_SET", nil)
67
+ } else if (response.error != nil) {
68
+ reject("challengeError", response.error, nil)
69
+ } else {
70
+ let challengeResponse: [String: String?] = [
71
+ "challengeId": response.data!.challengeId,
72
+ ]
73
+
74
+ resolve(challengeResponse)
75
+ }
76
+ }
77
+ }
78
+
79
+ @objc func verify(
80
+ _ code: NSString,
81
+ resolver resolve: @escaping RCTPromiseResolveBlock,
82
+ rejecter reject: @escaping RCTPromiseRejectBlock
83
+ ) -> Void {
84
+ if (authsignal == nil) {
85
+ resolve(nil)
86
+ return
87
+ }
88
+
89
+ let codeStr = code as String
90
+
91
+ Task.init {
92
+ let response = await authsignal!.verify(code: codeStr)
93
+
94
+ if (response.errorCode == "TOKEN_NOT_SET") {
95
+ reject("tokenNotSetError", "TOKEN_NOT_SET", nil)
96
+ } else if (response.error != nil) {
97
+ reject("verifyError", response.error, nil)
98
+ } else {
99
+ let verifyResponse: [String: Any?] = [
100
+ "isVerified": response.data!.isVerified,
101
+ "token": response.data!.token,
102
+ "failureReason": response.data!.failureReason,
103
+ ]
104
+
105
+ resolve(verifyResponse)
106
+ }
107
+ }
108
+ }
109
+ }
@@ -0,0 +1,18 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <Foundation/Foundation.h>
3
+
4
+ @interface RCT_EXTERN_MODULE(AuthsignalTOTPModule, NSObject)
5
+
6
+ RCT_EXTERN_METHOD(initialize:(NSString)tenantID
7
+ withBaseURL:(NSString)baseURL
8
+ resolver:(RCTPromiseResolveBlock)resolve
9
+ rejecter:(RCTPromiseRejectBlock)reject)
10
+
11
+ RCT_EXTERN_METHOD(enroll:(RCTPromiseResolveBlock)resolve
12
+ rejecter:(RCTPromiseRejectBlock)reject)
13
+
14
+ RCT_EXTERN_METHOD(verify:(NSString)code
15
+ resolver:(RCTPromiseResolveBlock)resolve
16
+ rejecter:(RCTPromiseRejectBlock)reject)
17
+
18
+ @end
@@ -0,0 +1,82 @@
1
+ import Security
2
+ import Foundation
3
+ import Authsignal
4
+
5
+ @objc(AuthsignalTOTPModule)
6
+ class AuthsignalTOTPModule: NSObject {
7
+ var authsignal: AuthsignalTOTP?
8
+
9
+ @objc static func requiresMainQueueSetup() -> Bool {
10
+ return true
11
+ }
12
+
13
+ @objc func initialize(
14
+ _ tenantID: NSString,
15
+ withBaseURL baseURL: NSString,
16
+ resolver resolve: @escaping RCTPromiseResolveBlock,
17
+ rejecter reject: @escaping RCTPromiseRejectBlock
18
+ ) -> Void {
19
+ self.authsignal = AuthsignalTOTP(tenantID: tenantID as String, baseURL: baseURL as String)
20
+
21
+ resolve(nil)
22
+ }
23
+
24
+ @objc func enroll(
25
+ _ resolve: @escaping RCTPromiseResolveBlock,
26
+ rejecter reject: @escaping RCTPromiseRejectBlock
27
+ ) -> Void {
28
+ if (authsignal == nil) {
29
+ resolve(nil)
30
+ return
31
+ }
32
+
33
+ Task.init {
34
+ let response = await authsignal!.enroll()
35
+
36
+ if (response.errorCode == "TOKEN_NOT_SET") {
37
+ reject("tokenNotSetError", "TOKEN_NOT_SET", nil)
38
+ } else if (response.error != nil) {
39
+ reject("enrollError", response.error, nil)
40
+ } else {
41
+ let enrollResponse: [String: String?] = [
42
+ "userAuthenticatorId": response.data!.userAuthenticatorId,
43
+ "uri": response.data!.uri,
44
+ "secret": response.data!.secret,
45
+ ]
46
+
47
+ resolve(enrollResponse)
48
+ }
49
+ }
50
+ }
51
+
52
+ @objc func verify(
53
+ _ code: NSString,
54
+ resolver resolve: @escaping RCTPromiseResolveBlock,
55
+ rejecter reject: @escaping RCTPromiseRejectBlock
56
+ ) -> Void {
57
+ if (authsignal == nil) {
58
+ resolve(nil)
59
+ return
60
+ }
61
+
62
+ let codeStr = code as String
63
+
64
+ Task.init {
65
+ let response = await authsignal!.verify(code: codeStr)
66
+
67
+ if (response.errorCode == "TOKEN_NOT_SET") {
68
+ reject("tokenNotSetError", "TOKEN_NOT_SET", nil)
69
+ } else if (response.error != nil) {
70
+ reject("verifyError", response.error, nil)
71
+ } else {
72
+ let verifyResponse: [String: Any?] = [
73
+ "isVerified": response.data!.isVerified,
74
+ "token": response.data!.token,
75
+ "failureReason": response.data!.failureReason,
76
+ ]
77
+
78
+ resolve(verifyResponse)
79
+ }
80
+ }
81
+ }
82
+ }