Reference Source Test

test/unit/utils/jwt.spec.js

const { expect } = require('chai');
const path = require('path');
const JWT = require('../../../src/utils/jwt');

const TEST_ID = '01XNj9qIpoW3eU1sED8EqrFRy01J3VTZ01x';
const TEST_SECRET =
  ' LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBNGdoaERZN25QTzFhMmxibHN0T3JTcmt3VUdkdzVaT0tjR0h5U2NkWXpoc1FudHNnCkw4VWxHcURScVhuZFZ2Ky9rMEI2MnZxbzJGT1gvYkdVK2srT2lRang4UCswNVJKOWEyL1lpSzJjQm56MG15WEEKOS9CajRVNis1d3dCUk15Z2xCd2VaeWt1ZVNsZ1dYYnZRRm50bE1LcXptYU5XcnJvSDNpVEJZUU9xeFF5dHdkZApaSXlVeTYwNDJUMXJaQm5WOVN3RzA0UEhjaVJ3TjJ3Ly83YVhMY2FGRnJTOUVxZ29SNGszcjllblN1YWM3STRvCmV5NVJwMmFaVXlzK3U1VnMwUzluMzIzWVViMWZtRU1kZzEyWU1yMHIyL2Q5ZjMrdVZXQVVUTkQ1MitSREsvZ00KOEt6dW5FZ2w5eWFacit6VlFpa0RhOFoyOE9yOUxrN0xNNk5TNlFJREFRQUJBb0lCQURPbXRvYmlvUFRMU0hlYwpZK0Q1ZmFzVnBuUzVMcE5IbzlzS2h0TlZPblhldVcyVHBVZEZSYlZRQ3BrdnYrU2hqS1dabG5senppR2crSnFBCmVncTVJMWt0TWh4Z1VuWUdRNkxKYkRIUGVsZ0JOZVErUEZwc0ZHYm9GN2UwaHBXeUxQK3JiVWNsb2ZrTiszWjIKTnpYOVZzMG5ydUI3anRHczVGNU1yMHdUWVVhMmFNSHU2dnNNZFNYY00rZTVZS3FCQ3Z3dS9MZ0ZvVFE1YXh0RQo0ZzJYbU91YUQrSFBPU0o1T0Mwc3grK1RkbXBNL1lMK3RjVjZZNVBWbUFMUURMcmFJdU9UM01lcUlicElvRlZQCmcxeldSOTBqb3BKWVpLSVFoNEY4WE4xODR1bmZ6bjVJbW1JdktOWE9QSU1YMk1oekw2YU5rSXZ5YmdpWUIvVGwKMm5vdVNBRUNnWUVBNHlzZmVZL0h3Rkl4Vy9MZ2R3UHJubDR4aGkwRkFWeE1QK1k0alhYUHU1bklXS3dvUk1xbgplTEd6UnhESnlhQmN5NXgzVjFhTmYwblV1YzJqRUM2Yi9XUUo2VWJMUzJvK2J1NmdJR1NsbmxLWS9uSlJGTnpwClE0d0F1c1J3M2dTVi9FNW12QVJiYk1vQ3Rha3FxdXhhWlMzODQ1MEFaQkxqcm1kZDU1VlFPUVVDZ1lFQS9yaGIKRm9oVmdxZzY0QjFpU0FCc3dYdTdLNzZHQUN4ZEg0MmxoVjQvNktiUVRVNnFwRWxVZURwbWlVeUkxeVBxZ1MwbApLYS9XMGg5VDI5S0Z1bVlFOWdlUG02b0ZaZjIvQ0RnaWtTWHdQTk5kRWp2SmtrMXdnb3dLbDNNbUhuWGtTYUlZCmpYVG9Td2tmN2RJREhVRXQ3RnRVd1VsQXROM3N4TFcvWlVKSEI1VUNnWUFMOXkyRlBhbUwyOGgxeTJrL1c1bUIKa2Z5UjBMVSt5Um5MRTlsT3VqSGk4OHExd1B1dUErNm1VTlhjbkduRWtRblNQNytaZmhtZDVzbXByOGN6QndGNAphMWlLVFF4UVFKeGhRM2h6dkZsczZYVGRraS9ySldlMEF4L1d0cG9yVjVwKzI3SlZuUFVqMmRBaXVYSmg1bWtzCmd5dWE0WjR2cHo4TzVLcnhrOC9SOFFLQmdRQ1BJbE4xTHZrMktZaWtCWDhEek5GUVRGSWFPNzZhL0ZMNzl5R3EKOXhKY2p0aUFpSk1WTEd1OS83czhyZmc3Uk9CeTVFWjh6V1dldjZIazVjRGx4SXhISUdxUFk1UVRBdXJGR0o0OApDQ0NlWFh0d1VvNXJtdjU5TFdxS1BsZU9TRnNYRVhKUWt3QXhvaGdDRU1CVlFSb29OZzVEYXdGa1lVeTZJUk5ECk9HSW5uUUtCZ1FDeWo1UVU3YjcycktVaWlhTisxaExrVEJFQUFab01jRjY4Ukp5Mlh5VXo5bVJQK1hLMkthbHoKbVdXNFh2RHZoVlB1T25tNjJ1RkxURCsybG1mNjdwUlY3bHlSVWlycVFabzNUVmsweE8yS3JJV21uRm1EZzBSRQp6YnB6MVJsZy9ZVjhQU3E4alE3ZUFsRUs0RHRSdlVoQW5RRU52NlVyVjltRnRjR1k0ZFhSUmc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=';

