# Jwt verify in php

**URL:** <https://staging-discuss.dev.twitch.com/t/jwt-verify-in-php/46231>\
**Category:** Extensions\
**Created:** [June 25, 2023, 12:23am UTC](https://staging-discuss.dev.twitch.com/t/jwt-verify-in-php/46231 "2023-06-25T00:23:00Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Andy](https://d1d6mrmdu7ztse.cloudfront.net/user_avatar/staging-discuss.dev.twitch.com/andy/32/25168_2.png) [@Andy](https://staging-discuss.dev.twitch.com/u/Andy)\
**Post date:** [June 25, 2023, 12:23am UTC](https://staging-discuss.dev.twitch.com/t/jwt-verify-in-php/46231/1 "2023-06-25T00:23:01Z")

</div>

Hello 🙂 i try to verify a jwt token. But its always false. Here is my code i use

```auto
function validate_twitch_jwt($jwt) {
    $secretKey = 'XXXXXXXXXXXXXXXXXCXXXXXX=';
    $jwtParts = explode('.', $jwt);

    $header = base64_decode($jwtParts[0]);
    $payload = base64_decode($jwtParts[1]);
    $signature = base64_decode($jwtParts[2]);
    $expectedSignature = hash_hmac('sha256', $jwtParts[0] . '.' . $jwtParts[1], $secretKey, true);

    if ($signature !== $expectedSignature) {
        echo "false";
    }
    else {
        echo "true";
    }
}

```

---

<div class="post-metadata">

**Author:** ![BarryCarlyon](https://d1d6mrmdu7ztse.cloudfront.net/user_avatar/staging-discuss.dev.twitch.com/barrycarlyon/32/253_2.png) [@BarryCarlyon](https://staging-discuss.dev.twitch.com/u/BarryCarlyon)\
**Post date:** [June 25, 2023, 12:26am UTC](https://staging-discuss.dev.twitch.com/t/jwt-verify-in-php/46231/2 "2023-06-25T00:26:25Z")

</div>

Use a library [GitHub - firebase/php-jwt: PHP package for JWT](https://github.com/firebase/php-jwt)

A snippet from an older EBS (older as in I don’t use it anymore)

```php
$secret = base64_decode(LIVE_EXTENSION_SECRET);

include( __DIR__. '/lib/jwt.php');
$j = new JWT();

try {
    $res = $j->decode($token, $secret);
} catch (Exception $e) {
    $output['error'] = 'J An Error Occured';
    $output['error'] = $e->getMessage();
    echo json_encode($output);
    exit;
}

$opaque = $res->opaque_user_id;
$permissions = $res->pubsub_perms;
$channel_id = $res->channel_id;

```

This snippet may not longer be valid since my copy of the library is from 2017, and the github repo I linked has a much newer/changed version.

---

<div class="post-metadata">

**Author:** ![Andy](https://d1d6mrmdu7ztse.cloudfront.net/user_avatar/staging-discuss.dev.twitch.com/andy/32/25168_2.png) [@Andy](https://staging-discuss.dev.twitch.com/u/Andy)\
**Post date:** [June 25, 2023, 12:50am UTC](https://staging-discuss.dev.twitch.com/t/jwt-verify-in-php/46231/3 "2023-06-25T00:50:06Z")

</div>

to be sure i use the Extension secret from the extension settings page. The one with the `=` at the end.

---

<div class="post-metadata">

**Author:** ![BarryCarlyon](https://d1d6mrmdu7ztse.cloudfront.net/user_avatar/staging-discuss.dev.twitch.com/barrycarlyon/32/253_2.png) [@BarryCarlyon](https://staging-discuss.dev.twitch.com/u/BarryCarlyon)\
**Post date:** [June 25, 2023, 12:51am UTC](https://staging-discuss.dev.twitch.com/t/jwt-verify-in-php/46231/4 "2023-06-25T00:51:30Z")

</div>

JWT’s are validatded using the `Extension Client Configuration` - `Extension Secrets` yes, generally ends `=` but may not

---

<div class="post-metadata">

**Author:** ![Andy](https://d1d6mrmdu7ztse.cloudfront.net/user_avatar/staging-discuss.dev.twitch.com/andy/32/25168_2.png) [@Andy](https://staging-discuss.dev.twitch.com/u/Andy)\
**Post date:** [June 25, 2023, 12:58am UTC](https://staging-discuss.dev.twitch.com/t/jwt-verify-in-php/46231/5 "2023-06-25T00:58:52Z")

</div>

Well it says still `{"error":"Signature verification failed"}`

---

<div class="post-metadata">

**Author:** ![BarryCarlyon](https://d1d6mrmdu7ztse.cloudfront.net/user_avatar/staging-discuss.dev.twitch.com/barrycarlyon/32/253_2.png) [@BarryCarlyon](https://staging-discuss.dev.twitch.com/u/BarryCarlyon)\
**Post date:** [June 25, 2023, 12:59am UTC](https://staging-discuss.dev.twitch.com/t/jwt-verify-in-php/46231/6 "2023-06-25T00:59:42Z")

</div>

Assuming you are using the current version of the library

Check if it needs or doesn’t need the Extentsion Secret base64 decoding first or not.

---

<div class="post-metadata">

**Author:** ![Andy](https://d1d6mrmdu7ztse.cloudfront.net/user_avatar/staging-discuss.dev.twitch.com/andy/32/25168_2.png) [@Andy](https://staging-discuss.dev.twitch.com/u/Andy)\
**Post date:** [June 25, 2023, 1:03am UTC](https://staging-discuss.dev.twitch.com/t/jwt-verify-in-php/46231/7 "2023-06-25T01:03:01Z")

</div>

seems not

```auto
$jwt = JWT::encode($payload, $key, 'HS256');
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
print_r($decoded);

```

---

<div class="post-metadata">

**Author:** ![Andy](https://d1d6mrmdu7ztse.cloudfront.net/user_avatar/staging-discuss.dev.twitch.com/andy/32/25168_2.png) [@Andy](https://staging-discuss.dev.twitch.com/u/Andy)\
**Post date:** [June 25, 2023, 1:37am UTC](https://staging-discuss.dev.twitch.com/t/jwt-verify-in-php/46231/8 "2023-06-25T01:37:12Z")

</div>

on [jwt.io](http://jwt.io) its possible to verify it. So the problemm must be in my code

---

<div class="post-metadata">

**Author:** ![BarryCarlyon](https://d1d6mrmdu7ztse.cloudfront.net/user_avatar/staging-discuss.dev.twitch.com/barrycarlyon/32/253_2.png) [@BarryCarlyon](https://staging-discuss.dev.twitch.com/u/BarryCarlyon)\
**Post date:** [June 25, 2023, 1:42am UTC](https://staging-discuss.dev.twitch.com/t/jwt-verify-in-php/46231/9 "2023-06-25T01:42:18Z")

</div>

Make sure you are verifing the token, not desconstructing and reconstructing it then verifying that

---

<div class="post-metadata">

**Author:** ![Andy](https://d1d6mrmdu7ztse.cloudfront.net/user_avatar/staging-discuss.dev.twitch.com/andy/32/25168_2.png) [@Andy](https://staging-discuss.dev.twitch.com/u/Andy)\
**Post date:** [June 25, 2023, 1:47am UTC](https://staging-discuss.dev.twitch.com/t/jwt-verify-in-php/46231/10 "2023-06-25T01:47:52Z")

</div>

Got it. I will post a working code for the new version. The key from twitch has to decoded.

```auto
function validate_twitch_jwt($jwt) {
    $secretKey = base64_decode("YOUR_KEY_FROM_TWITCH");
    try {
        $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256'));
        return true;
    } catch (Exception $e) {
        $output['error'] = 'J An Error Occured';
        $output['error'] = $e->getMessage();
        echo json_encode($output);
    }
}

```
