@capawesome/capacitor-app-integrity 0.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.
- package/CapawesomeCapacitorAppIntegrity.podspec +17 -0
- package/LICENSE +21 -0
- package/Package.swift +28 -0
- package/README.md +385 -0
- package/android/build.gradle +60 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/AppIntegrity.java +208 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/AppIntegrityPlugin.java +137 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/classes/CustomException.java +20 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/classes/CustomExceptions.java +11 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/classes/options/PrepareIntegrityTokenOptions.java +26 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/classes/options/RequestIntegrityTokenOptions.java +51 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/classes/results/IsAvailableResult.java +22 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/classes/results/RequestIntegrityTokenResult.java +23 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/interfaces/Callback.java +5 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/interfaces/EmptyCallback.java +5 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/interfaces/NonEmptyResultCallback.java +7 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/interfaces/Result.java +7 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +472 -0
- package/dist/esm/definitions.d.ts +384 -0
- package/dist/esm/definitions.js +152 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +10 -0
- package/dist/esm/web.js +22 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +188 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +191 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Plugin/AppIntegrity.swift +78 -0
- package/ios/Plugin/AppIntegrityPlugin.swift +116 -0
- package/ios/Plugin/Classes/Options/AttestKeyOptions.swift +29 -0
- package/ios/Plugin/Classes/Options/GenerateAssertionOptions.swift +29 -0
- package/ios/Plugin/Classes/Results/AttestKeyResult.swift +16 -0
- package/ios/Plugin/Classes/Results/GenerateAssertionResult.swift +16 -0
- package/ios/Plugin/Classes/Results/GenerateKeyResult.swift +16 -0
- package/ios/Plugin/Classes/Results/IsAvailableResult.swift +16 -0
- package/ios/Plugin/Enums/CustomError.swift +59 -0
- package/ios/Plugin/Info.plist +24 -0
- package/ios/Plugin/Protocols/Result.swift +5 -0
- package/package.json +91 -0
package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/AppIntegrity.java
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.appintegrity;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
5
|
+
import com.google.android.gms.common.ConnectionResult;
|
|
6
|
+
import com.google.android.gms.common.GoogleApiAvailabilityLight;
|
|
7
|
+
import com.google.android.play.core.integrity.IntegrityManagerFactory;
|
|
8
|
+
import com.google.android.play.core.integrity.IntegrityServiceException;
|
|
9
|
+
import com.google.android.play.core.integrity.IntegrityTokenRequest;
|
|
10
|
+
import com.google.android.play.core.integrity.StandardIntegrityException;
|
|
11
|
+
import com.google.android.play.core.integrity.StandardIntegrityManager;
|
|
12
|
+
import com.google.android.play.core.integrity.model.IntegrityErrorCode;
|
|
13
|
+
import com.google.android.play.core.integrity.model.StandardIntegrityErrorCode;
|
|
14
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.classes.CustomException;
|
|
15
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.classes.CustomExceptions;
|
|
16
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.classes.options.PrepareIntegrityTokenOptions;
|
|
17
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.classes.options.RequestIntegrityTokenOptions;
|
|
18
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.classes.results.IsAvailableResult;
|
|
19
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.classes.results.RequestIntegrityTokenResult;
|
|
20
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.interfaces.EmptyCallback;
|
|
21
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.interfaces.NonEmptyResultCallback;
|
|
22
|
+
|
|
23
|
+
public class AppIntegrity {
|
|
24
|
+
|
|
25
|
+
@NonNull
|
|
26
|
+
private final AppIntegrityPlugin plugin;
|
|
27
|
+
|
|
28
|
+
@Nullable
|
|
29
|
+
private StandardIntegrityManager.StandardIntegrityTokenProvider standardIntegrityTokenProvider;
|
|
30
|
+
|
|
31
|
+
public AppIntegrity(@NonNull AppIntegrityPlugin plugin) {
|
|
32
|
+
this.plugin = plugin;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public void isAvailable(@NonNull NonEmptyResultCallback<IsAvailableResult> callback) {
|
|
36
|
+
int status = GoogleApiAvailabilityLight.getInstance().isGooglePlayServicesAvailable(plugin.getContext());
|
|
37
|
+
callback.success(new IsAvailableResult(status == ConnectionResult.SUCCESS));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public void prepareIntegrityToken(@NonNull PrepareIntegrityTokenOptions options, @NonNull EmptyCallback callback) {
|
|
41
|
+
StandardIntegrityManager standardIntegrityManager = IntegrityManagerFactory.createStandard(plugin.getContext());
|
|
42
|
+
StandardIntegrityManager.PrepareIntegrityTokenRequest request = StandardIntegrityManager.PrepareIntegrityTokenRequest.builder()
|
|
43
|
+
.setCloudProjectNumber(options.getCloudProjectNumber())
|
|
44
|
+
.build();
|
|
45
|
+
standardIntegrityManager
|
|
46
|
+
.prepareIntegrityToken(request)
|
|
47
|
+
.addOnSuccessListener(provider -> {
|
|
48
|
+
standardIntegrityTokenProvider = provider;
|
|
49
|
+
callback.success();
|
|
50
|
+
})
|
|
51
|
+
.addOnFailureListener(exception -> callback.error(mapException(exception)));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public void requestIntegrityToken(
|
|
55
|
+
@NonNull RequestIntegrityTokenOptions options,
|
|
56
|
+
@NonNull NonEmptyResultCallback<RequestIntegrityTokenResult> callback
|
|
57
|
+
) throws Exception {
|
|
58
|
+
String nonce = options.getNonce();
|
|
59
|
+
String requestHash = options.getRequestHash();
|
|
60
|
+
if (requestHash != null) {
|
|
61
|
+
requestStandardIntegrityToken(requestHash, callback);
|
|
62
|
+
} else if (nonce != null) {
|
|
63
|
+
requestClassicIntegrityToken(nonce, options.getCloudProjectNumber(), callback);
|
|
64
|
+
} else {
|
|
65
|
+
throw CustomExceptions.NONCE_OR_REQUEST_HASH_MISSING;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@NonNull
|
|
70
|
+
private static Exception mapException(@NonNull Exception exception) {
|
|
71
|
+
if (exception instanceof IntegrityServiceException) {
|
|
72
|
+
return mapIntegrityServiceException((IntegrityServiceException) exception);
|
|
73
|
+
}
|
|
74
|
+
if (exception instanceof StandardIntegrityException) {
|
|
75
|
+
return mapStandardIntegrityException((StandardIntegrityException) exception);
|
|
76
|
+
}
|
|
77
|
+
return exception;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@NonNull
|
|
81
|
+
private static Exception mapIntegrityServiceException(@NonNull IntegrityServiceException exception) {
|
|
82
|
+
switch (exception.getErrorCode()) {
|
|
83
|
+
case IntegrityErrorCode.API_NOT_AVAILABLE:
|
|
84
|
+
return new CustomException("API_NOT_AVAILABLE", "The Play Integrity API is not available on this device.");
|
|
85
|
+
case IntegrityErrorCode.APP_NOT_INSTALLED:
|
|
86
|
+
return new CustomException("APP_NOT_INSTALLED", "The calling app is not installed.");
|
|
87
|
+
case IntegrityErrorCode.APP_UID_MISMATCH:
|
|
88
|
+
return new CustomException("APP_UID_MISMATCH", "The calling app UID does not match the one from the package manager.");
|
|
89
|
+
case IntegrityErrorCode.CANNOT_BIND_TO_SERVICE:
|
|
90
|
+
return new CustomException("CANNOT_BIND_TO_SERVICE", "The app could not bind to the integrity service in the Play Store.");
|
|
91
|
+
case IntegrityErrorCode.CLIENT_TRANSIENT_ERROR:
|
|
92
|
+
return new CustomException(
|
|
93
|
+
"CLIENT_TRANSIENT_ERROR",
|
|
94
|
+
"A transient error occurred on the device. Retry with an exponential backoff."
|
|
95
|
+
);
|
|
96
|
+
case IntegrityErrorCode.CLOUD_PROJECT_NUMBER_IS_INVALID:
|
|
97
|
+
return new CustomException(null, "cloudProjectNumber is invalid.");
|
|
98
|
+
case IntegrityErrorCode.GOOGLE_SERVER_UNAVAILABLE:
|
|
99
|
+
return new CustomException(
|
|
100
|
+
"GOOGLE_SERVER_UNAVAILABLE",
|
|
101
|
+
"The Google server is currently unavailable. Retry with an exponential backoff."
|
|
102
|
+
);
|
|
103
|
+
case IntegrityErrorCode.INTERNAL_ERROR:
|
|
104
|
+
return new CustomException("INTERNAL_ERROR", "An internal error occurred. Retry with an exponential backoff.");
|
|
105
|
+
case IntegrityErrorCode.NETWORK_ERROR:
|
|
106
|
+
return new CustomException("NETWORK_ERROR", "No network connection is available. Retry when the device is online.");
|
|
107
|
+
case IntegrityErrorCode.NONCE_IS_NOT_BASE64:
|
|
108
|
+
return new CustomException(null, "nonce must be encoded as a base64 web-safe no-wrap string.");
|
|
109
|
+
case IntegrityErrorCode.NONCE_TOO_LONG:
|
|
110
|
+
return new CustomException(null, "nonce must not be longer than 500 bytes.");
|
|
111
|
+
case IntegrityErrorCode.NONCE_TOO_SHORT:
|
|
112
|
+
return new CustomException(null, "nonce must be at least 16 bytes long.");
|
|
113
|
+
case IntegrityErrorCode.PLAY_SERVICES_NOT_FOUND:
|
|
114
|
+
return new CustomException("PLAY_SERVICES_NOT_FOUND", "Google Play Services is not available on this device.");
|
|
115
|
+
case IntegrityErrorCode.PLAY_SERVICES_VERSION_OUTDATED:
|
|
116
|
+
return new CustomException("PLAY_SERVICES_VERSION_OUTDATED", "Google Play Services needs to be updated.");
|
|
117
|
+
case IntegrityErrorCode.PLAY_STORE_NOT_FOUND:
|
|
118
|
+
return new CustomException("PLAY_STORE_NOT_FOUND", "No official Play Store app was found on the device.");
|
|
119
|
+
case IntegrityErrorCode.PLAY_STORE_VERSION_OUTDATED:
|
|
120
|
+
return new CustomException("PLAY_STORE_VERSION_OUTDATED", "The Play Store app needs to be updated.");
|
|
121
|
+
case IntegrityErrorCode.TOO_MANY_REQUESTS:
|
|
122
|
+
return new CustomException("TOO_MANY_REQUESTS", "The calling app is making too many requests and has been throttled.");
|
|
123
|
+
default:
|
|
124
|
+
return exception;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@NonNull
|
|
129
|
+
private static Exception mapStandardIntegrityException(@NonNull StandardIntegrityException exception) {
|
|
130
|
+
switch (exception.getErrorCode()) {
|
|
131
|
+
case StandardIntegrityErrorCode.API_NOT_AVAILABLE:
|
|
132
|
+
return new CustomException("API_NOT_AVAILABLE", "The Play Integrity API is not available on this device.");
|
|
133
|
+
case StandardIntegrityErrorCode.APP_NOT_INSTALLED:
|
|
134
|
+
return new CustomException("APP_NOT_INSTALLED", "The calling app is not installed.");
|
|
135
|
+
case StandardIntegrityErrorCode.APP_UID_MISMATCH:
|
|
136
|
+
return new CustomException("APP_UID_MISMATCH", "The calling app UID does not match the one from the package manager.");
|
|
137
|
+
case StandardIntegrityErrorCode.CANNOT_BIND_TO_SERVICE:
|
|
138
|
+
return new CustomException("CANNOT_BIND_TO_SERVICE", "The app could not bind to the integrity service in the Play Store.");
|
|
139
|
+
case StandardIntegrityErrorCode.CLIENT_TRANSIENT_ERROR:
|
|
140
|
+
return new CustomException(
|
|
141
|
+
"CLIENT_TRANSIENT_ERROR",
|
|
142
|
+
"A transient error occurred on the device. Retry with an exponential backoff."
|
|
143
|
+
);
|
|
144
|
+
case StandardIntegrityErrorCode.CLOUD_PROJECT_NUMBER_IS_INVALID:
|
|
145
|
+
return new CustomException(null, "cloudProjectNumber is invalid.");
|
|
146
|
+
case StandardIntegrityErrorCode.GOOGLE_SERVER_UNAVAILABLE:
|
|
147
|
+
return new CustomException(
|
|
148
|
+
"GOOGLE_SERVER_UNAVAILABLE",
|
|
149
|
+
"The Google server is currently unavailable. Retry with an exponential backoff."
|
|
150
|
+
);
|
|
151
|
+
case StandardIntegrityErrorCode.INTEGRITY_TOKEN_PROVIDER_INVALID:
|
|
152
|
+
return new CustomException(
|
|
153
|
+
"INTEGRITY_TOKEN_PROVIDER_INVALID",
|
|
154
|
+
"The integrity token provider is invalid. Call prepareIntegrityToken() again."
|
|
155
|
+
);
|
|
156
|
+
case StandardIntegrityErrorCode.INTERNAL_ERROR:
|
|
157
|
+
return new CustomException("INTERNAL_ERROR", "An internal error occurred. Retry with an exponential backoff.");
|
|
158
|
+
case StandardIntegrityErrorCode.NETWORK_ERROR:
|
|
159
|
+
return new CustomException("NETWORK_ERROR", "No network connection is available. Retry when the device is online.");
|
|
160
|
+
case StandardIntegrityErrorCode.PLAY_SERVICES_NOT_FOUND:
|
|
161
|
+
return new CustomException("PLAY_SERVICES_NOT_FOUND", "Google Play Services is not available on this device.");
|
|
162
|
+
case StandardIntegrityErrorCode.PLAY_SERVICES_VERSION_OUTDATED:
|
|
163
|
+
return new CustomException("PLAY_SERVICES_VERSION_OUTDATED", "Google Play Services needs to be updated.");
|
|
164
|
+
case StandardIntegrityErrorCode.PLAY_STORE_NOT_FOUND:
|
|
165
|
+
return new CustomException("PLAY_STORE_NOT_FOUND", "No official Play Store app was found on the device.");
|
|
166
|
+
case StandardIntegrityErrorCode.PLAY_STORE_VERSION_OUTDATED:
|
|
167
|
+
return new CustomException("PLAY_STORE_VERSION_OUTDATED", "The Play Store app needs to be updated.");
|
|
168
|
+
case StandardIntegrityErrorCode.REQUEST_HASH_TOO_LONG:
|
|
169
|
+
return new CustomException(null, "requestHash must not be longer than 500 bytes.");
|
|
170
|
+
case StandardIntegrityErrorCode.TOO_MANY_REQUESTS:
|
|
171
|
+
return new CustomException("TOO_MANY_REQUESTS", "The calling app is making too many requests and has been throttled.");
|
|
172
|
+
default:
|
|
173
|
+
return exception;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private void requestClassicIntegrityToken(
|
|
178
|
+
@NonNull String nonce,
|
|
179
|
+
@Nullable Long cloudProjectNumber,
|
|
180
|
+
@NonNull NonEmptyResultCallback<RequestIntegrityTokenResult> callback
|
|
181
|
+
) {
|
|
182
|
+
IntegrityTokenRequest.Builder requestBuilder = IntegrityTokenRequest.builder().setNonce(nonce);
|
|
183
|
+
if (cloudProjectNumber != null) {
|
|
184
|
+
requestBuilder.setCloudProjectNumber(cloudProjectNumber);
|
|
185
|
+
}
|
|
186
|
+
IntegrityManagerFactory.create(plugin.getContext())
|
|
187
|
+
.requestIntegrityToken(requestBuilder.build())
|
|
188
|
+
.addOnSuccessListener(response -> callback.success(new RequestIntegrityTokenResult(response.token())))
|
|
189
|
+
.addOnFailureListener(exception -> callback.error(mapException(exception)));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private void requestStandardIntegrityToken(
|
|
193
|
+
@NonNull String requestHash,
|
|
194
|
+
@NonNull NonEmptyResultCallback<RequestIntegrityTokenResult> callback
|
|
195
|
+
) throws Exception {
|
|
196
|
+
StandardIntegrityManager.StandardIntegrityTokenProvider provider = standardIntegrityTokenProvider;
|
|
197
|
+
if (provider == null) {
|
|
198
|
+
throw CustomExceptions.INTEGRITY_TOKEN_PROVIDER_NOT_PREPARED;
|
|
199
|
+
}
|
|
200
|
+
StandardIntegrityManager.StandardIntegrityTokenRequest request = StandardIntegrityManager.StandardIntegrityTokenRequest.builder()
|
|
201
|
+
.setRequestHash(requestHash)
|
|
202
|
+
.build();
|
|
203
|
+
provider
|
|
204
|
+
.request(request)
|
|
205
|
+
.addOnSuccessListener(token -> callback.success(new RequestIntegrityTokenResult(token.token())))
|
|
206
|
+
.addOnFailureListener(exception -> callback.error(mapException(exception)));
|
|
207
|
+
}
|
|
208
|
+
}
|
package/android/src/main/java/io/capawesome/capacitorjs/plugins/appintegrity/AppIntegrityPlugin.java
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.appintegrity;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
5
|
+
import com.getcapacitor.Logger;
|
|
6
|
+
import com.getcapacitor.Plugin;
|
|
7
|
+
import com.getcapacitor.PluginCall;
|
|
8
|
+
import com.getcapacitor.PluginMethod;
|
|
9
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
10
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.classes.CustomException;
|
|
11
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.classes.options.PrepareIntegrityTokenOptions;
|
|
12
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.classes.options.RequestIntegrityTokenOptions;
|
|
13
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.classes.results.IsAvailableResult;
|
|
14
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.classes.results.RequestIntegrityTokenResult;
|
|
15
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.interfaces.EmptyCallback;
|
|
16
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.interfaces.NonEmptyResultCallback;
|
|
17
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.interfaces.Result;
|
|
18
|
+
|
|
19
|
+
@CapacitorPlugin(name = "AppIntegrity")
|
|
20
|
+
public class AppIntegrityPlugin extends Plugin {
|
|
21
|
+
|
|
22
|
+
public static final String ERROR_UNKNOWN_ERROR = "An unknown error has occurred.";
|
|
23
|
+
public static final String TAG = "AppIntegrity";
|
|
24
|
+
|
|
25
|
+
private AppIntegrity implementation;
|
|
26
|
+
|
|
27
|
+
@Override
|
|
28
|
+
public void load() {
|
|
29
|
+
this.implementation = new AppIntegrity(this);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@PluginMethod
|
|
33
|
+
public void attestKey(PluginCall call) {
|
|
34
|
+
rejectCallAsUnimplemented(call);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@PluginMethod
|
|
38
|
+
public void generateAssertion(PluginCall call) {
|
|
39
|
+
rejectCallAsUnimplemented(call);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@PluginMethod
|
|
43
|
+
public void generateKey(PluginCall call) {
|
|
44
|
+
rejectCallAsUnimplemented(call);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@PluginMethod
|
|
48
|
+
public void isAvailable(PluginCall call) {
|
|
49
|
+
try {
|
|
50
|
+
NonEmptyResultCallback<IsAvailableResult> callback = new NonEmptyResultCallback<>() {
|
|
51
|
+
@Override
|
|
52
|
+
public void success(@NonNull IsAvailableResult result) {
|
|
53
|
+
resolveCall(call, result);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@Override
|
|
57
|
+
public void error(Exception exception) {
|
|
58
|
+
rejectCall(call, exception);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
implementation.isAvailable(callback);
|
|
62
|
+
} catch (Exception exception) {
|
|
63
|
+
rejectCall(call, exception);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@PluginMethod
|
|
68
|
+
public void prepareIntegrityToken(PluginCall call) {
|
|
69
|
+
try {
|
|
70
|
+
PrepareIntegrityTokenOptions options = new PrepareIntegrityTokenOptions(call);
|
|
71
|
+
EmptyCallback callback = new EmptyCallback() {
|
|
72
|
+
@Override
|
|
73
|
+
public void success() {
|
|
74
|
+
resolveCall(call);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@Override
|
|
78
|
+
public void error(Exception exception) {
|
|
79
|
+
rejectCall(call, exception);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
implementation.prepareIntegrityToken(options, callback);
|
|
83
|
+
} catch (Exception exception) {
|
|
84
|
+
rejectCall(call, exception);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@PluginMethod
|
|
89
|
+
public void requestIntegrityToken(PluginCall call) {
|
|
90
|
+
try {
|
|
91
|
+
RequestIntegrityTokenOptions options = new RequestIntegrityTokenOptions(call);
|
|
92
|
+
NonEmptyResultCallback<RequestIntegrityTokenResult> callback = new NonEmptyResultCallback<>() {
|
|
93
|
+
@Override
|
|
94
|
+
public void success(@NonNull RequestIntegrityTokenResult result) {
|
|
95
|
+
resolveCall(call, result);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@Override
|
|
99
|
+
public void error(Exception exception) {
|
|
100
|
+
rejectCall(call, exception);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
implementation.requestIntegrityToken(options, callback);
|
|
104
|
+
} catch (Exception exception) {
|
|
105
|
+
rejectCall(call, exception);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private void rejectCall(@NonNull PluginCall call, @NonNull Exception exception) {
|
|
110
|
+
String message = exception.getMessage();
|
|
111
|
+
if (message == null) {
|
|
112
|
+
message = ERROR_UNKNOWN_ERROR;
|
|
113
|
+
}
|
|
114
|
+
String code = null;
|
|
115
|
+
if (exception instanceof CustomException) {
|
|
116
|
+
code = ((CustomException) exception).getCode();
|
|
117
|
+
}
|
|
118
|
+
Logger.error(TAG, message, exception);
|
|
119
|
+
call.reject(message, code);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private void rejectCallAsUnimplemented(@NonNull PluginCall call) {
|
|
123
|
+
call.unimplemented("This method is not available on this platform.");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private void resolveCall(@NonNull PluginCall call) {
|
|
127
|
+
call.resolve();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private void resolveCall(@NonNull PluginCall call, @Nullable Result result) {
|
|
131
|
+
if (result == null) {
|
|
132
|
+
call.resolve();
|
|
133
|
+
} else {
|
|
134
|
+
call.resolve(result.toJSObject());
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.appintegrity.classes;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
5
|
+
|
|
6
|
+
public class CustomException extends Exception {
|
|
7
|
+
|
|
8
|
+
@Nullable
|
|
9
|
+
private final String code;
|
|
10
|
+
|
|
11
|
+
public CustomException(@Nullable String code, @NonNull String message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.code = code;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@Nullable
|
|
17
|
+
public String getCode() {
|
|
18
|
+
return code;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.appintegrity.classes;
|
|
2
|
+
|
|
3
|
+
public class CustomExceptions {
|
|
4
|
+
|
|
5
|
+
public static final CustomException CLOUD_PROJECT_NUMBER_MISSING = new CustomException(null, "cloudProjectNumber must be provided.");
|
|
6
|
+
public static final CustomException INTEGRITY_TOKEN_PROVIDER_NOT_PREPARED = new CustomException(
|
|
7
|
+
null,
|
|
8
|
+
"No integrity token provider available. Call prepareIntegrityToken() first."
|
|
9
|
+
);
|
|
10
|
+
public static final CustomException NONCE_OR_REQUEST_HASH_MISSING = new CustomException(null, "nonce or requestHash must be provided.");
|
|
11
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.appintegrity.classes.options;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import com.getcapacitor.PluginCall;
|
|
5
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.classes.CustomExceptions;
|
|
6
|
+
|
|
7
|
+
public class PrepareIntegrityTokenOptions {
|
|
8
|
+
|
|
9
|
+
private final long cloudProjectNumber;
|
|
10
|
+
|
|
11
|
+
public PrepareIntegrityTokenOptions(@NonNull PluginCall call) throws Exception {
|
|
12
|
+
this.cloudProjectNumber = PrepareIntegrityTokenOptions.getCloudProjectNumberFromCall(call);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public long getCloudProjectNumber() {
|
|
16
|
+
return cloudProjectNumber;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private static long getCloudProjectNumberFromCall(@NonNull PluginCall call) throws Exception {
|
|
20
|
+
Object value = call.getData().opt("cloudProjectNumber");
|
|
21
|
+
if (value instanceof Number) {
|
|
22
|
+
return ((Number) value).longValue();
|
|
23
|
+
}
|
|
24
|
+
throw CustomExceptions.CLOUD_PROJECT_NUMBER_MISSING;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.appintegrity.classes.options;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
5
|
+
import com.getcapacitor.PluginCall;
|
|
6
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.classes.CustomExceptions;
|
|
7
|
+
|
|
8
|
+
public class RequestIntegrityTokenOptions {
|
|
9
|
+
|
|
10
|
+
@Nullable
|
|
11
|
+
private final Long cloudProjectNumber;
|
|
12
|
+
|
|
13
|
+
@Nullable
|
|
14
|
+
private final String nonce;
|
|
15
|
+
|
|
16
|
+
@Nullable
|
|
17
|
+
private final String requestHash;
|
|
18
|
+
|
|
19
|
+
public RequestIntegrityTokenOptions(@NonNull PluginCall call) throws Exception {
|
|
20
|
+
this.cloudProjectNumber = RequestIntegrityTokenOptions.getCloudProjectNumberFromCall(call);
|
|
21
|
+
this.nonce = call.getString("nonce");
|
|
22
|
+
this.requestHash = call.getString("requestHash");
|
|
23
|
+
if (this.nonce == null && this.requestHash == null) {
|
|
24
|
+
throw CustomExceptions.NONCE_OR_REQUEST_HASH_MISSING;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@Nullable
|
|
29
|
+
public Long getCloudProjectNumber() {
|
|
30
|
+
return cloudProjectNumber;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@Nullable
|
|
34
|
+
public String getNonce() {
|
|
35
|
+
return nonce;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@Nullable
|
|
39
|
+
public String getRequestHash() {
|
|
40
|
+
return requestHash;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@Nullable
|
|
44
|
+
private static Long getCloudProjectNumberFromCall(@NonNull PluginCall call) {
|
|
45
|
+
Object value = call.getData().opt("cloudProjectNumber");
|
|
46
|
+
if (value instanceof Number) {
|
|
47
|
+
return ((Number) value).longValue();
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.appintegrity.classes.results;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import com.getcapacitor.JSObject;
|
|
5
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.interfaces.Result;
|
|
6
|
+
|
|
7
|
+
public class IsAvailableResult implements Result {
|
|
8
|
+
|
|
9
|
+
private final boolean available;
|
|
10
|
+
|
|
11
|
+
public IsAvailableResult(boolean available) {
|
|
12
|
+
this.available = available;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@Override
|
|
16
|
+
@NonNull
|
|
17
|
+
public JSObject toJSObject() {
|
|
18
|
+
JSObject result = new JSObject();
|
|
19
|
+
result.put("available", available);
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.appintegrity.classes.results;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import com.getcapacitor.JSObject;
|
|
5
|
+
import io.capawesome.capacitorjs.plugins.appintegrity.interfaces.Result;
|
|
6
|
+
|
|
7
|
+
public class RequestIntegrityTokenResult implements Result {
|
|
8
|
+
|
|
9
|
+
@NonNull
|
|
10
|
+
private final String token;
|
|
11
|
+
|
|
12
|
+
public RequestIntegrityTokenResult(@NonNull String token) {
|
|
13
|
+
this.token = token;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@Override
|
|
17
|
+
@NonNull
|
|
18
|
+
public JSObject toJSObject() {
|
|
19
|
+
JSObject result = new JSObject();
|
|
20
|
+
result.put("token", token);
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
File without changes
|