/** @test {Mux.Utils.JWT} */
describe('Utils::JWT', () => {
  /** @test {Mux.Utils.JWT.sign} */
  describe('sign', () => {
    /** @test {Mux.Utils.JWT.sign} */
    it('defaults to video and includes an expiration', () => {
      const options = {
        keyId: TEST_ID,
        keySecret: TEST_SECRET,
      };

      const token = JWT.sign('some-playback-id', options);
      expect(token).to.be.a('string');
      const decoded = JWT.decode(token);
      expect(decoded.aud).to.eq('v');
      expect(decoded.exp).to.be.greaterThan(new Date().getTime() / 1000);
    });

    it('maps type video to v', () => {
      const options = {
        keyId: TEST_ID,
        keySecret: TEST_SECRET,
        type: 'video',
      };
      const token = JWT.sign('some-playback-id', options);
      expect(token).to.be.a('string');
      const decoded = JWT.decode(token);
      expect(decoded.aud).to.eq('v');
    });

    it('maps type thumbnail to t', () => {
      const options = {
        keyId: TEST_ID,
        keySecret: TEST_SECRET,
        type: 'thumbnail',
      };
      const token = JWT.sign('some-playback-id', options);
      expect(token).to.be.a('string');
      const decoded = JWT.decode(token);
      expect(decoded.aud).to.eq('t');
    });

    it('maps type gif to g', () => {
      const options = {
        keyId: TEST_ID,
        keySecret: TEST_SECRET,
        type: 'gif',
      };
      const token = JWT.sign('some-playback-id', options);
      expect(token).to.be.a('string');
      const decoded = JWT.decode(token);
      expect(decoded.aud).to.eq('g');
    });

    it('maps type storyboard to s', () => {
      const options = {
        keyId: TEST_ID,
        keySecret: TEST_SECRET,
        type: 'storyboard',
      };
      const token = JWT.sign('some-playback-id', options);
      expect(token).to.be.a('string');
      const decoded = JWT.decode(token);
      expect(decoded.aud).to.eq('s');
    });

    it('takes a file path for a secret', () => {
      const options = {
        keyId: TEST_ID,
        keyFilePath: path.join(__dirname, 'example-private-key.pem'),
        type: 'gif',
      };

      const token = JWT.sign('some-playback-id', options);
      expect(token).to.be.a('string');
      const decoded = JWT.decode(token);
      expect(decoded.aud).to.eq('g');
    });

    it('falls back to using environment variables for the key and secret', () => {
      process.env.MUX_SIGNING_KEY = TEST_ID;
      process.env.MUX_PRIVATE_KEY = TEST_SECRET;
      const options = {
        type: 'gif',
      };

      const token = JWT.sign('some-playback-id', options);
      expect(token).to.be.a('string');
      const decoded = JWT.decode(token);
      expect(decoded.aud).to.eq('g');
    });

    it('accepts a timestamp or time shorthand', () => {
      const options1 = {
        keyId: TEST_ID,
        keySecret: TEST_SECRET,
        expiration: '3h',
      };

      const options2 = {
        ...options1,
        expiration: 60 * 60 * 3,
      };

      const token1 = JWT.sign('some-playback-id', options1);
      const token2 = JWT.sign('some-playback-id', options2);
      expect(token1).to.be.a('string');
      expect(token2).to.be.a('string');

      const decoded1 = JWT.decode(token1);
      const decoded2 = JWT.decode(token2);
      expect(decoded1.exp).to.be.closeTo(decoded2.exp, 2);
    });
  });
});