JWT token generation fails, MUX API responds with error

Viewed 425

I'm trying to run the PHP example code documented here on the MUX website. I have just generated a brand new API key + secret and have stored them in a mux-credentials.php file:

define('MUX_TOKEN_ID', 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx');
define('MUX_TOKEN_SECRET', '<base64-encoded-string-here>');

I used composer to install Firebase\JWT as instructed here and then ran the exact code specified in the MUX documentation:

// load libs
require_once 'vendor/autoload.php';

// load MUX credentials
require_once 'mux-credentials.php';

use \Firebase\JWT\JWT;


$myId = "<MY-ASSET-ID-HERE>";       // Enter the id for which you would like to get counts here
$myIdType = "asset_id";   // Enter the type of ID provided in my_id; one of video_id | asset_id | playback_id | live_stream_id
$keyId = MUX_TOKEN_ID;      // Enter your signing key id here
$keySecret = MUX_TOKEN_SECRET;  // Enter your base64 encoded private key here

$payload = array(
        "sub" => $myId,
        "aud" => $myIdType,
        "exp" => time() + 600, // Expiry time in epoch - in this case now + 10 mins
        "kid" => $keyId
);

$jwt = JWT::encode($payload, base64_decode($keySecret), 'RS256');


print "$jwt\n";

This code barfs with a fatal error:

PHP Warning:  openssl_sign(): supplied key param cannot be coerced into a private key in /home/example/vendor/firebase/php-jwt/src/JWT.php on line 225
PHP Fatal error:  Uncaught DomainException: OpenSSL unable to sign data in /home/example/vendor/firebase/php-jwt/src/JWT.php:227
Stack trace:
#0 /home/example/vendor/firebase/php-jwt/src/JWT.php(195): Firebase\JWT\JWT::sign()
#1 /home/example/people-watching.php(30): Firebase\JWT\JWT::encode()
#2 {main}
  thrown in /home/example/vendor/firebase/php-jwt/src/JWT.php on line 227

If I remove the last param in the JWT::encode call like so:

$jwt = JWT::encode($payload, base64_decode($keySecret));

Then the code successfully runs, and generates a long base64-encoded string. That JWT string, however, results in an error when I attempt to use it to contact the API:

curl 'https://stats.mux.com/counts?token=<JWT-HERE>'

The MUX api responds with:

{"error":{"type":"internal error","messages":["Could not get signing key."]}}

Can anyone help me fix this code so that I can contact the MUX API and retrieve the requested information about my asset id?

EDIT: I am grateful for the answers below pointing out that one should use a signing key rather than one's API credentials but, putting aside my confusion about why we need such a thing as a signing key, the curl request to create a signing key doesn't work either. This curl request (i've redacted my MUX_TOKEN_ID and MUX_TOKEN_SECRET):

curl -X POST \
-H "Content-Type: application/json" \
-u <MUX_TOKEN_KEY>:<MUX_TOKEN_SECRET> \
'https://api.mux.com/system/v1/signing-keys?product=data'

fails, returning this error:

{"error":{"type":"not_found","messages":["The requested resource either doesn't exist or you don't have access to it."]}}
2 Answers

Jared Smith here, one of the community engineers at Mux. Let me see if I can help clear this up a bit. The wording in that guide is a bit unclear, and I'll work internally to get that cleaned up, but I think I know where the confusion is here.

It looks to me like you're passing in your API token ID for $keyId and your API token secret for $keySecret.

Instead, you should first make a call to the /system/v1/signing-keys endpoint of the API (using your token ID and secret, as explained in step one of that guide) to create a signing key.

You then pass the signing key ID as $keyId, and the base 64 encoded signing key itself as $keySecret.

Another test you can use to make sure you've got the right signing key is to base 64 decode it, and make sure it begins with -----BEGIN RSA PRIVATE KEY----- and ends with -----END RSA PRIVATE KEY-----.

Hopefully that clears things up for you. If not, feel free to reach out for more help!

It looks like you're trying to use the API key and secret to sign the JWT. Mux instead is looking for separate a signing key

This signing key can be generated with the API key and secret you're currently using in a request to https://api.mux.com/system/v1/signing-keys?product=data

You can see an example of this request here: https://docs.mux.com/guides/data/see-how-many-people-are-watching#1-create-a-signing-key

The kid value of the JWT claims would then instead be set to the Key ID returned when signing key was created.

I'm a community engineer working with Mux – if you have any ideas on how you feel this process could be more clear, don't hesitate to provide any feedback!

Related