public function handleCode(TokenRequest $tokenRequest, ClientData $clientData)
 {
     $code = $tokenRequest->getCode();
     $redirectUri = $tokenRequest->getRedirectUri();
     // If the redirect_uri was present in the authorize request, it MUST also be there
     // in the token request. If it was not there in authorize request, it MUST NOT be
     // there in the token request (this is not explicit in the spec!)
     $result = $this->db->getAuthorizationCode($clientData->getId(), $code, $redirectUri);
     if (false === $result) {
         throw new BadRequestException('invalid_grant', 'the authorization code was not found');
     }
     if ($this->io->getTime() > $result['issue_time'] + 600) {
         throw new BadRequestException('invalid_grant', 'the authorization code expired');
     }
     // we MUST be able to delete the authorization code, otherwise it was used before
     if (false === $this->db->deleteAuthorizationCode($clientData->getId(), $code, $redirectUri)) {
         // check to prevent deletion race condition
         throw new BadRequestException('invalid_grant', 'this authorization code grant was already used');
     }
     $approval = $this->db->getApprovalByResourceOwnerId($clientData->getId(), $result['resource_owner_id']);
     $token = array();
     $token['access_token'] = $this->io->getRandomHex();
     $token['expires_in'] = $this->accessTokenExpiry;
     // we always grant the scope the user authorized, no further restrictions here...
     // FIXME: the merging of authorized scopes in the authorize function is a bit of a mess!
     // we should deal with that there and come up with a good solution...
     $token['scope'] = $result['scope'];
     $token['refresh_token'] = $approval['refresh_token'];
     $token['token_type'] = 'bearer';
     $this->db->storeAccessToken($token['access_token'], $this->io->getTime(), $clientData->getId(), $result['resource_owner_id'], $token['scope'], $token['expires_in']);
     return $token;
 }
 private function addApproval(ClientData $clientData, $userId, $scope)
 {
     $approval = $this->storage->getApprovalByResourceOwnerId($clientData->getId(), $userId);
     if (false === $approval) {
         // no approval exists, generate a refresh_token and add it
         $refreshToken = 'code' === $clientData->getType() ? $this->io->getRandomHex() : null;
         $this->storage->addApproval($clientData->getId(), $userId, $scope, $refreshToken);
     } else {
         // an approval exists, we don't care about the scope, we just
         // update it if needed keeping the same refresh_token
         $this->storage->updateApproval($clientData->getId(), $userId, $scope);
     }
 }