# JWT token creation

**URL:** <https://devforum.zoom.us/t/jwt-token-creation/15783>\
**Category:** API and Webhooks\
**Created:** [May 2, 2020, 1:36am UTC](https://devforum.zoom.us/t/jwt-token-creation/15783 "2020-05-02T01:36:12Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![laeggan](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/laeggan/32/7383_2.png) [@laeggan](https://devforum.zoom.us/u/laeggan)\
**Post date:** [May 2, 2020, 1:36am UTC](https://devforum.zoom.us/t/jwt-token-creation/15783/1 "2020-05-02T01:36:12Z")

</div>

Why doesn’t this work. In PHP 7.3  
I get error: The Token’s Signature resulted invalid when verified using the Algorithm: HmacSHA256

\<?php define("API\_KEY", "my API Key"); define ("API\_SECRET", "my AOI Secret"); $header = '{"alg":"HS256","typ":"JWT"}'; $payload = '{"iss":"' . API\_KEY . '","exp":' . (time() + 50) . '}'; $signature = hash\_hmac("sha256", base64url\_encode($header) . "." . base64url\_encode($payload), API\_SECRET, true); $token = base64url\_encode($header) . "." . base64url\_encode($payload) . "." . $signature; $curl = curl\_init(); curl\_setopt\_array($curl, array( CURLOPT\_URL =\> "https://api.zoom.us/v2/users", CURLOPT\_RETURNTRANSFER =\> true, CURLOPT\_ENCODING =\> "", CURLOPT\_MAXREDIRS =\> 10, CURLOPT\_TIMEOUT =\> 30, CURLOPT\_HTTP\_VERSION =\> CURL\_HTTP\_VERSION\_1\_1, CURLOPT\_CUSTOMREQUEST =\> "GET", CURLOPT\_HTTPHEADER =\> array( "authorization: Bearer " . $token, "content-type: application/json" ), )); $response = curl\_exec($curl); $err = curl\_error($curl); curl\_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } function base64url\_encode($data) { // Encode $data to Base64 string $b64 = base64\_encode($data); // Valid result? Otherwise, return FALSE, as the base64\_encode() function does if ($b64 === false) { return false; } // Convert Base64 to Base64URL by replacing "+" with "-" and "/" with "\_" $url = strtr($b64, '+/', '-\_'); // Remove padding character from the end of line and return the Base64URL result return rtrim($url, '='); } function base64url\_decode($data, $strict = false) { // Convert Base64URL to Base64 by replacing "-" with "+" and "\_" with "/" $b64 = strtr($data, '-\_', '+/'); // Decode Base64 string and return the original data return base64\_decode($b64, $strict); } ?\>

---

<div class="post-metadata">

**Author:** ![samly](https://avatars.discourse-cdn.com/v4/letter/s/a87d85/32.png) [@samly](https://devforum.zoom.us/u/samly)\
**Post date:** [May 5, 2020, 4:44pm UTC](https://devforum.zoom.us/t/jwt-token-creation/15783/2 "2020-05-05T16:44:13Z")

</div>

In your call to hash\_hmac, the last argument should be `False`, not `True`. Your code generates a proper JWT with that change:

> [@laeggan](#):
>
> Why doesn’t this work. In PHP 7.3  
> I get error: The Token’s Signature resulted invalid when verified using the Algorithm: HmacSHA256
> 
> ```php
> <?php
> define("API_KEY", "my API Key");
> define ("API_SECRET", "my AOI Secret");
> $header = '{"alg":"HS256","typ":"JWT"}';
> $payload = '{"iss":"' . API_KEY . '","exp":' . (time() + 50) . '}';
> $signature = hash_hmac("sha256", base64url_encode($header) . "." . base64url_encode($payload), API_SECRET, false);
> $token = base64url_encode($header) . "." . base64url_encode($payload) . "." . $signature;
>       
> $curl = curl_init();
> curl_setopt_array($curl, array(
> CURLOPT_URL => "https://api.zoom.us/v2/users",
> CURLOPT_RETURNTRANSFER => true,
> CURLOPT_ENCODING => "",
> CURLOPT_MAXREDIRS => 10,
> CURLOPT_TIMEOUT => 30,
> CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
> CURLOPT_CUSTOMREQUEST => "GET",
> CURLOPT_HTTPHEADER => array(
> "authorization: Bearer " . $token,
> "content-type: application/json"
> ),
> ));
> 
> $response = curl_exec($curl);
> $err = curl_error($curl);
> 
> curl_close($curl);
> 
> if ($err) {
> echo "cURL Error #:" . $err;
> } else {
> echo $response;
> }
> function base64url_encode($data)
> {
> // Encode $data to Base64 string
> $b64 = base64_encode($data);
> 
> // Valid result? Otherwise, return FALSE, as the base64_encode() function does
> if ($b64 === false) {
> return false;
> }
> 
> // Convert Base64 to Base64URL by replacing "+" with "-" and "/" with "_"
> $url = strtr($b64, '+/', '-_');
> 
> // Remove padding character from the end of line and return the Base64URL result
> return rtrim($url, '=');
> }
> function base64url_decode($data, $strict = false)
> {
> // Convert Base64URL to Base64 by replacing "-" with "+" and "_" with "/"
> $b64 = strtr($data, '-_', '+/');
> 
> // Decode Base64 string and return the original data
> return base64_decode($b64, $strict);
> }
> ?>
> 
> ```

---

<div class="post-metadata">

**Author:** ![laeggan](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/laeggan/32/7383_2.png) [@laeggan](https://devforum.zoom.us/u/laeggan)\
**Post date:** [May 6, 2020, 5:23pm UTC](https://devforum.zoom.us/t/jwt-token-creation/15783/3 "2020-05-06T17:23:41Z")

</div>

It did not work for me with false. I got the error I reported at the beginning of my post.  
What works for me is to have true in the call to hash\_hmac to get the signature, then base64url encode that when composing the token. I figured that out from reading the code in one of the [jwt.io](http://jwt.io) packages.  
Lloyd

---

<div class="post-metadata">

**Author:** ![tommy](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/tommy/32/72769_2.png) [@tommy](https://devforum.zoom.us/u/tommy)\
**Post date:** [May 12, 2020, 5:53am UTC](https://devforum.zoom.us/t/jwt-token-creation/15783/4 "2020-05-12T05:53:38Z")

</div>

Hey @laeggan,

Can you please private message me your JWT Key and I will take a look?

Thanks,  
Tommy

---

<div class="post-metadata">

**Author:** ![laeggan](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/laeggan/32/7383_2.png) [@laeggan](https://devforum.zoom.us/u/laeggan)\
**Post date:** [May 12, 2020, 9:08pm UTC](https://devforum.zoom.us/t/jwt-token-creation/15783/5 "2020-05-12T21:08:12Z")

</div>

Please don’t bother.  
As I said, it now works fine for me.  
Thanks.

---

<div class="post-metadata">

**Author:** ![tommy](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/tommy/32/72769_2.png) [@tommy](https://devforum.zoom.us/u/tommy)\
**Post date:** [May 15, 2020, 10:24pm UTC](https://devforum.zoom.us/t/jwt-token-creation/15783/6 "2020-05-15T22:24:23Z")

</div>

Happy to hear it’s working! 🙂

-Tommy

---

<div class="post-metadata">

**Author:** ![skodali](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/skodali/32/64744_2.png) [@skodali](https://devforum.zoom.us/u/skodali)\
**Post date:** [June 2, 2020, 2:07am UTC](https://devforum.zoom.us/t/jwt-token-creation/15783/7 "2020-06-02T02:07:20Z")

</div>

Hello Llyod,  
I am running into the same issue that you initially experienced. Do you mind sharing the final version of the working code?

---

<div class="post-metadata">

**Author:** ![tommy](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/tommy/32/72769_2.png) [@tommy](https://devforum.zoom.us/u/tommy)\
**Post date:** [March 16, 2021, 9:59pm UTC](https://devforum.zoom.us/t/jwt-token-creation/15783/8 "2021-03-16T21:59:54Z")

</div>

If you are still having this issue, please create a new topic: #api-and-webhooks

Thanks,  
Tommy

---

<div class="post-metadata">

**Author:** ![tommy](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/tommy/32/72769_2.png) [@tommy](https://devforum.zoom.us/u/tommy)\
**Post date:** [March 16, 2021, 10:00pm UTC](https://devforum.zoom.us/t/jwt-token-creation/15783/9 "2021-03-16T22:00:00Z")

</div>


