@tokamakdev/plugin-local-authentication 0.1.0-beta.64 → 0.1.0-beta.69

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.
@@ -0,0 +1,3 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ <uses-permission android:name="android.permission.USE_BIOMETRIC" />
3
+ </manifest>
@@ -2,12 +2,15 @@ package com.tokamak.plugins.localauthentication
2
2
 
3
3
  import android.hardware.biometrics.BiometricManager
4
4
  import android.hardware.biometrics.BiometricManager.Authenticators
5
- import android.hardware.biometrics.BiometricPrompt
6
- import android.os.CancellationSignal
7
5
  import com.tokamak.runtime.TokamakHost
8
6
  import com.tokamak.runtime.TokamakPlugin
9
7
  import com.tokamak.runtime.TokamakPluginError
10
8
  import com.tokamak.runtime.TokamakPluginReply
9
+ import com.tokamak.runtime.authenticateOwner
10
+ import com.tokamak.runtime.optionalString
11
+ import com.tokamak.runtime.requireObject
12
+ import com.tokamak.runtime.requireOwnerAuthentication
13
+ import com.tokamak.runtime.requireString
11
14
  import org.json.JSONObject
12
15
 
13
16
  class TokamakLocalAuthenticationPlugin(
@@ -19,16 +22,12 @@ class TokamakLocalAuthenticationPlugin(
19
22
 
20
23
  override fun call(method: String, arguments: Any?, reply: TokamakPluginReply) {
21
24
  when (method) {
22
- "status" -> respond(reply) { reply(Result.success(status(request(arguments)))) }
23
- "authenticate" -> respond(reply) { authenticate(request(arguments), reply) }
25
+ "status" -> reply(Result.success(status(requireObject(arguments))))
26
+ "authenticate" -> authenticate(requireObject(arguments), reply)
24
27
  else -> super.call(method, arguments, reply)
25
28
  }
26
29
  }
27
30
 
28
- private fun respond(reply: TokamakPluginReply, operation: () -> Unit) {
29
- runCatching(operation).onFailure { reply(Result.failure(pluginError(it))) }
30
- }
31
-
32
31
  private fun status(request: JSONObject): String =
33
32
  when (biometrics.canAuthenticate(authenticators(request))) {
34
33
  BiometricManager.BIOMETRIC_SUCCESS -> "available"
@@ -39,53 +38,17 @@ class TokamakLocalAuthenticationPlugin(
39
38
  private fun authenticate(request: JSONObject, reply: TokamakPluginReply) {
40
39
  val authenticators = authenticators(request)
41
40
  val prompt = request.requireString("prompt")
42
- if (prompt.isEmpty()) throw typeError("prompt must be a non-empty string")
43
- requireAvailable(authenticators)
44
- val activity = host.activity ?: throw notVisible()
45
- val callback = PromptCallback(reply) { reply(Result.success(null)) }
46
- val dialog =
47
- BiometricPrompt.Builder(activity)
48
- .setTitle(prompt)
49
- .setAllowedAuthenticators(authenticators)
50
- if ((authenticators and Authenticators.DEVICE_CREDENTIAL) == 0) {
51
- dialog.setNegativeButton(
52
- activity.getString(android.R.string.cancel),
53
- activity.mainExecutor,
54
- ) { _, _ ->
55
- reply(Result.failure(TokamakPluginError("NotAllowedError", "Authentication was cancelled")))
56
- }
57
- }
58
- dialog.build().authenticate(CancellationSignal(), activity.mainExecutor, callback)
59
- }
60
-
61
- private fun requireAvailable(authenticators: Int) {
62
- when (biometrics.canAuthenticate(authenticators)) {
63
- BiometricManager.BIOMETRIC_SUCCESS -> Unit
64
- BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE ->
65
- throw TokamakPluginError.notSupported("This device cannot perform the requested authentication")
66
- else -> throw notSetUp()
67
- }
41
+ if (prompt.isEmpty()) throw TokamakPluginError.typeError("prompt must be a non-empty string")
42
+ host.requireOwnerAuthentication(authenticators)
43
+ host.authenticateOwner(prompt, authenticators, null, reply) { reply(Result.success(null)) }
68
44
  }
69
45
 
70
46
  private fun authenticators(request: JSONObject): Int {
71
47
  val wireName = request.optionalString("authentication")
72
48
  return Authentication.entries.firstOrNull { it.wireName == wireName }?.authenticators
73
- ?: throw typeError("authentication must be \"biometricsOrPasscode\" or \"biometrics\"")
49
+ ?: throw TokamakPluginError.typeError("authentication must be \"biometricsOrPasscode\" or \"biometrics\"")
74
50
  }
75
51
 
76
- private fun request(arguments: Any?): JSONObject =
77
- arguments as? JSONObject ?: throw typeError("$id arguments must be an object")
78
-
79
- private fun JSONObject.requireString(name: String): String =
80
- optionalString(name) ?: throw typeError("$name must be a string")
81
-
82
- private fun JSONObject.optionalString(name: String): String? =
83
- when (val value = opt(name)) {
84
- null, JSONObject.NULL -> null
85
- is String -> value
86
- else -> throw typeError("$name must be a string")
87
- }
88
-
89
52
  private enum class Authentication(val wireName: String, val authenticators: Int) {
90
53
  BIOMETRICS_OR_PASSCODE(
91
54
  "biometricsOrPasscode",
@@ -93,46 +56,4 @@ class TokamakLocalAuthenticationPlugin(
93
56
  ),
94
57
  BIOMETRICS("biometrics", Authenticators.BIOMETRIC_STRONG),
95
58
  }
96
-
97
- private companion object {
98
- fun typeError(message: String) = TokamakPluginError("TypeError", message)
99
-
100
- fun notSetUp() =
101
- TokamakPluginError("InvalidStateError", "The requested authentication is not set up on this device")
102
-
103
- fun notVisible() =
104
- TokamakPluginError("InvalidStateError", "The app has no activity to show the authentication prompt in")
105
-
106
- fun pluginError(error: Throwable): TokamakPluginError =
107
- error as? TokamakPluginError
108
- ?: TokamakPluginError("OperationError", error.message ?: error.javaClass.name)
109
- }
110
59
  }
111
-
112
- private class PromptCallback(
113
- private val reply: TokamakPluginReply,
114
- private val succeeded: () -> Unit,
115
- ) : BiometricPrompt.AuthenticationCallback() {
116
- override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) = succeeded()
117
-
118
- override fun onAuthenticationError(code: Int, message: CharSequence) =
119
- reply(Result.failure(authenticationError(code, message)))
120
- }
121
-
122
- private fun authenticationError(code: Int, message: CharSequence) =
123
- TokamakPluginError(
124
- when (code) {
125
- BiometricPrompt.BIOMETRIC_ERROR_CANCELED,
126
- BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED,
127
- BiometricPrompt.BIOMETRIC_ERROR_TIMEOUT,
128
- BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT,
129
- BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT_PERMANENT,
130
- -> "NotAllowedError"
131
- BiometricPrompt.BIOMETRIC_ERROR_NO_BIOMETRICS,
132
- BiometricPrompt.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL,
133
- -> "InvalidStateError"
134
- BiometricPrompt.BIOMETRIC_ERROR_HW_NOT_PRESENT -> "NotSupportedError"
135
- else -> "OperationError"
136
- },
137
- message.toString(),
138
- )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokamakdev/plugin-local-authentication",
3
- "version": "0.1.0-beta.64",
3
+ "version": "0.1.0-beta.69",
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.64"
14
+ "@tokamakdev/plugin": "0.1.0-beta.69"
15
15
  },
16
16
  "files": [
17
17
  "android",
@@ -4,25 +4,17 @@
4
4
  "platforms": {
5
5
  "macos": {
6
6
  "class": "TokamakLocalAuthenticationPlugin",
7
- "sources": ["apple/LocalAuthenticationPlugin.swift"],
8
- "frameworks": ["LocalAuthentication"]
7
+ "sources": ["apple/LocalAuthenticationPlugin.swift"]
9
8
  },
10
9
  "ios": {
11
10
  "class": "TokamakLocalAuthenticationPlugin",
12
11
  "sources": ["apple/LocalAuthenticationPlugin.swift"],
13
- "frameworks": ["LocalAuthentication"],
14
- "plist": "apple/Info.plist"
15
- },
16
- "ios-simulator": {
17
- "class": "TokamakLocalAuthenticationPlugin",
18
- "sources": ["apple/LocalAuthenticationPlugin.swift"],
19
- "frameworks": ["LocalAuthentication"],
20
12
  "plist": "apple/Info.plist"
21
13
  },
22
14
  "android": {
23
15
  "class": "com.tokamak.plugins.localauthentication.TokamakLocalAuthenticationPlugin",
24
16
  "sources": ["android/LocalAuthenticationPlugin.kt"],
25
- "permissions": ["android.permission.USE_BIOMETRIC"]
17
+ "manifest": "android/AndroidManifest.xml"
26
18
  }
27
19
  }
28
20
  }