firebase / php-jwt

PHP package for JWT

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

FirebaseAuthInvalidCredentialsException: The custom token format is incorrect

varun7952 opened this issue · comments

Hi I have an app using it's own server for authentications of users and other stuff except user chatting part which depends on Firebase Realtime Database, To secure my data on Firebase and App Server i am generating the JWT After generating JWT i am passing it to

firebaseAuth.signInWithCustomToken(Session.getJWT())
    .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
         @Override
         public void onComplete(@NonNull Task<AuthResult> task) {
         // Here i get the exeception
         //com.google.android.gms.tasks.RuntimeExecutionException: com.google.firebase.auth.FirebaseAuthInvalidCredentialsException: The custom token format is incorrect. Please check the documentation.
         }
         });

On app side this functions calls only when user login successfully and session never expire like all apps until user logout itself, that JWT token will stay on app for months and firebase allows only 1 hour expiry

So this is the same token which i am using to validate the app request to API and i saw somewhere that i need to set expiry to maximum one hour and if i gonna set it 1 hour then it will not work on app server side API validation. I am not sure how can i generate JWT for both sides because my existing way is showing the custom token format is incorrect.

The function which generate the token in PHP

function generateJWT($con,$userID,$cretedTime) {
    $secret_Key  = "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXZYPWn0x0zltm\nk1uZiT/GwsB8izRu2uYpCQFrSPsqGZ/TaHHB1/SpMhEG2VOPBrcxOweqM0tyIx49\nt9lljZuuUiI3Cmeji2epWkPQJvBJIjKwl/6hcXAoVI0nPc82oUewSQFwbPOVCKq7\nM/JLKLSt9wpctxoutXUMD6idyHIiKQZdtKawSTRnMuylNCb5fUtKU7UuQbCnEOdF\nGPSgOdvxEi4lwQ8k0HSnj0ZQzJ7hkqS9da1DKYi1IMQn7IsL5RzOgY28Gb0l2gn\nK9rBoQtnxQKBgQCHUze4MRW7ExP0rkG93gRNXjopg/akjq0oG/VDO7rv85Pjw4Yx\nitVchWwu9lEtj5HlVRq/oti9b0aohZexNxrKJAE+68h5b8MRhoKkDXmQkWzYR0+j\nnlLgcj2qaEr/y+Utq8jj9F8I6uS3pF/zvcih0aS7j7p/VG3fAjBUy/uaXQKBgGDk\nS9ARY7wE0vfZqEO7FbUAsVktik3g9bwkwTivp1G7Zoq+hlfi0gPcZ7RxcBFsH7Ht\nrEBkUPOB+DYNnqoakH8+8lB9TboZEYepJB39qkuK/RweKoQdwVsBUpQGVrzPoemt\n0wRERBCMrqkfyY1fqDKFUkCigERBdL6fKTr+Gze9AoGAMcMsIfjxf8eZiSev7T4s\nvS1t404foWpWqcjoJpse/UWJnyKSmMKzJ/ulNOclq76MJN4YO5k8AdysXK8+azZG\n6i8qxXf9T/jnGoJSsxJ9KMolMMW+EF9B5mn61vQJyW72tCFoXFcOIBrGQS+THCPW\nAtY9K1/19yScEhdmhw8Ozek=\n-----END PRIVATE KEY-----\n";
    $date   = time();
    //$expire_at     = $date->modify('+3 minutes')->getTimestamp(); // Add 60 seconds
    $domainName = "firebase-adminsdk-xxxx@xxxx-xxxx.iam.gserviceaccount.com";

    $request_data = [
    'iss'  => $domainName, 
    'sub' => $domainName,
    'aud' => "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
    'iat'  => $date,         // Issued at: time when the token was generated
                              // Issuer
    //'exp' => $date+(60*60),  // Maximum expiration time six month in seconds //15778476 
    'uid' => $userID,                     // User name
    'created' => $cretedTime,                     // User name
    ];
     $newToken = JWT::encode($request_data,$secret_Key,'RS256');
     return $newToken; 
    
}

The token is not valid with the current setup, it may be because of i am not using the expiry for firebaseAuth.signInWithCustomToken(Session.getJWT()) but setting expiry might break the server API validations too. Anyone have idea how to resolve the issue i have.

Tokens used for firebase auth need to follow the format and specification defined in the docs: https://firebase.google.com/docs/auth/admin/create-custom-tokens

The maximum expiration of 3600 seconds in the future is indeed one of the requirements. You also seem to have a 'created' claim that I is not listed.

You probably need to create two tokens if you need one with exp 3600 seconds in the future, and another with a longer time. Also note what is mentioned in the Firebase docs: But once you sign a user in using signInWithCustomToken(), they will remain signed in into the device until their session is invalidated or the user signs out.

@Krisell Thanks for the answer. Generating 2 token is not a good idea i guess. Created is the extra payload that i need to check on app server and the requirement of Firebase token created time iat is present in the token.

Is there anyway i can make token valid on app server, if i set expiry of 1 hour and ignore the expiry variable when checking the JWT

function checkJWT($con,$userID,$jwt) {
	$now = new DateTimeImmutable();
	$domainName = "firebase-xxxxxx-xxxxxx@xxxxxx-xxxxxx-xxxxxx.iam.gserviceaccount.com";
	$secret_Key  = "-----BEGIN PRIVATE KEY-----\xxxxxxqxxxxxx\n-----END PRIVATE KEY-----\n";
	$sql = "SELECT JWT,created FROM sample where ID = $userID";
	
	$res = mysqli_query($con,$sql);
	$data = mysqli_fetch_array($res);	
	if($data['JWT'] == $jwt){
	$res = openssl_get_privatekey($secret_Key);
    $details = openssl_pkey_get_details($res);
	$publicKey = $details['key'];
    $token = JWT::decode($jwt, new Key($publicKey, 'RS256'));
	$time = $data['created'];
	if ($token->iss !== $domainName || $token->uid !== $userID || $token->created !== $time){
		
		return false;			
	}else{
		return true;			
	}

	}
}

As this is a question regarding the Firebase Realtime Database, I am closing it. This library is a utility library for signing JWTs and (despite the fact that it's in the Firebase organization) does not apply specifically to FRD.