Skip to content

Commit

Permalink
Merge pull request 1EdTech#51 from packbackbooks/jwt-alg
Browse files Browse the repository at this point in the history
MGMT-61 Fix key alg
  • Loading branch information
dbhynds authored Apr 14, 2022
2 parents 135b4e1 + 00e387f commit 84f8896
Showing 1 changed file with 40 additions and 0 deletions.
40 changes: 40 additions & 0 deletions src/LtiMessageLaunch.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class LtiMessageLaunch
public const ERR_VALIDATOR_CONFLICT = 'Validator conflict.';
public const ERR_UNRECOGNIZED_MESSAGE_TYPE = 'Unrecognized message type.';
public const ERR_INVALID_MESSAGE = 'Message validation failed.';
public const ERR_INVALID_ALG = 'Invalid alg was specified in the JWT header.';
public const ERR_MISMATCHED_ALG_KEY = 'The alg specified in the JWT header is incompatible with the JWK key type.';

private $db;
private $cache;
Expand All @@ -48,6 +50,16 @@ class LtiMessageLaunch
private $registration;
private $launch_id;

// See https://www.imsglobal.org/spec/security/v1p1#approved-jwt-signing-algorithms.
private static $ltiSupportedAlgs = [
'RS256' => 'RSA',
'RS384' => 'RSA',
'RS512' => 'RSA',
'ES256' => 'EC',
'ES384' => 'EC',
'ES512' => 'EC',
];

/**
* Constructor.
*
Expand Down Expand Up @@ -285,6 +297,8 @@ private function getPublicKey()
// Find key used to sign the JWT (matches the KID in the header)
foreach ($publicKeySet['keys'] as $key) {
if ($key['kid'] == $this->jwt['header']['kid']) {
$key['alg'] = $this->getKeyAlgorithm($key);

try {
$keySet = JWK::parseKeySet([
'keys' => [$key],
Expand All @@ -303,6 +317,32 @@ private function getPublicKey()
throw new LtiException(static::ERR_NO_PUBLIC_KEY);
}

/**
* If alg is omitted from the JWK, infer it from the JWT header alg.
* See https://datatracker.ietf.org/doc/html/rfc7517#section-4.4.
*/
private function getKeyAlgorithm(array $key): string
{
if (isset($key['alg'])) {
return $key['alg'];
}

// The header alg must match the key type (family) specified in the JWK's kty.
if ($this->jwtAlgMatchesJwkKty($key)) {
return $this->jwt['header']['alg'];
}

throw new LtiException(static::ERR_MISMATCHED_ALG_KEY);
}

private function jwtAlgMatchesJwkKty($key): bool
{
$jwtAlg = $this->jwt['header']['alg'];

return isset(static::$ltiSupportedAlgs[$jwtAlg]) &&
static::$ltiSupportedAlgs[$jwtAlg] === $key['kty'];
}

private function cacheLaunchData()
{
$this->cache->cacheLaunchData($this->launch_id, $this->jwt['body']);
Expand Down

0 comments on commit 84f8896

Please sign in to comment.