Esempio n. 1
0
 /**
  * Builds the JOSE response.  This will return one of the following:
  *
  * - A JSON encoded string, if {@link $signed_response_alg} and
  *   {@link $encrypted_response_alg} are both null
  * - A signed JWT (JWS), if {@link $signed_response_alg} is set
  * - A JWE containing a nested JWT, if both {@link $signed_response_alg}
  *   and {@link $encrypted_response_alg} are set
  *
  * @param SimpleJWT\Keys\KeySet $set the key set used to sign and/or
  * encrypt the token.  If set to null, the default set of keys
  * configured for the client and the server are loaded
  * @return string the response body
  */
 function buildJOSE($set = null)
 {
     $rand = new Random();
     $typ = $this->getType();
     if ($typ == 'json') {
         return json_encode($this->container);
     }
     if ($set == null) {
         $builder = new KeySetBuilder($client);
         $set = $builder->addClientSecret()->addClientPublicKeys()->addServerPrivateKeys()->toKeySet();
     }
     $headers = array_merge($this->headers, array('alg' => $this->signed_response_alg));
     $claims = array_merge($this->container, array('iss' => $this->issuer, 'aud' => $this->client->getStoreID(), 'jti' => $rand->id()));
     $jwt = new JWT($headers, $claims);
     try {
         $token = $jwt->encode($set);
     } catch (CryptException $e) {
         return null;
     }
     if ($typ == 'jwt') {
         return $token;
     }
     $headers = array('alg' => $this->encrypted_response_alg, 'enc' => $this->encrypted_response_enc, 'cty' => 'JWT');
     $jwe = new JWE($headers, $token);
     try {
         return $jwe->encrypt($set);
     } catch (CryptException $e) {
         return null;
     }
 }
Esempio n. 2
0
 /**
  * Decrypts and verifies a nested JWT.
  *
  * If the supplied token is a JWT, this function calls {@link getObject()}
  * to decode the JWT.
  *
  * If the supplied token is a JWE, the JWE is firstly decrypted, then the underlying
  * plaintext is treated as a JWT, and further decoded.
  *
  * @param SimpleJWT\Keys\KeySet $keys the key set containing the decryption
  * and verification keys
  * @param string $expected_jwe_alg the expected value of the `alg` parameter for the
  * JWE, which should be agreed between the parties out-of-band
  * @param string $expected_jwt_alg the expected value of the `alg` parameter for the
  * underlying JWT, which should be agreed between the parties out-of-band
  * @param string $jwe_kid the ID of the key to use for decryption. If null, this
  * is automatically retrieved
  * @param string $jwt_kid the ID of the key to use for verification. If null, this
  * is automatically retrieved
  * @return JWT the decoded JWT
  * @throws InvalidTokenException if the token is invalid for any reason
  */
 function getJWTObject($keys, $expected_jwe_alg, $expected_jwt_alg, $jwe_kid = null, $jwt_kid = null)
 {
     switch ($this->type) {
         case 'JWT':
             return $this->getObject($keys, $expected_jwt_alg, $jwt_kid);
         case 'JWE':
             $jwe = JWE::decrypt($this->data, $keys, $expected_jwe_alg, $jwe_kid, $this->format);
             if ($jwe->getHeader('cty') != 'JWT') {
                 throw new InvalidTokenException('Not a nested JWT', InvalidTokenException::TOKEN_PARSE_ERROR);
             }
             return JWT::decode($jwe->getPlaintext(), $keys, $expected_jwt_alg, $jwt_kid);
     }
 }
Esempio n. 3
0
 /**
  * @see SimpleID\API\OAuthHooks::oAuthProcessAuthRequestHook()
  */
 function oAuthProcessAuthRequestHook($request, $response)
 {
     $store = StoreManager::instance();
     $auth = AuthManager::instance();
     $client = $store->loadClient($request['client_id'], 'SimpleID\\Protocols\\OAuth\\OAuthClient');
     // Check 1: Check whether the prompt parameter is present in the request
     $request->setImmediate($request->paramContains('prompt', 'none'));
     if ($request->paramContains('prompt', 'login')) {
         $this->f3->set('message', $this->t('This app\'s policy requires you to log in again to confirm your identity.'));
         $request->paramRemove('prompt', 'login');
         return self::CHECKID_REENTER_CREDENTIALS;
     }
     if ($request->paramContains('prompt', 'consent')) {
         $request->paramRemove('prompt', 'consent');
         return self::CHECKID_APPROVAL_REQUIRED;
     }
     // Check 2: If id_token_hint is provided, check that it refers to the current logged-in user
     if (isset($request['id_token_hint'])) {
         try {
             $jwt = JWT::decode($request['id_token_hint']);
             $user_match = $jwt->getClaim('sub') == $this->getSubject($auth->getUser(), $client);
         } catch (CryptException $e) {
             $user_match = false;
         }
         if (!$user_match) {
             $auth->logout();
             return self::CHECKID_LOGIN_REQUIRED;
         }
     }
     // Check 3: Check whether the max_age or acr parameters are present in the client defaults
     // or the request parameters
     if (isset($request['max_age'])) {
         $max_age = $request['max_age'];
     } elseif (isset($client['connect']) && isset($client['connect']['default_max_age'])) {
         $max_age = $client['connect']['default_max_age'];
     } else {
         $max_age = -1;
     }
     // If the relying party provides a max_auth_age
     if ($max_age > -1 && $auth->isLoggedIn()) {
         $auth_level = $auth->getAuthLevel();
         if ($auth_level == null) {
             $auth_level = AuthManager::AUTH_LEVEL_SESSION;
         }
         $auth_time = $auth->getAuthTime();
         if ($auth_time == null) {
             $auth_time = 0;
         }
         // If the last time we logged on actively (i.e. using a password) is greater than
         // max_age, we then require the user to log in again
         if ($auth_level < AuthManager::AUTH_LEVEL_CREDENTIALS || time() - $auth->getAuthTime() > $max_age) {
             $this->f3->set('message', $this->t('This app\'s policy requires you to log in again to confirm your identity.'));
             return self::CHECKID_REENTER_CREDENTIALS;
         }
     }
     if (isset($request['acr'])) {
         $acr = $request['acr'];
     } elseif (isset($client['connect']) && isset($client['connect']['default_acr'])) {
         $acr = $client['connect']['default_acr'];
     } else {
         $acr = -1;
     }
     if ($acr > -1) {
         return self::CHECKID_INSUFFICIENT_TRUST;
     }
     return null;
 }