1nikolas / play-integrity-checker-app Goto Github PK
View Code? Open in Web Editor NEWGet info about your Device Integrity through the Play Intergrity API
License: MIT License
Get info about your Device Integrity through the Play Intergrity API
License: MIT License
Add API documentation link to About:
https://developer.android.com/google/play/integrity/overview
For people to learn what they are testing
It would be also nice to see JSON with verdict (like in YASNAC for SafetyNet)
Example
#6 (comment)
I found issue with that device passes device integrity at the time of install but after restart device, device Integrity check failed with following response.
{ "requestDetails": { "requestPackageName": "com.mantra.rdservice", "timestampMillis": "1674455009345", "nonce": "Y29tLm1hbnRyYS5yZHNlcnZpY2UyMDIzMDEyMzExNTIzMjajHDrnJ9vtl2AfC1fUdEDJmD_HfvFtcpc\u003d" }, "appIntegrity": { "appRecognitionVerdict": "UNEVALUATED" }, "deviceIntegrity": { }, "accountDetails": { "appLicensingVerdict": "UNEVALUATED" } }
There is a special case where I click on Check and it spins forever
Two logcats are attached
It can be reproduced by using Hide My Applist v3.1.1 (module for Zygisk LSPosed):
https://github.com/Dr-TSNG/Hide-My-Applist/releases/tag/V3.1.1
Install HMA and enable in LSposed, go to App manage, enable Show system apps
Find Google Play Store (com.android.vending), open and check Enable hide - as on the screenshot).
(That's a step toward configuring HMA to detach some apps from PlayStore)
Go back, reboot
Then open PI API Checker, click on Check and it will never end, nor report an error
See also:
https://forum.xda-developers.com/t/hide-my-applist-a-brief-guide.4519731/post-88264113
Looks like that Check is missing some timeout or error detection that PI API checking cannot be performed, to report an error
Just like to mention that you have typo in your playstore's title 'Play Intergrity API Checker'
Great job anyway ๐๐ผ
Following your example but unfortunately am not getting the token since it is giving an error as GOOGLE_SERVER__UNAVAILABLE. Have done the ground works like Play & Cloud console enablement.
You can check my code:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// playIntegritySetup.lol();
getToken();
}
private void getToken() {
String nonce = Base64.encodeToString(generateNonce(50).getBytes(), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
// Create an instance of a manager.
IntegrityManager integrityManager = IntegrityManagerFactory.create(getApplicationContext());
// Request the integrity token by providing a nonce.
Task<IntegrityTokenResponse> integrityTokenResponse = integrityManager.requestIntegrityToken(
IntegrityTokenRequest.builder()
.setNonce(nonce)
.build());
integrityTokenResponse.addOnSuccessListener(new OnSuccessListener<IntegrityTokenResponse>() {
@Override
public void onSuccess(IntegrityTokenResponse integrityTokenResponse) {
String integrityToken = integrityTokenResponse.token();
SplashActivity.this.doIntegrityCheck(integrityToken);
Log.e("Integrity Token", "integrity token from the app" + integrityToken);
}
});
integrityTokenResponse.addOnFailureListener(e -> showErrorDialog("Error getting token from Google. Google said: " + getErrorText(e)));
}
private void doIntegrityCheck(String token) {
AtomicBoolean hasError = new AtomicBoolean(false);
Observable.fromCallable(() -> {
OkHttpClient okHttpClient = new OkHttpClient();
Response response = okHttpClient.newCall(new Request.Builder().url("money control url" + "token from backend server" + token).build()).execute();
Log.e("Token", "token from the app" + token);
if (!response.isSuccessful()) {
hasError.set(true);
return "Api request error. Code: " + response.code();
}
ResponseBody responseBody = response.body();
if (responseBody == null) {
hasError.set(true);
return "Api request error. Empty response";
}
JSONObject responseJson = new JSONObject(responseBody.string());
if (responseJson.has("error")) {
hasError.set(true);
return "Api request error: " + responseJson.getString("error");
}
if (!responseJson.has("deviceIntegrity")) {
hasError.set(true);
}
return responseJson.getJSONObject("deviceIntegrity").toString();
}) // Execute in IO thread, i.e. background thread.
.subscribeOn(Schedulers.io())
// report or post the result to main thread.
.observeOn(AndroidSchedulers.mainThread())
// execute this RxJava
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String result) {
if (hasError.get()) {
if (result.contains("MEETS_DEVICE_INTEGRITY") && result.contains("MEETS_BASIC_INTEGRITY")) {
//Here goes my other code
}
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
private String getErrorText(Exception e) {
String msg = e.getMessage();
if (msg == null) {
return "Unknown Error";
}
//the error code
int errorCode = Integer.parseInt(msg.replaceAll("\n", "").replaceAll(":(.*)", ""));
switch (errorCode) {
case IntegrityErrorCode.API_NOT_AVAILABLE:
return "API_NOT_AVAILABLE";
case IntegrityErrorCode.NO_ERROR:
return "NO_ERROR";
case IntegrityErrorCode.INTERNAL_ERROR:
return "INTERNAL_ERROR";
case IntegrityErrorCode.NETWORK_ERROR:
return "NETWORK_ERROR";
case IntegrityErrorCode.PLAY_STORE_NOT_FOUND:
return "PLAY_STORE_NOT_FOUND";
case IntegrityErrorCode.PLAY_STORE_ACCOUNT_NOT_FOUND:
return "PLAY_STORE_ACCOUNT_NOT_FOUND";
case IntegrityErrorCode.APP_NOT_INSTALLED:
return "APP_NOT_INSTALLED";
case IntegrityErrorCode.PLAY_SERVICES_NOT_FOUND:
return "PLAY_SERVICES_NOT_FOUND";
case IntegrityErrorCode.APP_UID_MISMATCH:
return "APP_UID_MISMATCH";
case IntegrityErrorCode.TOO_MANY_REQUESTS:
return "TOO_MANY_REQUESTS";
case IntegrityErrorCode.CANNOT_BIND_TO_SERVICE:
return "CANNOT_BIND_TO_SERVICE";
case IntegrityErrorCode.NONCE_TOO_SHORT:
return "NONCE_TOO_SHORT";
case IntegrityErrorCode.NONCE_TOO_LONG:
return "NONCE_TOO_LONG";
case IntegrityErrorCode.GOOGLE_SERVER_UNAVAILABLE:
return "GOOGLE_SERVER_UNAVAILABLE";
case IntegrityErrorCode.NONCE_IS_NOT_BASE64:
return "NONCE_IS_NOT_BASE64";
default:
return "Unknown Error";
}
}
private String generateNonce(int length) {
String nonce = "";
String allowed = getNonce();
for (int i = 0; i < length; i++) {
nonce = nonce.concat(String.valueOf(allowed.charAt((int) Math.floor(Math.random() * allowed.length()))));
}
return nonce;
}
public native String getNonce();
static {
System.loadLibrary("all-keys");
}
Today at around 18 CET, there was already a rate limit for the 10k tests per day and the error message said we have to wait midnight PT, which is 9 CET (so the app is unusable more than half a day).
It would be nice if users cannot easily abuse the rate limit and affect other users, by allowing around 5 requests a day per IP address.
I've just got an error message, error getting token form google
The calling app is making too many requests to the API and hance is throttled.
This shouldn't happen. If it does please open an issue on Github.
i hav used this app to chck my intgeity status, becuse play certification checking app say it passes but play store and gpay say my phone is not certified. I have Xaomi mi 9 and i was using EvolutionX rom and i had root instaled. It was all working fine but after a while form one day to another it stoped and while trying to pay said my device is not meeting security requirements. Done factory reset already, clean flush of ROM, other roms as well, and it's still not woroking even thou i havent installed root yet, just basic rom that sould have all certifications. Can someone help me?
Hi.
I am trying to run your app and when I click CHECK it reports:
Error
Error getting token from Google. Google
said: API_NOT_AVAILABLE
This was at least running before I installed Magisk 25.2.
As an additional data item, Google Play Store is also reporting that I am offline even though I really am. Many online functions are working perfectly fine.
I have done the typical Magisk Deny List application to hide root from Google services and installed the universal safetynet fix module v2.3.1.
Anything more I need to do?
When I try the play integrity API checker on my pixel 7 pro a message shows up:"Error getting token from Google
The calling app UID (user id) does not match the one from Package Manager.
This shouldn't happen. If it does please open an issue on Github."
When I use YASNAC the result is:"Google Play Services API error
17: APLNOT_CONNECTED"
qianhe
Version 1.1 (11) from Google Play. Default settings, no server config modifications.
Xiaomi mi 11 ultra. Latest Xiaomi.eu build on A13
Would it be possible to run the integrity check via adb (with the app installed)?
It would be really nice if there was an option to periodically check the integrity and notify if a change occurs. (From passing to failing)
Edit: I guess #18 kinda would prevent that. Didn't realize this needed to check against a rate limited Google server :S
It seems that for non playstore apps to request an integrity token, the setCloudProjectNumber
field must be set here. Without this number set, it is not possible to use a custom api server. The cloud project number can be found here using the api tester. I'm curious if you would also consider adding this as a variable that can be accessed through the local.properties
file, similar to the API_URL
property.
Also the API_URL
specified in the readme is incorrect with a trailing /
because the app itself already appends the /
. Please consider correcting the documentation.
Lastly, in my use case, I modified the server a little bit so that I could use it outside of Vercel in a local Docker environment. With this, I ran into an issue where accessing my local server directly by IP in the local environment resulted in an error, so I had to add android:usesCleartextTraffic="true"
to the manifest as specified here. I understand if you may not want to add this to the main app, but it would be a helpful hint to also have in the documentation.
Thanks for making this wonderful app!
Error getting token from Google
The calling app is making too many requests to the API and hence is throttled.
Are you able to create compiled assets for download?
This issue is hitting everyone right now and your checker is sorely needed to help people understand the issue.
Only found one compiled apk on XDA and it appears your v2 now shows more info:
kdrag0n/safetynet-fix#203 (comment)
Hope it get to Google Play soon, but Google is notoriously slow!
This is to avoid issues like #5 and #8
Instead of showing the error id, add the explanation according to the documentation
https://developer.android.com/reference/unity/namespace/Google/Play/Integrity
Unban please
I'd like to check if my device has the basic and device integrity every 12 or 24 hours and get a notification when it doesn't.
This would help me react and update my Magisk modules so that Google Wallet keeps working with NFC payments.
Now, I usually learn that I lost the NFC payment option right at the terminal.
This feature would help prevent the problematic situation.
What do you think?
Could you add it or guide me/others through how we could achieve this?
Thanks!
Hello.
Background: SecurID's recent update (version 4.1.5.7 in September 2022) apparently has switched to using Play Integrity API for checking if a phone has been 'rooted', and they are citing your application in checking for integrity. I have three phones, none of them 'rooted' in any way, none of them have any developer switches enabled (as far as I know), Android versions 8, 10, and 11.
Both SecurID and your checker application fail against my Android 8 and 10 phones (three crosses) but seem to work okay on the Android 11 phone (three ticks). I'm not an Android developer by any means, so any clues as to why this might be happening might be helpful.
(If one looks at the recent reviews for SecurID within the last few days (19-21 September 2022) I am clearly not the only one running afoul of this new 'root' detection method.)
Appreciate any help with this. Thanks.
please release .apk on github repo
some testing devices that are inconvenient to log in play store
thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.