@tokamakdev/plugin-secure-storage 0.1.0-beta.49 → 0.1.0-beta.51
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.
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
package com.tokamak.plugins.securestorage
|
|
2
2
|
|
|
3
|
-
import android.app.Activity
|
|
4
3
|
import android.hardware.biometrics.BiometricManager
|
|
5
4
|
import android.hardware.biometrics.BiometricManager.Authenticators
|
|
6
5
|
import android.hardware.biometrics.BiometricPrompt
|
|
@@ -12,6 +11,7 @@ import android.security.keystore.KeyProperties
|
|
|
12
11
|
import android.security.keystore.StrongBoxUnavailableException
|
|
13
12
|
import android.security.keystore.UserNotAuthenticatedException
|
|
14
13
|
import android.util.AtomicFile
|
|
14
|
+
import com.tokamak.runtime.TokamakHost
|
|
15
15
|
import com.tokamak.runtime.TokamakPlugin
|
|
16
16
|
import com.tokamak.runtime.TokamakPluginError
|
|
17
17
|
import com.tokamak.runtime.TokamakPluginReply
|
|
@@ -46,15 +46,16 @@ import org.json.JSONObject
|
|
|
46
46
|
* carries the value's unlock and authentication requirements. Every write uses a new key
|
|
47
47
|
* pair, identified in the value's file, so a failed write leaves the previous value readable.
|
|
48
48
|
*/
|
|
49
|
-
|
|
50
|
-
private val
|
|
49
|
+
class TokamakSecureStoragePlugin(
|
|
50
|
+
private val host: TokamakHost,
|
|
51
51
|
) : TokamakPlugin {
|
|
52
52
|
override val id = "secure-storage"
|
|
53
53
|
|
|
54
|
+
private val context = host.context
|
|
54
55
|
private val worker = Executors.newSingleThreadExecutor()
|
|
55
|
-
private val directory = File(
|
|
56
|
+
private val directory = File(context.noBackupFilesDir, "tokamak-secure-storage")
|
|
56
57
|
private val keyStore = KeyStore.getInstance(KEYSTORE).apply { load(null) }
|
|
57
|
-
private val biometrics =
|
|
58
|
+
private val biometrics = context.getSystemService(BiometricManager::class.java)
|
|
58
59
|
private val random = SecureRandom()
|
|
59
60
|
|
|
60
61
|
override fun call(method: String, arguments: Any?, reply: TokamakPluginReply) {
|
|
@@ -83,7 +84,7 @@ internal class TokamakSecureStoragePlugin(
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
private fun onUiThread(reply: TokamakPluginReply, operation: () -> Unit) =
|
|
86
|
-
|
|
87
|
+
context.mainExecutor.execute {
|
|
87
88
|
runCatching(operation).onFailure { reply(Result.failure(pluginError(it))) }
|
|
88
89
|
}
|
|
89
90
|
|
|
@@ -200,8 +201,9 @@ internal class TokamakSecureStoragePlugin(
|
|
|
200
201
|
stored: StoredValue,
|
|
201
202
|
reply: TokamakPluginReply,
|
|
202
203
|
) {
|
|
204
|
+
val activity = host.activity ?: throw notVisible()
|
|
203
205
|
val callback = PromptCallback(reply) { execute(reply) { reply(Result.success(open(stored, unwrap))) } }
|
|
204
|
-
val title = prompt?.takeIf { it.isNotEmpty() } ?:
|
|
206
|
+
val title = prompt?.takeIf { it.isNotEmpty() } ?: context.applicationInfo.loadLabel(context.packageManager)
|
|
205
207
|
val dialog =
|
|
206
208
|
BiometricPrompt.Builder(activity)
|
|
207
209
|
.setTitle(title)
|
|
@@ -346,6 +348,9 @@ internal class TokamakSecureStoragePlugin(
|
|
|
346
348
|
fun notSetUp() =
|
|
347
349
|
TokamakPluginError("InvalidStateError", "The requested authentication is not set up on this device")
|
|
348
350
|
|
|
351
|
+
fun notVisible() =
|
|
352
|
+
TokamakPluginError("InvalidStateError", "The app has no activity to show the authentication prompt in")
|
|
353
|
+
|
|
349
354
|
fun pluginError(error: Throwable): TokamakPluginError =
|
|
350
355
|
when (error) {
|
|
351
356
|
is TokamakPluginError -> error
|
package/apple/Info.plist
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>NSFaceIDUsageDescription</key>
|
|
6
|
+
<string>This app uses Face ID to confirm your identity.</string>
|
|
7
|
+
</dict>
|
|
8
|
+
</plist>
|
|
@@ -9,6 +9,8 @@ final class TokamakSecureStoragePlugin: TokamakPlugin {
|
|
|
9
9
|
/// Keychain calls block while the system authentication prompt is shown.
|
|
10
10
|
private let queue = DispatchQueue(label: "tokamak.secure-storage")
|
|
11
11
|
|
|
12
|
+
init(host: TokamakHost) {}
|
|
13
|
+
|
|
12
14
|
private static let teamSigningRequired = TokamakPluginError.notSupported(
|
|
13
15
|
"Secure storage requires a team-signed build"
|
|
14
16
|
)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokamakdev/plugin-secure-storage",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.51",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/mantty/tokamak.git",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
".": "./src/index.ts"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@tokamakdev/plugin": "0.1.0-beta.
|
|
14
|
+
"@tokamakdev/plugin": "0.1.0-beta.51"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"android",
|
package/tokamak-plugin.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "secure-storage",
|
|
4
|
-
"kind": "frontend",
|
|
5
4
|
"platforms": {
|
|
6
5
|
"macos": {
|
|
7
6
|
"class": "TokamakSecureStoragePlugin",
|
|
@@ -12,17 +11,13 @@
|
|
|
12
11
|
"class": "TokamakSecureStoragePlugin",
|
|
13
12
|
"sources": ["apple/SecureStoragePlugin.swift"],
|
|
14
13
|
"frameworks": ["LocalAuthentication", "Security"],
|
|
15
|
-
"plist":
|
|
16
|
-
"NSFaceIDUsageDescription": "This app uses Face ID to confirm your identity."
|
|
17
|
-
}
|
|
14
|
+
"plist": "apple/Info.plist"
|
|
18
15
|
},
|
|
19
16
|
"ios-simulator": {
|
|
20
17
|
"class": "TokamakSecureStoragePlugin",
|
|
21
18
|
"sources": ["apple/SecureStoragePlugin.swift"],
|
|
22
19
|
"frameworks": ["LocalAuthentication", "Security"],
|
|
23
|
-
"plist":
|
|
24
|
-
"NSFaceIDUsageDescription": "This app uses Face ID to confirm your identity."
|
|
25
|
-
}
|
|
20
|
+
"plist": "apple/Info.plist"
|
|
26
21
|
},
|
|
27
22
|
"android": {
|
|
28
23
|
"class": "com.tokamak.plugins.securestorage.TokamakSecureStoragePlugin",
|