Session token verification issue

dmogil
New Member
7 0 0

Hi guys, I have a PHP code:

$jwtArr = array_combine(['header', 'payload', 'signature'], explode('.', explode(" ", $_SERVER['HTTP_AUTHORIZATION'])[1]));
$calculatedHash = hash("sha256", $jwtArr['header'] . '.' . $jwtArr['payload']); //hashing two joined arguments
$calculatedHash = hash_hmac('sha256', $calculatedHash, SECRET_KEY, true); //hmac the result
$calculatedHash = base64_encode($calculatedHash); //base64 encode

echo $calculatedHash . PHP_EOL; //result
echo $jwtArr['signature']; //signature from the session token

Its been written based on this instruction: https://shopify.dev/tutorials/authenticate-your-app-using-session-tokens#verify-the-signature

But the result never the same as the signature, and I can't get in mind what am I doing wrong. Please help!

0 Likes
dmogil
New Member
7 0 0

Nevermind. $calculatedHash = hash("sha256", $jwtArr['header'] . '.' . $jwtArr['payload']); - this one wasn't needed. I just wrong understand the instruction. 

If anyone needs ready PHP solution:

function verify_session_token($token){
		$jwtArr = array_combine(['header', 'payload', 'signature'], explode('.', $token)); //convert token to associative array
		$calculatedHash = hash_hmac('sha256', $jwtArr['header'] . '.' . $jwtArr['payload'], SECRET_KEY, true); //hmac the two first arguments
		$calculatedHash = rtrim(strtr(base64_encode($calculatedHash), '+/', '-_'), '='); //base64 url encode, trim =
		return $calculatedHash === $jwtArr['signature'];
	}
0 Likes
Jorem
New Member
3 0 0

Can you please share code for this $token variable?

0 Likes
dmogil
New Member
7 0 0

Not sure what you mean

0 Likes
Jorem
New Member
3 0 0

How can I get that $token variable data from Shopify so I can pass in above function to verify.

0 Likes
dmogil
New Member
7 0 0

On front-end site you get token using AppBridge:

var utils=window['app-bridge-utils'];

utils.getSessionToken(app)

.then(res=>sessionToken=res);

and then using it making authenticated requests, by attaching it to headers of the request

let opts={
method: "POST",
    headers: { 
    "Content-Type": "application/json",
    "Authorization": "Bearer: "+sessionToken
    }
};
Then you get it from the header on server side and use above function to verify it
0 Likes
Jorem
New Member
3 0 0

So we have to do two authentication, this is so confusing?

1. Auth.

 

$shared_secret    = "";
$params         = $_GET; 
$hmac           = $_GET['hmac'];
$params         = array_diff_key($params, array('hmac' => ''));
ksort($params); 
$computed_hmac = hash_hmac('sha256', http_build_query($params), $shared_secret);
if ( hash_equals($hmac, $computed_hmac) ) {
            
} else {
            
}

 

 

2. Authenticate an embedded app using session tokens

0 Likes
Saifullah_Bin_A
Tourist
8 0 2

Which PHP JWT library you are using to verify the payload? Or only verifying signature?

0 Likes
darakhsa_farhan
New Member
9 0 0

When JWT token will expire after 1 minute then what to do to handle this thing in our Apps. Can you please provide step by step details for how to integrate JWT tokens part in our APP?

FYI: My APP using PHP technology.

0 Likes
ParanoidAndroid
New Member
2 0 0

Thank you for this, but note this only verifies the signature. You still need to verify the payload. Here is how I've done that.

 

const CLIENT_ID = '';
const CLIENT_SECRET = '';

function verifyJWT($token) {
    //verify signature
    $jwtArr = array_combine(['header', 'payload', 'signature'], explode('.', $token)); //convert token to associative array
    $calculatedHash = hash_hmac('sha256', $jwtArr['header'] . '.' . $jwtArr['payload'], CLIENT_SECRET, true); //hmac the two first arguments
    $calculatedHash = rtrim(strtr(base64_encode($calculatedHash), '+/', '-_'), '='); //base64 url encode, trim =
    $signature_verified = $calculatedHash === $jwtArr['signature'];
    if(!$signature_verified) return false;
    $payload = json_decode(base64_decode($jwtArr['payload']));
    //verify not before time
    if(time() < $payload->nbf) return false;
    //verify expiration
    if($payload->exp < time()) return false;
    //make sure shopify domains exist in each place
    if(!strstr($payload->iss, $payload->dest)) return false;
    //verify AUD matches our key
    if($payload->aud != CLIENT_ID) return false;
    return true;
}

 

 

0 Likes