const jwt = require('../index');
const crypto = require("crypto");
const {expect} = require('chai');
const JsonWebTokenError = require("../lib/JsonWebTokenError");

describe('when verifying a malicious token', function () {
  // attacker has access to the public rsa key, but crafts the token as HS256
  // with kid set to the id of the rsa key, instead of the id of the hmac secret.
  // const maliciousToken = jwt.sign(
  //   {foo: 'bar'},
  //   pubRsaKey,
  //   {algorithm: 'HS256', keyid: 'rsaKeyId'}
  // );
  // consumer accepts self signed tokens (HS256) and third party tokens (RS256)
  const options = {algorithms: ['RS256', 'HS256']};

  const {
    publicKey: pubRsaKey
  } = crypto.generateKeyPairSync('rsa', {modulusLength: 2048});

  it('should not allow HMAC verification with an RSA key in KeyObject format', function () {
    const maliciousToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InJzYUtleUlkIn0.eyJmb28iOiJiYXIiLCJpYXQiOjE2NTk1MTA2MDh9.cOcHI1TXPbxTMlyVTfjArSWskrmezbrG8iR7uJHwtrQ';

    expect(() => jwt.verify(maliciousToken, pubRsaKey, options)).to.throw(JsonWebTokenError, 'must be a symmetric key');
  })

  it('should not allow HMAC verification with an RSA key in PEM format', function () {
    const maliciousToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InJzYUtleUlkIn0.eyJmb28iOiJiYXIiLCJpYXQiOjE2NTk1MTA2MDh9.cOcHI1TXPbxTMlyVTfjArSWskrmezbrG8iR7uJHwtrQ';

    expect(() => jwt.verify(maliciousToken, pubRsaKey.export({type: 'spki', format: 'pem'}), options)).to.throw(JsonWebTokenError, 'must be a symmetric key');
  })

  it('should not allow arbitrary execution from malicious Buffers containing objects with overridden toString functions', function () {
    const token = jwt.sign({"foo": "bar"}, 'secret')
    const maliciousBuffer = {toString: () => {throw new Error("Arbitrary Code Execution")}}

    expect(() => jwt.verify(token, maliciousBuffer)).to.throw(Error, 'not valid key material');
  })
})
