@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.
- package/IoReactNativeCie.podspec +1 -1
- package/README.md +72 -21
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/pagopa/ioreactnativecie/IoReactNativeCieModule.kt +230 -7
- package/ios/Data/Data+StringRepresentations.swift +9 -2
- package/ios/Data/DataEncoding.swift +1 -0
- package/ios/IoReactNativeCie.mm +13 -0
- package/ios/IoReactNativeCie.swift +88 -2
- package/lib/module/manager/index.js +99 -2
- package/lib/module/manager/index.js.map +1 -1
- package/lib/module/manager/types.js +33 -2
- package/lib/module/manager/types.js.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/manager/index.d.ts +95 -4
- package/lib/typescript/src/manager/index.d.ts.map +1 -1
- package/lib/typescript/src/manager/types.d.ts +88 -3
- package/lib/typescript/src/manager/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +4 -0
- package/src/manager/index.ts +121 -3
- package/src/manager/types.ts +49 -3
package/IoReactNativeCie.podspec
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
|
101
|
-
|
|
|
102
|
-
| `hasNFCFeature()`
|
|
103
|
-
| `isNfcEnabled()`
|
|
104
|
-
| `isCieAuthenticationSupported()`
|
|
105
|
-
| `openNfcSettings()`
|
|
106
|
-
| `addListener(event: CieEvent, listener: CieEventHandlers)`
|
|
107
|
-
| `removeListener(event: CieEvent)`
|
|
108
|
-
| `removeAllListeners()`
|
|
109
|
-
| `setCustomIdpUrl(url?: string)`
|
|
110
|
-
| `setAlertMessage(key: AlertMessageKey, value: string)`
|
|
111
|
-
| `setCurrentAlertMessage(value: string)`
|
|
112
|
-
| `startInternalAuthentication(challenge: string)`
|
|
113
|
-
| `
|
|
114
|
-
| `
|
|
115
|
-
| `
|
|
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.
|
package/android/build.gradle
CHANGED
|
@@ -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
|
-
|
|
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
|
|
12
|
+
/// Converts the data to an uppercase hexadecimal string.
|
|
13
13
|
func toHexString() -> String {
|
|
14
|
-
return self.map { String(format: "%
|
|
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
|
}
|
package/ios/IoReactNativeCie.mm
CHANGED
|
@@ -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
|
-
"
|
|
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.
|
|
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
|
|