public function authenticate($method, $host, $port, $resource, $contentType = null, $payload = null, $headerObjectOrString = null) { if (null === $headerObjectOrString) { throw new UnauthorizedException("Missing Authorization header"); } if (is_string($headerObjectOrString)) { $header = HeaderFactory::createFromString('Authorization', $headerObjectOrString); } elseif ($headerObjectOrString instanceof Header) { $header = $headerObjectOrString; } else { throw new UnauthorizedException("Invalid Authorization header"); } // Measure now before any other processing $now = $this->timeProvider->createTimestamp() + $this->localtimeOffsetSec; $artifacts = new Artifacts($method, $host, $port, $resource, $header->attribute('ts'), $header->attribute('nonce'), $header->attribute('ext'), $payload, $contentType, $header->attribute('hash'), $header->attribute('app'), $header->attribute('dlg')); foreach (array('id', 'ts', 'nonce', 'mac') as $requiredAttribute) { if (null === $header->attribute($requiredAttribute)) { throw new UnauthorizedException('Missing attributes'); } } $credentials = $this->credentialsProvider->loadCredentialsById($header->attribute('id')); $calculatedMac = $this->crypto->calculateMac('header', $credentials, $artifacts); if (!$this->crypto->fixedTimeComparison($calculatedMac, $header->attribute('mac'))) { throw new UnauthorizedException('Bad MAC'); } if (null !== $artifacts->payload()) { if (null === $artifacts->hash()) { // Should this ever happen? Difficult to get a this far if // hash is missing as the MAC will probably be wrong anyway. throw new UnauthorizedException('Missing required payload hash'); } $calculatedHash = $this->crypto->calculatePayloadHash($artifacts->payload(), $credentials->algorithm(), $artifacts->contentType()); if (!$this->crypto->fixedTimeComparison($calculatedHash, $artifacts->hash())) { throw new UnauthorizedException('Bad payload hash'); } } if (!$this->nonceValidator->validateNonce($artifacts->nonce(), $artifacts->timestamp())) { throw new UnauthorizedException('Invalid nonce'); } if (abs($header->attribute('ts') - $now) > $this->timestampSkewSec) { $ts = $this->timeProvider->createTimestamp() + $this->localtimeOffsetSec; $tsm = $this->crypto->calculateTsMac($ts, $credentials); throw new UnauthorizedException('Stale timestamp', array('ts' => $ts, 'tsm' => $tsm)); } return new Response($credentials, $artifacts); }
public function authenticate(CredentialsInterface $credentials, Request $request, $headerObjectOrString, array $options = array()) { if (is_string($headerObjectOrString)) { $header = HeaderFactory::createFromString('Server-Authorization', $headerObjectOrString); } elseif ($headerObjectOrString instanceof Header) { $header = $headerObjectOrString; } else { throw new \InvalidArgumentException("Header must either be a string or an instance of 'Dflydev\\Hawk\\Header\\Header'"); } if (isset($options['payload']) || isset($options['content_type'])) { if (isset($options['payload']) && isset($options['content_type'])) { $payload = $options['payload']; $contentType = $options['content_type']; } else { throw new \InvalidArgumentException("If one of 'payload' and 'content_type' are specified, both must be specified."); } } else { $payload = null; $contentType = null; } if ($ts = $header->attribute('ts')) { // do something with ts } $artifacts = new Artifacts($request->artifacts()->method(), $request->artifacts()->host(), $request->artifacts()->port(), $request->artifacts()->resource(), $request->artifacts()->timestamp(), $request->artifacts()->nonce(), $header->attribute('ext'), $payload, $contentType, $header->attribute('hash'), $request->artifacts()->app(), $request->artifacts()->dlg()); $mac = $this->crypto->calculateMac('response', $credentials, $artifacts); if ($header->attribute('mac') !== $mac) { return false; } if (!$payload) { return true; } if (!$artifacts->hash()) { return false; } $hash = $this->crypto->calculatePayloadHash($payload, $credentials->algorithm(), $contentType); return $artifacts->hash() === $hash; }