/** * Signs and serialises the JWT. * * @param SimpleJWT\Keys\KeySet $keys the key set containing the key to sign the * JWT * @param string $kid the ID of the key to use to sign. If null, this * is automatically retrieved * @param bool|array $auto_complete an array of headers or claims that * should be automatically completed, or false if no auto-completion is * to be performed * @param string $alg if not null, override the `alg` header * @param string $format the JWT serialisation format * @return string the signed and serialised JWT * @throws SimpleJWT\Keys\KeyException if there is an error obtaining the key * to sign the JWT * @throws SimpleJWT\Crypt\CryptException if there is a cryptographic error */ public function encode($keys, $kid = null, $auto_complete = array('iat', 'kid'), $alg = null, $format = self::COMPACT_FORMAT) { if ($auto_complete === false) { $auto_complete = array(); } if ($alg != null) { $this->headers['alg'] = $alg; } if (in_array('iat', $auto_complete) && !isset($this->claims['iat'])) { $this->claims['iat'] = time(); } try { $signer = AlgorithmFactory::create($this->headers['alg']); } catch (\UnexpectedValueException $e) { throw new CryptException($e->getMessage(), 0, $e); } $key = $signer->getSigningKey($keys, $kid); if ($key != null && in_array('kid', $auto_complete)) { $this->headers['kid'] = $key->getKeyId(); } $protected = Util::base64url_encode(json_encode($this->headers)); $payload = Util::base64url_encode(json_encode($this->claims)); $signing_input = $protected . '.' . $payload; $signature = $signer->sign($signing_input, $keys, $kid); switch ($format) { case self::COMPACT_FORMAT: return $signing_input . '.' . $signature; case self::JSON_FORMAT: return json_encode(array('protected' => $protected, 'payload' => $payload, 'signature' => $signature)); default: throw new \InvalidArgumentException('Incorrect format'); } }
/** * Displays the OpenID Connect configuration file for this installation. * */ public function openid_configuration() { $mgr = ModuleManager::instance(); header('Content-Type: application/json'); header('Content-Disposition: inline; filename=openid-configuration'); $scopes = $mgr->invokeAll('scopes'); $jwt_signing_algs = AlgorithmFactory::getSupportedAlgs(Algorithm::SIGNATURE_ALGORITHM); $jwt_encryption_algs = AlgorithmFactory::getSupportedAlgs(Algorithm::KEY_ALGORITHM); $jwt_encryption_enc_algs = AlgorithmFactory::getSupportedAlgs(Algorithm::ENCRYPTION_ALGORITHM); $claims_supported = array('sub', 'iss', 'auth_time', 'acr'); foreach ($scopes['oauth'] as $scope => $settings) { if (isset($settings['claims'])) { $claims_supporteds = array_merge($claims_supported, $settings['claims']); } } $token_endpoint_auth_methods_supported = array('client_secret_basic', 'client_secret_post'); $config = array('issuer' => $this->getCanonicalHost(), 'authorization_endpoint' => $this->getCanonicalURL('@oauth_auth', '', 'https'), 'token_endpoint' => $this->getCanonicalURL('@oauth_token', '', 'https'), 'userinfo_endpoint' => $this->getCanonicalURL('@connect_userinfo', '', 'https'), 'jwks_uri' => $this->getCanonicalURL('@connect_jwks', '', 'https'), 'scopes_supported' => array_keys($scopes['oauth']), 'response_types_supported' => array('code', 'token', 'id_token', 'id_token token', 'code token', 'code id_token', 'code id_token token'), 'response_modes_supported' => Response::getResponseModesSupported(), 'grant_types_supported' => array('authorization_code', 'refresh_token'), 'acr_values_supported' => array(), 'subject_types_supported' => array('public', 'pairwise'), 'userinfo_signing_alg_values_supported' => $jwt_signing_algs, 'userinfo_encryption_alg_values_supported' => $jwt_encryption_algs, 'userinfo_encryption_enc_alg_values_supported' => $jwt_encryption_enc_algs, 'id_token_signing_alg_values_supported' => $jwt_signing_algs, 'id_token_encrpytion_alg_values_supported' => $jwt_encryption_algs, 'id_token_encrpytion_enc_alg_values_supported' => $jwt_encryption_enc_algs, 'request_object_signing_alg_values_supported' => array_merge($jwt_signing_algs, array('none')), 'request_object_encryption_alg_values_supported' => $jwt_encryption_algs, 'request_object_encryption_enc_alg_values_supported' => $jwt_encryption_enc_algs, 'token_endpoint_auth_methods_supported' => $token_endpoint_auth_methods_supported, 'claim_types_supported' => array('normal'), 'claims_supported' => $claims_supported, 'claims_parameter_supported' => true, 'request_parameter_supported' => true, 'request_uri_parameter_supported' => true, 'require_request_uri_registration' => false, 'service_documentation' => 'http://simpleid.koinic.net/docs/'); $config = array_merge($config, $mgr->invokeAll('connectConfiguration')); print json_encode($config); }
function setShortHashClaim($claim, $value) { $alg = $this->signed_response_alg ? $this->signed_response_alg : 'HS256'; $signer = AlgorithmFactory::create($alg); if ($signer) { $this->container[$claim] = $signer->shortHash($value); } }
/** * Encrypts the JWE. * * @param SimpleJWT\Keys\KeySet $keys the key set containing the key to encrypt the * content encryption key * @param string $kid the ID of the key to use to encrypt. If null, this * is automatically retrieved * @param string $format the JWE serialisation format * @return string the encrypted JWE * @throws SimpleJWT\Keys\KeyException if there is an error obtaining the key * to sign the JWT * @throws SimpleJWT\Crypt\CryptException if there is a cryptographic error */ public function encrypt($keys, $kid = null, $format = self::COMPACT_FORMAT) { if (!isset($this->headers['alg'])) { throw new \InvalidArgumentException('alg parameter missing'); } if (!isset($this->headers['enc'])) { throw new \InvalidArgumentException('enc parameter missing'); } $key_enc = AlgorithmFactory::create($this->headers['alg']); $content_enc = AlgorithmFactory::create($this->headers['enc']); if ($kid != null) { $this->headers['kid'] = $kid; } if ($key_enc instanceof KeyDerivationAlgorithm) { $agreed_key = $key_enc->deriveKey($keys, $this->headers, $kid); if ($key_enc instanceof KeyEncryptionAlgorithm) { // Key agreement with wrapping $keys->add(new SymmetricKey(array('kty' => SymmetricKey::KTY, 'alg' => $this->headers['alg'], 'k' => Util::base64url_encode($agreed_key)), 'php')); } else { // Direct key agreement or direct encryption $cek = $agreed_key; } } if (!isset($cek)) { $cek = Util::random_bytes($content_enc->getCEKSize() / 8); } if ($key_enc instanceof KeyEncryptionAlgorithm) { $encrypted_key = $key_enc->encryptKey($cek, $keys, $this->headers, $kid); } else { $encrypted_key = ''; } if (isset($this->headers['zip'])) { switch ($this->headers['zip']) { case 'DEF': $plaintext = gzdeflate($this->plaintext); break; default: throw new \InvalidArgumentException('Unsupported zip header:' . $this->headers['zip']); } } else { $plaintext = $this->plaintext; } $protected = Util::base64url_encode(json_encode($this->headers)); $results = $content_enc->encryptAndSign($plaintext, $cek, $protected); $ciphertext = $results['ciphertext']; $iv = isset($results['iv']) ? $results['iv'] : ''; $tag = $results['tag']; switch ($format) { case self::COMPACT_FORMAT: return $protected . '.' . $encrypted_key . '.' . $iv . '.' . $ciphertext . '.' . $tag; case self::JSON_FORMAT: $obj = array('protected' => $protected, 'ciphertext' => $ciphertext, 'tag' => $tag, 'encrypted_key' => $encrypted_key); if ($iv) { $obj['iv'] = $iv; } return json_encode($obj); default: throw new \InvalidArgumentException('Incorrect format'); } }