Re: Embedded App - how to decode and use the session token?

Embedded App - how to decode and use the session token?

ddaine
Excursionist
14 0 3

I would like to verify the user who wants to access the admin panel of my Shopify app after the app is already installed in the shop. Shopify delivers a session token as a parameter, if the user wants to access the admin panel. As far as my understanding goes, the session token is exactly for that, to verify the shop and if the user is authenticated at the Shopify site.

 

What do I do with it? In the manual it is referenced as a JWT token but it does not have the structure header.payload.signature. So I don't really know what to do with it. I don't want to use any foreign library.

Replies 6 (6)

ddaine
Excursionist
14 0 3

I would like to refresh this thread to increase the chance that somebody will see it.

akcps
Visitor
1 0 0

I have the same issue.

I can see some documentation around it. https://shopify.dev/tutorials/authenticate-your-app-using-session-tokens#verify-the-signature

But it is difficult to comprehend it. 

 

Can someone help?

ddaine
Excursionist
14 0 3

How does your application architecture look like? Do you work with a backend?

Cartbear
Tourist
9 0 3

Hi ddaine,

a bit more context about your embedded app would be useful.

I use t the getSessionToken function from the app-bridge-utils to obtain session tokens. To validate the token I send it to the backend.

You could decode the jwt token on the client-side using libraries like jwt-decode. If you don't want to use a 3rd party library as you mentioned, you could check the code to learn how jwt tokens are encoded.

To make sure the jwt token was issued by Shopify the signature needs to be verified. This is really important for security reasons. Since your app's secret key was used to sign the token you should validate it in your backend. Otherwise, you would have to expose the secret to the client to perform the validation. That would cause more security issues.

Another idea would be to use the token and call an endpoint of the Shopify Admin API directly (if you don't have a backend). E.g. get the shop configuration. If the call returns a successful response you can be sure that the user has access to your shop.


Just some thoughts. Hope it helps.

 

 

 

 

 

MRG @ Cartbear
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
ddaine
Excursionist
14 0 3
Hello and thanks for your reply, Cartbear. My intentions was to reply to akcps, b/c I was able to solve the problem with a little bit of headache.
hackerunet
Shopify Partner
3 0 0

I think this piece of code could help someone:

verifyTokenSignature(token: JsonWebtoken, originalToken: string): boolean {
    const { exp, nbf, iss, dest, aud, sub } = token;
    console.log(originalToken);

    if (exp <= Math.floor(Date.now() / 1000)) {
      throw new Error('Token expiration time has passed');
    }

    if (nbf > Math.floor(Date.now() / 1000)) {
      throw new Error('Token is not yet valid');
    }

    const issDomain = iss.split('//')[1].split('/')[0];
    const destDomain = dest.split('//')[1].split('/')[0];

    if (issDomain !== destDomain) {
      throw new Error('Iss and Dest top-level domains do not match');
    }

    if (aud !== process.env.SHOPIFY_API_KEY) {
      throw new Error('Invalid clientId provided');
    }

    const [header, payload, signature] = originalToken.split('.');
    const generatedSignature = crypto
      .createHmac('sha256', process.env.SHOPIFY_API_SECRET)
      .update(header + payload)
      .digest('base64');

    console.log(generatedSignature, signature);
    if (generatedSignature !== signature) {
      throw new Error('Invalid signature');
    }

    const hashedSegments = Buffer.from(header + payload);
    console.log(hashedSegments);

    return true;
  }