/** * Grants access token for request * * @param IRequest $request * * @throws \OAuth2\Exception\InvalidGrantException * @throws \OAuth2\Exception\InvalidRequestException * @throws \OAuth2\Exception\InvalidScopeException * @throws \OAuth2\Exception\UnauthorizedClientException * @return IAccessToken */ public function grant(IRequest $request) { $username = $request->request('username'); $password = $request->request('password'); if (empty($username) || empty($password)) { throw new InvalidRequestException('Username and password are required.'); } $client = $this->clientAuthenticator->authenticate($request); if (!$client->isAllowedToUse($this)) { throw new UnauthorizedClientException('Client can not use this grant type.'); } $user = $this->userAuthenticator->authenticate($username, $password); if (!$user) { throw new InvalidUserCredentialsException('Invalid user credentials.'); } $requestedScopes = $request->request('scope'); $availableScopes = $user->getScopes(); if (empty($availableScopes)) { $availableScopes = $this->scopeResolver->getDefaultScopes(); } if (empty($availableScopes)) { throw new InvalidScopeException('Scope parameter has to be specified.'); } // intersection of requested and user scopes $scopes = $this->scopeResolver->intersect($requestedScopes, $availableScopes); return $this->accessTokenStorage->generate($user, $client, $scopes); }
function it_throws_exception_if_client_secret_is_provided_for_public_client(IRequest $request, IClientStorage $clientStorage, IClient $client) { $request->request('client_id')->willReturn('public')->shouldBeCalled(); $request->request('client_secret')->willReturn('secret')->shouldBeCalled(); $clientStorage->get('public')->willReturn($client)->shouldBeCalled(); $client->getSecret()->willReturn(null)->shouldBeCalled(); $this->shouldThrow(new InvalidClientException('Invalid client credentials.'))->during('authenticate', [$request]); }
/** * Authenticates client and returns it * * @param IRequest $request * * @return IClient * @throws InvalidClientException */ public function authenticate(IRequest $request) { $id = $request->request('client_id'); $secret = $request->request('client_secret'); if (!$id) { throw new InvalidClientException('Client id is missing.'); } if (!($client = $this->clientStorage->get($id))) { throw new InvalidClientException('Invalid client credentials.'); } if ((string) $secret !== (string) $client->getSecret()) { throw new InvalidClientException('Invalid client credentials.'); } return $client; }
/** * Matches token type against request and returns if it matches * * @param IRequest $request * * @throws \OAuth2\Exception\InvalidContentTypeException * @throws \OAuth2\Exception\InvalidHttpMethodException * @throws \OAuth2\Exception\MalformedTokenException * @return boolean */ public function match(IRequest $request) { // first check request for authorization header $header = $request->headers('authorization'); if ($header) { if (!preg_match('~Bearer\\s(\\S+)~', $header, $matches)) { throw new MalformedTokenException(); } $this->identifier = $matches[1]; return true; } // if is POST check for request (POST BODY) parameters if ($accessToken = $request->request('access_token')) { if (!($request->isMethod('post') || $request->isMethod('put'))) { throw new InvalidHttpMethodException(); } $contentType = $request->headers('content_type'); if (!$contentType || strpos($contentType, 'application/x-www-form-urlencoded') !== 0) { throw new InvalidContentTypeException(); } $this->identifier = $accessToken; return true; } // check query for access token if ($accessToken = $request->query('access_token')) { $this->identifier = $accessToken; return true; } return false; }
function it_matches_against_request(IRequest $request1, IRequest $request2) { $request1->request('grant_type')->willReturn('client_credentials')->shouldBeCalled(); $this->match($request1)->shouldReturn(true); $request2->request('grant_type')->willReturn('pom')->shouldBeCalled(); $this->match($request2)->shouldReturn(false); }
/** * Grants access token for request * * @param IRequest $request * * @throws \OAuth2\Exception\InvalidGrantException * @throws \OAuth2\Exception\MissingParameterException * @throws \OAuth2\Exception\UnauthorizedClientException * @return IAccessToken */ public function grant(IRequest $request) { if (!($refreshTokenIdentifier = $request->request('refresh_token'))) { throw new MissingParameterException("Parameter 'refresh_token' is missing."); } if (!($refreshToken = $this->refreshTokenStorage->get($refreshTokenIdentifier))) { throw new InvalidGrantException('Invalid refresh token.'); } $client = $this->clientAuthenticator->authenticate($request); // are clients same? if ($client->getId() !== $refreshToken->getClient()->getId()) { throw new InvalidGrantException('Invalid refresh token.'); } // is client allowed to use this grant type? if (!$client->isAllowedToUse($this)) { throw new UnauthorizedClientException('Client can not use this grant type.'); } $expiresAt = $refreshToken->getExpiresAt(); if ($expiresAt instanceof \DateTime) { $expiresAt = $expiresAt->getTimestamp(); } // is refresh token expired? if ($expiresAt < time()) { throw new InvalidGrantException('Refresh token has expired.'); } // intersection of refresh token and requested scopes $scopes = $this->scopeResolver->intersect($request->request('scope'), $refreshToken->getScopes()); return $this->accessTokenStorage->generate($refreshToken->getUser(), $refreshToken->getClient(), $scopes); }
function it_should_return_access_token_from_token_in_uri_query_parameter(IRequest $request) { $request->headers('authorization')->willReturn(null); $request->request('access_token')->willReturn(null); $request->query('access_token')->willReturn('pom'); $this->match($request)->shouldReturn(true); $this->getAccessToken()->shouldReturn('pom'); }
function it_issues_an_access_token(IRequest $request, IRefreshToken $refreshToken, IRefreshTokenStorage $refreshTokenStorage, IAccessTokenStorage $accessTokenStorage, IAccessToken $accessToken, IUser $user, IClient $client, IScope $scope1, IScope $scope2, IScopeResolver $scopeResolver, IClientAuthenticator $clientAuthenticator) { $scopes = [$scope1, $scope2]; $request->request('refresh_token')->willReturn('pom')->shouldBeCalled(); $refreshTokenStorage->get('pom')->willReturn($refreshToken)->shouldBeCalled(); $refreshToken->getClient()->willReturn($client)->shouldBeCalled(); $clientAuthenticator->authenticate($request)->willReturn($client)->shouldBeCalled(); $client->getId()->willReturn('test')->shouldBeCalled(); $client->isAllowedToUse($this)->willReturn(true)->shouldBeCalled(); $refreshToken->getExpiresAt()->willReturn(time() + 100)->shouldBeCalled(); $refreshToken->getScopes()->willReturn($scopes)->shouldBeCalled(); $request->request('scope')->willReturn(null)->shouldBeCalled(); $scopeResolver->intersect(null, $scopes)->willReturn($scopes)->shouldBeCalled(); $refreshToken->getUser()->willReturn($user)->shouldBeCalled(); $accessTokenStorage->generate($user, $client, $scopes)->willReturn($accessToken)->shouldBeCalled(); $this->grant($request)->shouldReturnAnInstanceOf('OAuth2\\Storage\\IAccessToken'); }
/** * Grants access token for request * * @param IRequest $request * * @throws \OAuth2\Exception\InvalidGrantException * @throws \OAuth2\Exception\InvalidRequestException * @throws \OAuth2\Exception\UnauthorizedClientException * @return IAccessToken */ public function grant(IRequest $request) { $code = $request->request('code'); if (empty($code)) { throw new InvalidRequestException("Parameter 'code' is missing."); } $client = $this->clientAuthenticator->authenticate($request); if (!$client->isAllowedToUse($this)) { throw new UnauthorizedClientException('Client can not use this grant type.'); } $authorizationCode = $this->authorizationCodeStorage->get($code); if (!$authorizationCode) { throw new InvalidGrantException('Authorization code is invalid.'); } if ($authorizationCode->getExpiresAt() < time()) { throw new InvalidGrantException('Authorization code has expired.'); } if ($client->getId() !== $authorizationCode->getClient()->getId()) { throw new InvalidGrantException('Authorization code is invalid.'); } $redirectUri = $request->request('redirect_uri'); $codeRedirectUri = $authorizationCode->getRedirectUri(); if (!empty($redirectUri)) { if (empty($codeRedirectUri) || $redirectUri !== $codeRedirectUri) { throw new InvalidRequestException('Redirect URI is missing, was not used in authorization or is invalid.'); } } else { if (!empty($codeRedirectUri)) { throw new InvalidRequestException('Redirect URI is missing, was not used in authorization or is invalid.'); } } return $this->accessTokenStorage->generate($authorizationCode->getUser(), $authorizationCode->getClient(), $authorizationCode->getScopes()); }
/** * Does grant type match given request? * * @param IRequest $request * * @return bool */ public function match(IRequest $request) { return $request->request('grant_type') === 'client_credentials'; }
function it_issues_an_access_token(IRequest $request, IClientAuthenticator $clientAuthenticator, IAuthorizationCodeStorage $authorizationCodeStorage, IAuthorizationCode $authorizationCode, IAccessTokenStorage $accessTokenStorage, IAccessToken $accessToken, IUser $user, IClient $client, IScope $scope) { $request->request('code')->willReturn('a')->shouldBeCalled(); $clientAuthenticator->authenticate($request)->willReturn($client)->shouldBeCalled(); $client->isAllowedToUse($this)->willReturn(true)->shouldBeCalled(); $authorizationCodeStorage->get('a')->willReturn($authorizationCode)->shouldBeCalled(); $authorizationCode->getExpiresAt()->willReturn(time() + 100)->shouldBeCalled(); $client->getId()->willReturn('id')->shouldBeCalled(); $authorizationCode->getClient()->willReturn($client)->shouldBeCalled(); $request->request('redirect_uri')->willReturn(null)->shouldBeCalled(); $authorizationCode->getRedirectUri()->willReturn(null)->shouldBeCalled(); $authorizationCode->getScopes()->willReturn([$scope])->shouldBeCalled(); $authorizationCode->getUser()->willReturn($user)->shouldBeCalled(); $authorizationCode->getClient()->willReturn($client)->shouldBeCalled(); $accessTokenStorage->generate($user, $client, [$scope])->willReturn($accessToken)->shouldBeCalled(); $this->grant($request)->shouldReturn($accessToken); }
function it_issues_an_access_token_using_default_scopes(IRequest $request, IClientAuthenticator $clientAuthenticator, IUserAuthenticator $userAuthenticator, IScopeResolver $scopeResolver, IUser $user, IClient $client, IScope $scope, IAccessTokenStorage $accessTokenStorage, IAccessToken $accessToken) { $request->request('username')->willReturn('root')->shouldBeCalled(); $request->request('password')->willReturn('p')->shouldBeCalled(); $clientAuthenticator->authenticate($request)->willReturn($client)->shouldBeCalled(); $client->isAllowedToUse($this)->willReturn(true)->shouldBeCalled(); $userAuthenticator->authenticate('root', 'p')->willReturn($user)->shouldBeCalled(); $request->request('scope')->willReturn(null)->shouldBeCalled(); $user->getScopes()->willReturn([])->shouldBeCalled(); $scopeResolver->getDefaultScopes()->willReturn([$scope])->shouldBeCalled(); $scopeResolver->intersect(null, [$scope])->willReturn([$scope])->shouldBeCalled(); $accessTokenStorage->generate($user, $client, [$scope])->willReturn($accessToken)->shouldBeCalled(); $this->grant($request)->shouldReturn($accessToken); }