/**
  * Handles digest authentication.
  *
  * @param EventInterface $event An EventInterface instance
  */
 public function handle(EventInterface $event)
 {
     $request = $event->get('request');
     if (!($header = $request->server->get('PHP_AUTH_DIGEST'))) {
         return;
     }
     $digestAuth = new DigestData($header);
     if (null !== ($token = $this->securityContext->getToken())) {
         if ($token->isImmutable()) {
             return;
         }
         if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && (string) $token === $digestAuth->getUsername()) {
             return;
         }
     }
     if (null !== $this->logger) {
         $this->logger->debug(sprintf('Digest Authorization header received from user agent: %s', $header));
     }
     try {
         $digestAuth->validateAndDecode($this->authenticationEntryPoint->getKey(), $this->authenticationEntryPoint->getRealmName());
     } catch (BadCredentialsException $e) {
         $this->fail($event, $request, $e);
         return;
     }
     try {
         $user = $this->provider->loadUserByUsername($digestAuth->getUsername());
         if (null === $user) {
             throw new AuthenticationServiceException('AuthenticationDao returned null, which is an interface contract violation');
         }
         $serverDigestMd5 = $digestAuth->calculateServerDigest($user->getPassword(), $request->getMethod());
     } catch (UsernameNotFoundException $notFound) {
         $this->fail($event, $request, new BadCredentialsException(sprintf('Username %s not found.', $digestAuth->getUsername())));
         return;
     }
     if ($serverDigestMd5 !== $digestAuth->getResponse()) {
         if (null !== $this->logger) {
             $this->logger->debug(sprintf("Expected response: '%s' but received: '%s'; is AuthenticationDao returning clear text passwords?", $serverDigestMd5, $digestAuth->getResponse()));
         }
         $this->fail($event, $request, new BadCredentialsException('Incorrect response'));
         return;
     }
     if ($digestAuth->isNonceExpired()) {
         $this->fail($event, $request, new NonceExpiredException('Nonce has expired/timed out.'));
         return;
     }
     if (null !== $this->logger) {
         $this->logger->debug(sprintf('Authentication success for user "%s" with response "%s"', $digestAuth->getUsername(), $digestAuth->getResponse()));
     }
     $this->securityContext->setToken(new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey));
 }
예제 #2
0
 /**
  * Handles digest authentication.
  *
  * @param GetResponseEvent $event A GetResponseEvent instance
  *
  * @throws AuthenticationServiceException
  */
 public function handle(GetResponseEvent $event)
 {
     $request = $event->getRequest();
     if (!($header = $request->server->get('PHP_AUTH_DIGEST'))) {
         return;
     }
     $digestAuth = new DigestData($header);
     if (null !== ($token = $this->tokenStorage->getToken())) {
         if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && $token->getUsername() === $digestAuth->getUsername()) {
             return;
         }
     }
     if (null !== $this->logger) {
         $this->logger->debug('Digest Authorization header received from user agent.', array('header' => $header));
     }
     try {
         $digestAuth->validateAndDecode($this->authenticationEntryPoint->getKey(), $this->authenticationEntryPoint->getRealmName());
     } catch (BadCredentialsException $e) {
         $this->fail($event, $request, $e);
         return;
     }
     try {
         $user = $this->provider->loadUserByUsername($digestAuth->getUsername());
         if (null === $user) {
             throw new AuthenticationServiceException('Digest User provider returned null, which is an interface contract violation');
         }
         $serverDigestMd5 = $digestAuth->calculateServerDigest($user->getPassword(), $request->getMethod());
     } catch (UsernameNotFoundException $e) {
         $this->fail($event, $request, new BadCredentialsException(sprintf('Username %s not found.', $digestAuth->getUsername())));
         return;
     }
     if ($serverDigestMd5 !== $digestAuth->getResponse()) {
         if (null !== $this->logger) {
             $this->logger->debug('Unexpected response from the DigestAuth received; is the header returning a clear text passwords?', array('expected' => $serverDigestMd5, 'received' => $digestAuth->getResponse()));
         }
         $this->fail($event, $request, new BadCredentialsException('Incorrect response'));
         return;
     }
     if ($digestAuth->isNonceExpired()) {
         $this->fail($event, $request, new NonceExpiredException('Nonce has expired/timed out.'));
         return;
     }
     if (null !== $this->logger) {
         $this->logger->info('Digest authentication successful.', array('username' => $digestAuth->getUsername(), 'received' => $digestAuth->getResponse()));
     }
     $this->tokenStorage->setToken(new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey));
 }
예제 #3
0
 private function calculateServerDigest($username, $realm, $password, $key, $nc, $cnonce, $qop, $method, $uri)
 {
     $time = microtime(true);
     $nonce = base64_encode($time . ':' . md5($time . ':' . $key));
     $response = md5(md5($username . ':' . $realm . ':' . $password) . ':' . $nonce . ':' . $nc . ':' . $cnonce . ':' . $qop . ':' . md5($method . ':' . $uri));
     $digest = sprintf('username="******", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=%s, qop="%s", response="%s"', $username, $realm, $nonce, $uri, $cnonce, $nc, $qop, $response);
     $digestAuth = new DigestData($digest);
     $this->assertEquals($digestAuth->getResponse(), $digestAuth->calculateServerDigest($password, $method));
 }