Example #1
0
 /**
  * Fetches the JSON web key set from the `jwks_uri` parameter.
  */
 public function fetchJWKs()
 {
     if (isset($this->container['oauth']['jwks_uri'])) {
         $web = \Web::instance();
         $response = new HTTPResponse($web->request($this->container['oauth']['jwks_uri'], array('headers' => array('Accept' => 'application/jwk-set+json,application/json,text/plain,application/octet-stream'))));
         if ($response->isHttpError()) {
             return;
         }
         $jwks = json_decode($response->getBody(), true);
         if ($jwks == NULL) {
             return;
         }
         $this->container['oauth']['jwks'] = $jwks;
     }
 }
 /**
  * Verifies a sector identifier URI.
  *
  * This function retrieves the JSON document specified by `$sector_identifier_uri` and checks
  * whether the URIs in that document are contained in `$expected_redirect_uris`
  *
  * @param string $sector_identifier_uri the sector identifier URI
  * @param array $expected_redirect_uris an array of URIs that the document in `$sector_identifier_uri`
  * is expected to match
  * @return bool true if the sector identifier is verified
  */
 protected function verifySectorIdentifier($sector_identifier_uri, $expected_redirect_uris)
 {
     $web = \Web::instance();
     $this->logger->log(LogLevel::INFO, 'OAuth dynamic client registration request: verifying OpenID Connect sector_identifier_uri ' . $sector_identifier_uri);
     if (parse_url($sector_identifier_uri, PHP_URL_SCHEME) != 'https') {
         $this->logger->log(LogLevel::ERROR, 'Not https:' . $sector_identifier_uri);
         return false;
     }
     $response = new HTTPResponse($web->request($sector_identifier_uri, array('headers' => array('Accept' => 'application/json'))));
     if ($response->isHttpError()) {
         $this->logger->log(LogLevel::ERROR, 'Cannot retrieve sector_identifier_uri:' . $sector_identifier_uri);
         return false;
     }
     $test_redirect_uris = json_decode($response->getBody(), true);
     if ($test_redirect_uris == NULL) {
         $this->logger->log(LogLevel::ERROR, 'Invalid sector_identifier_uri: not valid JSON');
         return false;
     } elseif (count(array_diff($expected_redirect_uris, $test_redirect_uris)) > 0 || count(array_diff($test_redirect_uris, $expected_redirect_uris)) > 0) {
         $this->logger->log(LogLevel::ERROR, 'Redirect URIs in sector_identifier_uri do not match redirect_uris');
         return false;
     } else {
         $this->logger->log(LogLevel::DEBUG, 'sector_identifier_uri verified');
         return true;
     }
 }
Example #3
0
 /**
  * Parses and returns the request's `Authorization` header.
  *
  * This method extracts the request's `Authorization` header and returns an
  * array with the following elements:
  *
  * - `#scheme` - the authentication scheme, e.g. Basic, Bearer
  * - `#credentials` - the credentials following the scheme
  *
  * If `$parse_credentials` is true, the method will also attempt to parse
  * the credential information.  For the `Basic` scheme, the user name and
  * password will be returned in the array as `#username` and `#password`
  * respectively.  For other schemes with delimited name-value parameters,
  * those name-value pairs will be returned.
  *
  * @param bool $parse_credentials whether to parse the credential information
  * @return array the parsed `Authorization` header, or `null` if none
  * exists
  */
 public function getAuthorizationHeader($parse_credentials = false)
 {
     if (!$this->hasHeader('Authorization')) {
         return null;
     }
     $results = array();
     $header = $this->getHeader('Authorization');
     list($scheme, $credentials) = preg_split('/\\s+/', $header, 2);
     $results['#scheme'] = HTTPResponse::httpCase($scheme);
     $results['#credentials'] = $credentials;
     if ($parse_credentials) {
         if ($results['#scheme'] == 'Basic') {
             list($username, $password) = explode(':', base64_decode($credentials));
             $results['#username'] = $username;
             $results['#password'] = $password;
         } else {
             $matches = array();
             preg_match_all('/([-a-zA-Z]+)=\\"([^\\"]+)\\"/', $credentials, $matches, PREG_SET_ORDER);
             foreach ($matches as $match) {
                 $results[$match[1]] = $match[2];
             }
         }
     }
     return $results;
 }
Example #4
0
 /**
  * @see SimpleID\API\OAuthHooks::oAuthResolveAuthRequestHook()
  */
 public function oAuthResolveAuthRequestHook($request, $response)
 {
     $store = StoreManager::instance();
     $web = Web::instance();
     // 1. Check if request_uri parameter is present.  If so, fetch the JWT
     // from this URL and place it in the request parameter
     if (isset($request['request_uri'])) {
         $this->logger->log(LogLevel::INFO, 'OpenID request object: getting object from ' . $request['request_uri']);
         $parts = parse_url($request['request_uri']);
         $http_response = new HTTPResponse($web->request($request['request_uri'], array('headers' => array('Accept' => 'application/jwt,text/plain,application/octet-stream'))));
         if ($http_response->isHTTPError()) {
             $this->logger->log(LogLevel::ERROR, 'Cannot retrieve request file from request_uri:' . $request['request_uri']);
             $response->setError('invalid_request_uri', 'cannot retrieve request file from request_uri');
             return;
         }
         $request['request'] = $http_response->getBody();
         unset($request['request_uri']);
     }
     // 2. Check if the request parameter is present.  If so, we are dealing with
     // an additional OpenID Connect request object.  We need to parse this object
     if (isset($request['request'])) {
         $this->logger->log(LogLevel::INFO, 'OpenID request object token: ' . $request['request']);
         $client = $store->loadClient($request['client_id'], 'SimpleID\\Protocols\\OAuth\\OAuthClient');
         if (!isset($client['connect']['request_object_signing_alg'])) {
             $this->logger->log(LogLevel::ERROR, 'Invalid OpenID request object: signature algorithm not registered');
             $response->setError('invalid_openid_request_object', 'signature algorithm not registered');
             return;
         }
         $jwt_alg = isset($client['connect']['request_object_signing_alg']) ? $client['connect']['request_object_signing_alg'] : null;
         $jwe_alg = isset($client['connect']['request_object_encryption_alg']) ? $client['connect']['request_object_encryption_alg'] : null;
         $builder = new KeySetBuilder($client);
         $set = $builder->addClientSecret()->addClientPublicKeys()->addServerPrivateKeys()->toKeySet();
         try {
             AlgorithmFactory::addNoneAlg();
             $helper = new Helper($request['request']);
             $jwt = $helper->getJWTObject($set, $jwe_alg, $jwt_alg);
             $request->loadData($jwt->getClaims());
         } catch (\UnexpectedValueException $e) {
             $this->logger->log(LogLevel::ERROR, 'Invalid OpenID request object: ' . $e->getMessage());
             $response->setError('invalid_openid_request_object', $e->getMessage());
             return;
         }
     }
     AlgorithmFactory::removeNoneAlg();
     // 3. nonce
     if ($request->paramContains('scope', 'openid') && $request->paramContains('response_type', 'token') && !isset($request['nonce'])) {
         $this->logger->log(LogLevel::ERROR, 'Protocol Error: nonce not set when using implicit flow');
         $response->setError('invalid_request', 'nonce not set when using implicit flow')->renderRedirect();
         return;
     }
 }