I have a problem for decrypt token from StandardIntegrityToken in Unity and back-end use Firebase function. Code in unity:
public async UniTask<(string, string)> RequestIntegrityToken()
{
return await PrepareIntegrityTokenAsync();
}
private async UniTask<(string, string)> PrepareIntegrityTokenAsync()
{
// Create an instance of a standard integrity manager.
var standardIntegrityManager = new StandardIntegrityManager();
// Request the token provider.
var integrityTokenProviderOperation =
standardIntegrityManager.PrepareIntegrityToken(
new PrepareIntegrityTokenRequest(CLOUD_PROJECT_NUMBER));
// Wait for PlayAsyncOperation to complete.
await integrityTokenProviderOperation.ToUniTask();
// Check the resulting error code.
if (integrityTokenProviderOperation.Error != StandardIntegrityErrorCode.NoError)
{
Debug.LogError("StandardIntegrityAsyncOperation failed with error: " +
integrityTokenProviderOperation.Error);
return (null, null);
}
// Get the response.
var integrityTokenProvider = integrityTokenProviderOperation.GetResult();
string randomString = IntegrityTokenHelper.GenerateRandomString(20);
string expectedRequestHash = IntegrityTokenHelper.GenerateRequestHash(randomString);
var integrityTokenOperation = integrityTokenProvider.Request(new StandardIntegrityTokenRequest(expectedRequestHash));
await integrityTokenOperation.ToUniTask();
if (integrityTokenOperation.Error != StandardIntegrityErrorCode.NoError)
{
return (null, null);
}
// Get the response.
var integrityToken = integrityTokenOperation.GetResult();
return (integrityToken.Token, expectedRequestHash);
}
Code in firebase function:
const axios = require("axios");
const { OAuth2Client } = require("google-auth-library");
const auth = new OAuth2Client({
keyFile: 'credentials/service-account-file.json',
scopes: ['']
});
exports.verifyAndSaveData = onCall(
{ enforceAppCheck: true },
async (request) => {
if (!request.app) {
return { success: false, banReason: "App check failed" };
}
try {
const token = request.data.token;
const expectedRequestHash = request.data.expectedRequestHash;
const userId = request.data.userId;
const existingPlayerAuthData = await fetchPlayerAuthData(userId);
if (existingPlayerAuthData && existingPlayerAuthData.is_banned) {
return { success: false, banReason: existingPlayerAuthData.ban_reason };
}
const client = await auth.getClient();
const accessToken = await client.getAccessToken();
const url = `/${expectedPackageName}:decodeIntegrityToken`;
const response = await axios.post(
url,
{ integrity_token: token },
{ headers: { Authorization: `Bearer ${accessToken.token}` } }
);
if (!response.data) {
return { iserror: true, success: false, banReason: "Decode Integrity Token Failed" };
}
let isBanned = false;
let banReason = "";
const payload = response.data;
const requestDetails = payload.requestDetails;
const requestPackageName = requestDetails.requestPackageName;
const requestHash = requestDetails.requestHash;
const timestampMillis = requestDetails.timestampMillis;
const currentTimestampMillis = Date.now();
if (requestPackageName !== expectedPackageName
|| requestHash !== expectedRequestHash
|| currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS)
{
isBanned = true;
banReason = "Fake token integrity";
}
else
{
const appIntegrity = payload.appIntegrity.appRecognitionVerdict;
const deviceIntegrityArray = payload.deviceIntegrity.deviceRecognitionVerdict || [];
const licensingVerdict = payload.accountDetails.licensingVerdict;
if (appIntegrity !== "PLAY_INTEGRITY_VERDICT_OK") {
isBanned = true;
banReason = "App integrity check failed";
}
if (deviceIntegrityArray.includes("MEETS_DEVICE_INTEGRITY")) {
isBanned = true;
banReason = "Device integrity check failed";
}
if (licensingVerdict !== "LICENSED") {
isBanned = true;
banReason = "App not licensed";
}
}
const playerAuthRef = admin.firestore().collection("player_auth").doc(userId);
if (existingPlayerAuthData) {
await playerAuthRef.update({
is_banned: isBanned,
ban_reason: isBanned ? banReason : "",
lastChecked: admin.firestore.FieldValue.serverTimestamp(),
});
}
if (isBanned) {
return { success: false, banReason: existingPlayerAuthData.ban_reason };
}
return { success: true, banReason: "" };
} catch (error) {
return { iserror: true, success: false, banReason: error.message };
}
}
);
I use documents from this source:
And I got the error:
Wrong number of segments in token: CtsCARCnMGsxYSAjH2rAlbYYJlUvq4CGkyb_M154Merg6GnC-wdTMcjSibJwOOerVlYtQ3kpiVZgwM2_rHYXDbvUxCfp9Uvh40Ie8L3Z7_S98ZH1c0_91OS-oECtcylE7kLkKtv53ibOfIKjKxYl_iBfdx1Ilq4bTJhQy2kFEJd8Q2lp-MQWuSyGgR6mmVVH4uKnixvjLQv8WU_Qmt8WiaajNtkkTBdxwQWVU0OlqE1SwqMLmnifdDPbfJvhMgaV7cIWWe5Q00qJZc3nSKmyST8_M_kFGm_G4FC4kWT1o_NrIAbgaSuFXGyWUTfL38UhFTGRg74p8psW3RRA5Do9hUDlImdcM-jICx1qtU11yE5afYZukrOAGklyAiUUUnbtNdp_yfyw--98NK5_wuKQj906t9iSQ0ni0DK5axN9oBfab3b4k9EvBw3lRkXk-DhgRaBZ-0RsJNHhlXGlXC4afgHMcfsFFjTZ8B79lFbwTjiFIU8RogAqvQEf2B9blQaF9uUWxP-AXjFNeXEgCYhFtAAb0ac7s5WGX3sifRjPf4vU7DddT1Y1613y4o9G-6dgGLKy2dFS4-irlo5c0rIyfQbumIlcB6Yfxx9oQhUIdmM8G8X0TRQVUMNl8JJHzg
It seems there is a problem with my token. Has anyone encountered this problem?
I try to use debug my code and get the error from my token send to api google.