@pagopa/io-react-native-cie 1.2.0 → 1.2.2

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.
@@ -16,7 +16,7 @@ Pod::Spec.new do |s|
16
16
  s.source_files = "ios/**/*.{h,m,mm,swift}"
17
17
 
18
18
  # CieSDK dependency
19
- s.dependency "CieSDK", "~> 0.1.12"
19
+ s.dependency "CieSDK", "~> 0.1.13"
20
20
 
21
21
  # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
22
22
  # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
package/README.md CHANGED
@@ -73,14 +73,15 @@ More info in the [official Android documentation](https://developer.android.com/
73
73
  <string>We need to use NFC</string>
74
74
  ```
75
75
  [More info on Apple's doc](https://developer.apple.com/documentation/bundleresources/information-property-list/nfcreaderusagedescription?language=objc)
76
- 3. Add the required ISO7816 identifiers into your `info.plist`
76
+ 3. Add the required ISO7816 identifiers into your `info.plist`. **IMPORTART**: the NFC tags order is important!
77
77
  ```xml
78
78
  <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
79
79
  <array>
80
- <string>A0000000308000000009816001</string>
81
- <string>A00000000039</string>
82
- <string>A0000002471001</string>
83
- <string>00000000000000</string>
80
+ <string>A0000002471001</string>
81
+ <string>A0000000308000000009816001</string>
82
+ <string>A00000000039</string>
83
+ <string>A0000002472001</string>
84
+ <string>00000000000000</string>
84
85
  </array>
85
86
  ```
86
87
  [More info on Apple's doc](https://developer.apple.com/documentation/corenfc/nfciso7816tag).
@@ -97,22 +98,24 @@ To run the example app, follow the instructions in [example/README.md](./example
97
98
 
98
99
  List of available functions
99
100
 
100
- | Function | Return | Description |
101
- | :---------------------------------------------------------------------- | :----------------- | :----------------------------------------------------------------------------- |
102
- | `hasNFCFeature()` | `Promise<boolean>` | (Android) Checks if the device supports NFC feature |
103
- | `isNfcEnabled()` | `Promise<boolean>` | (Android) Checks if the NFC is currently enabled |
104
- | `isCieAuthenticationSupported()` | `Promise<boolean>` | (Android) Checks if the device supports CIE autentication |
105
- | `openNfcSettings()` | `Promise<void>` | (Android) Opens NFC system settings page |
106
- | `addListener(event: CieEvent, listener: CieEventHandlers)` | `() => void` | Adds a NFC event listener and returns a function to unsubscribe from the event |
107
- | `removeListener(event: CieEvent)` | `void` | Removes all listeners for the specified event |
108
- | `removeAllListeners()` | `void` | Removes all registered listeners |
109
- | `setCustomIdpUrl(url?: string)` | `void` | Updates IDP url, if `undefined` will use the default IDP url |
110
- | `setAlertMessage(key: AlertMessageKey, value: string)` | `void` | (iOS) Updates iOS NFC modal alert message |
111
- | `setCurrentAlertMessage(value: string)` | `void` | (iOS) Updates currently displayed iOS NFC modal alert message |
112
- | `startInternalAuthentication(challenge: string)` | `Promise<void>` | Start the CIE IAS/NIS Internal Authentication |
113
- | `startReadingAttributes(timeout: number)` | `Promise<void>` | Start the CIE attributes reading process |
114
- | `startReading(pin: string, authenticationUrl: string, timeout: number)` | `Promise<void>` | Start the CIE reading process fro authentication |
115
- | `stopReading()` | `Promise<void>` | (Android) Stops all reading process |
101
+ | Function | Return | Description |
102
+ | :------------------------------------------------------------------------------------------------------------------- | :----------------- | :----------------------------------------------------------------------------- |
103
+ | `hasNFCFeature()` | `Promise<boolean>` | (Android) Checks if the device supports NFC feature |
104
+ | `isNfcEnabled()` | `Promise<boolean>` | (Android) Checks if the NFC is currently enabled |
105
+ | `isCieAuthenticationSupported()` | `Promise<boolean>` | (Android) Checks if the device supports CIE autentication |
106
+ | `openNfcSettings()` | `Promise<void>` | (Android) Opens NFC system settings page |
107
+ | `addListener(event: CieEvent, listener: CieEventHandlers)` | `() => void` | Adds a NFC event listener and returns a function to unsubscribe from the event |
108
+ | `removeListener(event: CieEvent)` | `void` | Removes all listeners for the specified event |
109
+ | `removeAllListeners()` | `void` | Removes all registered listeners |
110
+ | `setCustomIdpUrl(url?: string)` | `void` | Updates IDP url, if `undefined` will use the default IDP url |
111
+ | `setAlertMessage(key: AlertMessageKey, value: string)` | `void` | (iOS) Updates iOS NFC modal alert message |
112
+ | `setCurrentAlertMessage(value: string)` | `void` | (iOS) Updates currently displayed iOS NFC modal alert message |
113
+ | `startInternalAuthentication(challenge: string, resultEncoding?: ResultEncoding, timeout?: number)` | `Promise<void>` | Start the CIE IAS/NIS Internal Authentication |
114
+ | `startMRTDReading(can: string, resultEncoding?: ResultEncoding, timeout?: number)` | `Promise<void>` | Start PACE MRTD reading (reads MRTD data using CAN) |
115
+ | `startInternalAuthAndMRTDReading(can: string, challenge: string, resultEncoding?: ResultEncoding, timeout?: number)` | `Promise<void>` | Start combined Internal Authentication + PACE MRTD reading |
116
+ | `startReadingAttributes(timeout: number)` | `Promise<void>` | Start the CIE attributes reading process |
117
+ | `startReading(pin: string, authenticationUrl: string, timeout: number)` | `Promise<void>` | Start the CIE reading process fro authentication |
118
+ | `stopReading()` | `Promise<void>` | (Android) Stops all reading process |
116
119
 
117
120
  ## Usage
118
121
 
@@ -394,6 +397,54 @@ type NfcError = {
394
397
 
395
398
  Error event that may be sent during the CIE reading process. Contains the name of the error and an optional message. Error names and order may vary based on the platform.
396
399
 
400
+ ```typescript
401
+ type InternalAuthResponse = {
402
+ nis: string,
403
+ publicKey: string,
404
+ sod: string,
405
+ signedChallenge: string,
406
+ });
407
+ ```
408
+
409
+ Represent the CIE response coming from NIS Internal Auth.
410
+ All string value are Hex, Base64 or Base64 url encoded
411
+
412
+ ```typescript
413
+ type MrtdResponse = {
414
+ dg1: string,
415
+ dg11: string,
416
+ sod: string,
417
+ });
418
+ ```
419
+
420
+ Represent the CIE response coming from MRTD with PACE reading
421
+ All string value are Hex, Base64 or Base64 url encoded.
422
+
423
+ ```typescript
424
+ type InternalAuthAndMrtdResponse = {
425
+ nis_data: {
426
+ nis: string,
427
+ publicKey: string,
428
+ sod: string,
429
+ signedChallenge: string,
430
+ },
431
+ mrtd_data: {
432
+ dg1: string,
433
+ dg11: string,
434
+ sod: string,
435
+ },
436
+ });
437
+ ```
438
+
439
+ Represent the CIE response coming from NIS Internal Auth and MRTD with PACE reading during the same NFC session.
440
+ All string value are Hex, Base64 or Base64 url encoded.
441
+
442
+ ```typescript
443
+ type ResultEncoding = 'hex' | 'base64' | 'base64url';
444
+ ```
445
+
446
+ Supported types of encoding for Internal Auth and Mrtd reponse payloads.
447
+
397
448
  ## Errors
398
449
 
399
450
  The CIE reading function may throw exceptions if the reading process cannot be initiated. These exceptions indicate issues with input validation or system compatibility.
@@ -78,6 +78,6 @@ dependencies {
78
78
  implementation "com.facebook.react:react-android"
79
79
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
80
80
  // CIE SDK
81
- implementation "it.pagopa.io.app.cie:cie:0.1.5"
81
+ implementation "it.pagopa.io.app.cie:cie:0.1.7"
82
82
  }
83
83
 
@@ -5,18 +5,24 @@ import com.facebook.react.bridge.Promise
5
5
  import com.facebook.react.bridge.ReactApplicationContext
6
6
  import com.facebook.react.bridge.ReactContextBaseJavaModule
7
7
  import com.facebook.react.bridge.ReactMethod
8
- import com.facebook.react.bridge.WritableMap
9
8
  import com.facebook.react.bridge.WritableNativeMap
10
9
  import com.facebook.react.modules.core.DeviceEventManagerModule
11
10
  import com.pagopa.ioreactnativecie.cie.Atr
12
11
  import it.pagopa.io.app.cie.CieLogger
13
12
  import it.pagopa.io.app.cie.CieSDK
13
+ import it.pagopa.io.app.cie.IntAuthMRTDResponse
14
+ import it.pagopa.io.app.cie.NisAndPaceCallback
14
15
  import it.pagopa.io.app.cie.cie.CieAtrCallback
15
16
  import it.pagopa.io.app.cie.cie.NfcError
16
17
  import it.pagopa.io.app.cie.cie.NfcEvent
17
18
  import it.pagopa.io.app.cie.network.NetworkCallback
18
19
  import it.pagopa.io.app.cie.network.NetworkError
19
20
  import it.pagopa.io.app.cie.nfc.NfcEvents
21
+ import it.pagopa.io.app.cie.nis.InternalAuthenticationResponse
22
+ import it.pagopa.io.app.cie.nis.NisCallback
23
+ import it.pagopa.io.app.cie.pace.MRTDResponse
24
+ import it.pagopa.io.app.cie.pace.PaceCallback
25
+ import it.pagopa.io.app.cie.toHex
20
26
  import java.net.URL
21
27
 
22
28
  class IoReactNativeCieModule(reactContext: ReactApplicationContext) :
@@ -35,16 +41,19 @@ class IoReactNativeCieModule(reactContext: ReactApplicationContext) :
35
41
  */
36
42
  val cieSdk: CieSDK by lazy {
37
43
  CieSDK.withContext(currentActivity)
38
- };
44
+ }
39
45
 
46
+ @Suppress("unused")
40
47
  @ReactMethod
41
48
  fun addListener(eventName: String) {
42
49
  }
43
50
 
51
+ @Suppress("unused")
44
52
  @ReactMethod
45
53
  fun removeListeners(count: Int) {
46
54
  }
47
55
 
56
+ @Suppress("unused")
48
57
  @ReactMethod
49
58
  fun hasNfcFeature(promise: Promise) {
50
59
  try {
@@ -56,6 +65,7 @@ class IoReactNativeCieModule(reactContext: ReactApplicationContext) :
56
65
  }
57
66
  }
58
67
 
68
+ @Suppress("unused")
59
69
  @ReactMethod
60
70
  fun isNfcEnabled(promise: Promise) {
61
71
  try {
@@ -67,6 +77,7 @@ class IoReactNativeCieModule(reactContext: ReactApplicationContext) :
67
77
  }
68
78
  }
69
79
 
80
+ @Suppress("unused")
70
81
  @ReactMethod
71
82
  fun isCieAuthenticationSupported(promise: Promise) {
72
83
  cieSdk.isCieAuthenticationSupported().apply {
@@ -74,6 +85,7 @@ class IoReactNativeCieModule(reactContext: ReactApplicationContext) :
74
85
  }
75
86
  }
76
87
 
88
+ @Suppress("unused")
77
89
  @ReactMethod
78
90
  fun openNfcSettings(promise: Promise) {
79
91
  try {
@@ -84,21 +96,205 @@ class IoReactNativeCieModule(reactContext: ReactApplicationContext) :
84
96
  }
85
97
  }
86
98
 
99
+ @Suppress("unused")
87
100
  @ReactMethod
88
101
  fun setAlertMessage(key: String, value: String) {
89
102
  // Android does not support alert messages for NFC reading
90
103
  }
91
104
 
105
+ @Suppress("unused")
92
106
  @ReactMethod
93
107
  fun setCurrentAlertMessage(value: String) {
94
108
  // Android does not support alert messages for NFC reading
95
109
  }
96
110
 
111
+ @Suppress("unused")
97
112
  @ReactMethod
98
113
  fun setCustomIdpUrl(url: String) {
99
114
  cieSdk.withCustomIdpUrl(url)
100
115
  }
101
116
 
117
+ @Suppress("unused")
118
+ @ReactMethod
119
+ fun startInternalAuthentication(
120
+ challenge: String,
121
+ resultEncoding: String,
122
+ timeout: Int = 10000,
123
+ promise: Promise,
124
+ ) {
125
+ val encoding: ResultEncoding = ResultEncoding.fromString(resultEncoding)
126
+ try {
127
+ cieSdk.startReadingNis(challenge, timeout, object : NfcEvents {
128
+ override fun event(event: NfcEvent) {
129
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
130
+ .emit(EventType.EVENT.value, WritableNativeMap().apply {
131
+ putString("name", event.name)
132
+ putDouble(
133
+ "progress",
134
+ (event.numeratorForNis.toDouble() / NfcEvent.totalNisOfNumeratorEvent.toDouble())
135
+ )
136
+ })
137
+ }
138
+
139
+ override fun error(error: NfcError) {
140
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
141
+ .emit(EventType.ERROR.value, WritableNativeMap().apply {
142
+ putString("name", mapNfcError(error).name)
143
+ error.msg?.let { putString("message", it) }
144
+ })
145
+
146
+ }
147
+ }, object : NisCallback {
148
+ override fun onSuccess(nisAuth: InternalAuthenticationResponse) {
149
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
150
+ .emit(EventType.INTERNAL_AUTHENTICATION_SUCCESS.value, WritableNativeMap().apply {
151
+ putString("nis", encoding.encode(nisAuth.nis))
152
+ putString("publicKey", encoding.encode(nisAuth.kpubIntServ))
153
+ putString("sod", encoding.encode(nisAuth.sod))
154
+ putString("signedChallenge", encoding.encode(nisAuth.challengeSigned))
155
+ })
156
+ }
157
+
158
+ override fun onError(error: NfcError) {
159
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
160
+ .emit(EventType.ERROR.value, WritableNativeMap().apply {
161
+ putString("name", mapNfcError(error).name)
162
+ error.msg?.let { putString("message", it) }
163
+ })
164
+ }
165
+ })
166
+ promise.resolve(null)
167
+ } catch (e: Exception) {
168
+ promise.reject(ModuleException.UNKNOWN_EXCEPTION, e.message, e)
169
+ }
170
+ }
171
+
172
+ @Suppress("unused")
173
+ @ReactMethod
174
+ fun startMRTDReading(
175
+ can: String,
176
+ resultEncoding: String,
177
+ timeout: Int = 10000,
178
+ promise: Promise,
179
+ ) {
180
+ val encoding: ResultEncoding = ResultEncoding.fromString(resultEncoding)
181
+ try {
182
+ cieSdk.startDoPace(can, timeout, object : NfcEvents {
183
+ override fun event(event: NfcEvent) {
184
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
185
+ .emit(EventType.EVENT.value, WritableNativeMap().apply {
186
+ putString("name", event.name)
187
+ putDouble(
188
+ "progress",
189
+ (event.numeratorForPace.toDouble() / NfcEvent.totalPaceOfNumeratorEvent.toDouble())
190
+ )
191
+ })
192
+ }
193
+
194
+ override fun error(error: NfcError) {
195
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
196
+ .emit(EventType.ERROR.value, WritableNativeMap().apply {
197
+ putString("name", mapNfcError(error).name)
198
+ error.msg?.let { putString("message", it) }
199
+ })
200
+
201
+ }
202
+ }, object : PaceCallback {
203
+ override fun onSuccess(eMRTDResponse: MRTDResponse) {
204
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
205
+ .emit(EventType.MRTD_WITH_PACE_SUCCESS.value, WritableNativeMap().apply {
206
+ putString("dg1", encoding.encode(eMRTDResponse.dg1))
207
+ putString("dg11", encoding.encode(eMRTDResponse.dg11))
208
+ putString("sod", encoding.encode(eMRTDResponse.sod))
209
+ })
210
+ }
211
+
212
+ override fun onError(error: NfcError) {
213
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
214
+ .emit(EventType.ERROR.value, WritableNativeMap().apply {
215
+ putString("name", mapNfcError(error).name)
216
+ error.msg?.let { putString("message", it) }
217
+ })
218
+ }
219
+ })
220
+ promise.resolve(null)
221
+ } catch (e: Exception) {
222
+ promise.reject(ModuleException.UNKNOWN_EXCEPTION, e.message, e)
223
+ }
224
+ }
225
+
226
+ @Suppress("unused")
227
+ @ReactMethod
228
+ fun startInternalAuthAndMRTDReading(
229
+ can: String,
230
+ challenge: String,
231
+ resultEncoding: String,
232
+ timeout: Int = 10000,
233
+ promise: Promise,
234
+ ) {
235
+ val encoding: ResultEncoding = ResultEncoding.fromString(resultEncoding)
236
+ try {
237
+ cieSdk.startNisAndPace(challenge, can, timeout, object : NfcEvents {
238
+ override fun event(event: NfcEvent) {
239
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
240
+ .emit(EventType.EVENT.value, WritableNativeMap().apply {
241
+ putString("name", event.name)
242
+ putDouble(
243
+ "progress",
244
+ (event.numeratorForNisAndPace.toDouble() / NfcEvent.totalNisAndPaceOfNumeratorEvent.toDouble())
245
+ )
246
+ })
247
+ }
248
+
249
+ override fun error(error: NfcError) {
250
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
251
+ .emit(EventType.ERROR.value, WritableNativeMap().apply {
252
+ putString("name", mapNfcError(error).name)
253
+ error.msg?.let { putString("message", it) }
254
+ })
255
+
256
+ }
257
+ }, object : NisAndPaceCallback {
258
+ override fun onSuccess(intAuthMRTDResponse: IntAuthMRTDResponse) {
259
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
260
+ .emit(
261
+ EventType.INTERNAL_AUTH_AND_MRTD_WITH_PACE_SUCCESS.value,
262
+ WritableNativeMap().apply {
263
+ putMap("nis_data", WritableNativeMap().apply {
264
+ putString("nis", encoding.encode(intAuthMRTDResponse.internalAuthentication.nis))
265
+ putString(
266
+ "publicKey",
267
+ encoding.encode(intAuthMRTDResponse.internalAuthentication.kpubIntServ)
268
+ )
269
+ putString("sod", encoding.encode(intAuthMRTDResponse.internalAuthentication.sod))
270
+ putString(
271
+ "signedChallenge",
272
+ encoding.encode(intAuthMRTDResponse.internalAuthentication.challengeSigned)
273
+ )
274
+ })
275
+ putMap("mrtd_data", WritableNativeMap().apply {
276
+ putString("dg1", encoding.encode(intAuthMRTDResponse.mrtd.dg1))
277
+ putString("dg11", encoding.encode(intAuthMRTDResponse.mrtd.dg11))
278
+ putString("sod", encoding.encode(intAuthMRTDResponse.mrtd.sod))
279
+ })
280
+ })
281
+ }
282
+
283
+ override fun onError(error: NfcError) {
284
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
285
+ .emit(EventType.ERROR.value, WritableNativeMap().apply {
286
+ putString("name", mapNfcError(error).name)
287
+ error.msg?.let { putString("message", it) }
288
+ })
289
+ }
290
+ })
291
+ promise.resolve(null)
292
+ } catch (e: Exception) {
293
+ promise.reject(ModuleException.UNKNOWN_EXCEPTION, e.message, e)
294
+ }
295
+ }
296
+
297
+ @Suppress("unused")
102
298
  @ReactMethod
103
299
  fun startReadingAttributes(
104
300
  timeout: Int = 10000,
@@ -148,6 +344,7 @@ class IoReactNativeCieModule(reactContext: ReactApplicationContext) :
148
344
  }
149
345
  }
150
346
 
347
+ @Suppress("unused")
151
348
  @ReactMethod
152
349
  fun startReading(
153
350
  pin: String,
@@ -159,7 +356,7 @@ class IoReactNativeCieModule(reactContext: ReactApplicationContext) :
159
356
  cieSdk.setPin(pin)
160
357
  } catch (e: Exception) {
161
358
  promise.reject(ModuleException.PIN_REGEX_NOT_VALID, e.message, e)
162
- return;
359
+ return
163
360
  }
164
361
 
165
362
  try {
@@ -210,6 +407,7 @@ class IoReactNativeCieModule(reactContext: ReactApplicationContext) :
210
407
  }
211
408
  }
212
409
 
410
+ @Suppress("unused")
213
411
  @ReactMethod
214
412
  fun stopReading() {
215
413
  cieSdk.stopNFCListening()
@@ -239,12 +437,37 @@ class IoReactNativeCieModule(reactContext: ReactApplicationContext) :
239
437
 
240
438
  companion object {
241
439
  const val NAME = "IoReactNativeCie"
242
- const val ERROR_USER_INFO_KEY = "error"
440
+
441
+ enum class ResultEncoding(val value: String) {
442
+ HEX("hex"),
443
+ BASE64("base64"),
444
+ BASE64URL("base64url");
445
+
446
+ fun encode(data: ByteArray): String = when (this) {
447
+ HEX -> data.toHex().uppercase()
448
+ BASE64 -> Base64.encodeToString(data, Base64.DEFAULT or Base64.NO_WRAP)
449
+ BASE64URL -> Base64.encodeToString(data, Base64.URL_SAFE or Base64.NO_WRAP)
450
+ }
451
+
452
+ companion object {
453
+ fun fromString(value: String?): ResultEncoding {
454
+ return when (value) {
455
+ "hex" -> HEX
456
+ "base64" -> BASE64
457
+ "base64url" -> BASE64URL
458
+ else -> BASE64 // Default
459
+ }
460
+ }
461
+ }
462
+ }
243
463
 
244
464
  enum class EventType(val value: String) {
245
465
  EVENT("onEvent"),
246
466
  ERROR("onError"),
247
467
  ATTRIBUTES_SUCCESS("onAttributesSuccess"),
468
+ INTERNAL_AUTHENTICATION_SUCCESS("onInternalAuthenticationSuccess"),
469
+ MRTD_WITH_PACE_SUCCESS("onMRTDWithPaceSuccess"),
470
+ INTERNAL_AUTH_AND_MRTD_WITH_PACE_SUCCESS("onInternalAuthAndMRTDWithPaceSuccess"),
248
471
  SUCCESS("onSuccess")
249
472
  }
250
473
 
@@ -262,9 +485,9 @@ class IoReactNativeCieModule(reactContext: ReactApplicationContext) :
262
485
  }
263
486
 
264
487
  private object ModuleException {
265
- const val PIN_REGEX_NOT_VALID = "PIN_REGEX_NOT_VALID";
266
- const val INVALID_AUTH_URL = "INVALID_AUTH_URL";
267
- const val UNKNOWN_EXCEPTION = "UNKNOWN_EXCEPTION";
488
+ const val PIN_REGEX_NOT_VALID = "PIN_REGEX_NOT_VALID"
489
+ const val INVALID_AUTH_URL = "INVALID_AUTH_URL"
490
+ const val UNKNOWN_EXCEPTION = "UNKNOWN_EXCEPTION"
268
491
  }
269
492
  }
270
493
  }
@@ -9,9 +9,9 @@ import Foundation
9
9
 
10
10
  extension Data {
11
11
 
12
- /// Converts the data to a lowercase hexadecimal string.
12
+ /// Converts the data to an uppercase hexadecimal string.
13
13
  func toHexString() -> String {
14
- return self.map { String(format: "%02x", $0) }.joined()
14
+ return self.map { String(format: "%02X", $0) }.joined()
15
15
  }
16
16
 
17
17
  /// Converts the data to a base64url encoded string (RFC 7515), without padding.
@@ -32,6 +32,11 @@ extension Array where Element == UInt8 {
32
32
  return Data(self).toHexString()
33
33
  }
34
34
 
35
+ /// Converts the byte array to a base64 encoded string.
36
+ func base64EncodedString() -> String {
37
+ return Data(self).base64EncodedString()
38
+ }
39
+
35
40
  /// Converts the byte array to a base64url encoded string.
36
41
  func base64UrlEncodedString() -> String {
37
42
  return Data(self).base64UrlEncodedString()
@@ -42,6 +47,8 @@ extension Array where Element == UInt8 {
42
47
  case .HEX:
43
48
  return Data(self).toHexString()
44
49
  case .BASE64:
50
+ return Data(self).base64EncodedString()
51
+ case .BASE64URL:
45
52
  return Data(self).base64UrlEncodedString()
46
53
  }
47
54
  }
@@ -8,6 +8,7 @@
8
8
  enum DataEncoding: String, Sendable {
9
9
  case HEX = "HEX"
10
10
  case BASE64 = "BASE64"
11
+ case BASE64URL = "BASE64URL"
11
12
 
12
13
  static func from(string: String?) -> DataEncoding {
13
14
  return DataEncoding(rawValue: string?.uppercased() ?? "") ?? .BASE64
@@ -31,6 +31,19 @@ RCT_EXTERN_METHOD(startInternalAuthentication: (NSString)challenge
31
31
  withResolver: (RCTPromiseResolveBlock)resolve
32
32
  withRejecter: (RCTPromiseRejectBlock)reject)
33
33
 
34
+ RCT_EXTERN_METHOD(startMRTDReading: (NSString)can
35
+ withResultEncoding: (NSString)encodingString
36
+ withTimeout: (NSNumber)timeout
37
+ withResolver: (RCTPromiseResolveBlock)resolve
38
+ withRejecter: (RCTPromiseRejectBlock)reject)
39
+
40
+ RCT_EXTERN_METHOD(startInternalAuthAndMRTDReading: (NSString)can
41
+ withChallenge: (NSString)challenge
42
+ withResultEncoding: (NSString)encodingString
43
+ withTimeout: (NSNumber)timeout
44
+ withResolver: (RCTPromiseResolveBlock)resolve
45
+ withRejecter: (RCTPromiseRejectBlock)reject)
46
+
34
47
  RCT_EXTERN_METHOD(startReadingAttributes: (NSNumber)timeout
35
48
  withResolver: (RCTPromiseResolveBlock)resolve
36
49
  withRejecter: (RCTPromiseRejectBlock)reject)
@@ -85,15 +85,99 @@ class IoReactNativeCie: RCTEventEmitter {
85
85
  )
86
86
  let encoding = DataEncoding.from(string: encodingString)
87
87
  let payload: NSDictionary = [
88
- "response": [
88
+ "nis": internalAuthResponse.nis.encodedDataString(encoding: encoding),
89
+ "publicKey": internalAuthResponse.publicKey.encodedDataString(encoding: encoding),
90
+ "sod": internalAuthResponse.sod.encodedDataString(encoding: encoding),
91
+ "signedChallenge": internalAuthResponse.signedChallenge.encodedDataString(encoding: encoding)
92
+ ]
93
+ self.sendEvent(
94
+ withName: EventType.onInternalAuthenticationSuccess.rawValue, body: payload)
95
+ resolve(nil)
96
+ } catch {
97
+ guard let nfcDigitalIdError = error as? NfcDigitalIdError else {
98
+ reject(ModuleException.unexpected.rawValue, error.localizedDescription, error)
99
+ return
100
+ }
101
+ handleReadError(nfcDigitalIdError)
102
+ resolve(nil)
103
+ }
104
+ }
105
+ }
106
+
107
+ @objc func startMRTDReading(
108
+ _ can: String,
109
+ withResultEncoding encodingString: String,
110
+ withTimeout timeout: Int,
111
+ withResolver resolve: @escaping RCTPromiseResolveBlock,
112
+ withRejecter reject: @escaping RCTPromiseRejectBlock
113
+ ) {
114
+ Task { [weak self] in
115
+ guard let self = self else {
116
+ reject(ModuleException.threadingError.rawValue, "Failed to perform background operation, self was deallocated", nil)
117
+ return
118
+ }
119
+
120
+ do {
121
+ let mrtdResponse = try await self.cieSdk.performMtrd(
122
+ can: can,
123
+ handleReadEvent
124
+ )
125
+ let encoding = DataEncoding.from(string: encodingString)
126
+ let payload: NSDictionary = [
127
+ "dg1": mrtdResponse.dg1.encodedDataString(encoding: encoding),
128
+ "dg11": mrtdResponse.dg11.encodedDataString(encoding: encoding),
129
+ "sod": mrtdResponse.sod.encodedDataString(encoding: encoding)
130
+ ]
131
+ self.sendEvent(
132
+ withName: EventType.onMRTDWithPaceSuccess.rawValue, body: payload)
133
+ resolve(nil)
134
+ } catch {
135
+ guard let nfcDigitalIdError = error as? NfcDigitalIdError else {
136
+ reject(ModuleException.unexpected.rawValue, error.localizedDescription, error)
137
+ return
138
+ }
139
+ handleReadError(nfcDigitalIdError)
140
+ resolve(nil)
141
+ }
142
+ }
143
+ }
144
+
145
+ @objc func startInternalAuthAndMRTDReading(
146
+ _ can: String,
147
+ withChallenge challenge: String,
148
+ withResultEncoding encodingString: String,
149
+ withTimeout timeout: Int,
150
+ withResolver resolve: @escaping RCTPromiseResolveBlock,
151
+ withRejecter reject: @escaping RCTPromiseRejectBlock
152
+ ) {
153
+ Task { [weak self] in
154
+ guard let self = self else {
155
+ reject(ModuleException.threadingError.rawValue, "Failed to perform background operation, self was deallocated", nil)
156
+ return
157
+ }
158
+
159
+ do {
160
+ let (mrtdResponse, internalAuthResponse) = try await self.cieSdk.performMRTDAndInternalAuthentication(
161
+ challenge: Array(challenge.utf8),
162
+ can: can,
163
+ handleReadEvent
164
+ )
165
+ let encoding = DataEncoding.from(string: encodingString)
166
+ let payload: NSDictionary = [
167
+ "nis_data": [
89
168
  "nis": internalAuthResponse.nis.encodedDataString(encoding: encoding),
90
169
  "publicKey": internalAuthResponse.publicKey.encodedDataString(encoding: encoding),
91
170
  "sod": internalAuthResponse.sod.encodedDataString(encoding: encoding),
92
171
  "signedChallenge": internalAuthResponse.signedChallenge.encodedDataString(encoding: encoding)
172
+ ],
173
+ "mrtd_data": [
174
+ "dg1": mrtdResponse.dg1.encodedDataString(encoding: encoding),
175
+ "dg11": mrtdResponse.dg11.encodedDataString(encoding: encoding),
176
+ "sod": mrtdResponse.sod.encodedDataString(encoding: encoding)
93
177
  ]
94
178
  ]
95
179
  self.sendEvent(
96
- withName: EventType.onInternalAuthenticationSuccess.rawValue, body: payload)
180
+ withName: EventType.onInternalAuthAndMRTDWithPaceSuccess.rawValue, body: payload)
97
181
  resolve(nil)
98
182
  } catch {
99
183
  guard let nfcDigitalIdError = error as? NfcDigitalIdError else {
@@ -216,6 +300,8 @@ class IoReactNativeCie: RCTEventEmitter {
216
300
  case onError
217
301
  case onAttributesSuccess
218
302
  case onInternalAuthenticationSuccess
303
+ case onMRTDWithPaceSuccess
304
+ case onInternalAuthAndMRTDWithPaceSuccess
219
305
  case onSuccess
220
306
  }
221
307