public function createAccessToken($client_id, $user_id, $scope = NULL) { try { $issueRefreshToken = Config::get('oauth2.includeRefreshToken', true); return Model::factory('oauth')->createAccessToken($client_id, $user_id, $scope, $issueRefreshToken); } catch (Exception $e) { throw Oauth2_Exception::factory(500, 'server_error', 'The Token server encountered an unexpected condition which prevented it from fulfilling the request.'); } }
/** * Handle the creation of access token, also issue refresh token if supported / desirable. * * @param $client_id * Client identifier related to the authorization code * @param $user_id * User ID associated with the authorization code * @param $redirect_uri * An absolute URI to which the authorization server will redirect the * user-agent to when the end-user authorization step is completed. * @param $scope * (optional) Scopes to be stored in space-separated string. * * @see http://tools.ietf.org/html/rfc6749#section-5 * @ingroup oauth2_section_5 */ protected function createAccessToken($client_id, $user_id, $redirect_uri, $scope = NULL) { try { /** * Client Credentials Grant does NOT include a refresh token * * @see http://tools.ietf.org/html/rfc6749#section-4.4.3 */ $includeRefreshToken = false; return Model::factory('oauth')->createAccessToken($client_id, $user_id, $scope, $includeRefreshToken); } catch (Exception $e) { throw Oauth2_Exception::factory(500, 'server_error', 'The Token server encountered an unexpected condition which prevented it from fulfilling the request.'); } }
protected function validateRevokeRequest() { if (!($token = $this->request->query("token"))) { // We don't have a good URI to use throw Oauth2_Exception::factory(400, 'invalid_request', "No Token supplied"); return false; } $this->token = $token; if (!($result = Model::factory('oauth')->isValidRevoke($token))) { throw Oauth2_Exception::factory(400, 'invalid_grant', "Token invalid"); return false; } $this->token_info = $result[0]; return TRUE; }
/** * Grant or deny a requested access token. * This would be called from the "/token" endpoint as defined in the spec. * You can call your endpoint whatever you want. * * @see http://tools.ietf.org/html/rfc6749#section-4 * @see http://tools.ietf.org/html/rfc6749#section-10.6 * @see http://tools.ietf.org/html/rfc6749#section-4.1.3 * * @ingroup oauth2_section_4 */ protected function grantAccessToken() { if (strtolower($this->request->method()) != 'post') { $this->response->headers(array('Allow' => 'POST')); throw Oauth2_Exception::factory(405, 'invalid_request', 'The request method must be POST when requesting an access token', NULL, '#section-3.2'); return FALSE; } /* Determine grant type from request * and validate the request for that grant type */ if (!($grantTypeIdentifier = $this->request->post('grant_type'))) { throw Oauth2_Exception::factory(400, 'invalid_request', 'The grant type was not specified in the request'); return FALSE; } if (!isset($this->grantTypes[$grantTypeIdentifier])) { /* TODO: If this is an OAuth2 supported grant type that we have chosen not to implement, throw a 501 Not Implemented instead */ throw Oauth2_Exception::factory(400, 'unsupported_grant_type', sprintf('Grant type "%s" not supported', $grantTypeIdentifier)); return null; } $grantType = $this->grantTypes[$grantTypeIdentifier]; /* Retrieve the client information from the request * ClientCredentials allow for grant types which also assert the client data * in which case ClientCredentials is handled in the validateRequest method * * @see OAuth2\GrantType\ClientCredentials */ if (!$grantType instanceof Oauth2_GrantType_ClientCredentials) { $check = new Oauth2_GrantType_ClientCredentials($this->config, FALSE); if (!$check->validateRequest($this->request, $this->response)) { return null; } $clientId = $check->getClientId(); } /* Retrieve the grant type information from the request * The GrantTypeInterface object handles all validation * If the object is an instance of Oauth2_GrantType_ClientCredentials, * That logic is handled here as well */ if (!$grantType->validateRequest($this->request, $this->response)) { return null; } if ($grantType instanceof Oauth2_GrantType_ClientCredentials) { $clientId = $grantType->getClientId(); } else { // validate the Client ID (if applicable) if (!is_null($storedClientId = $grantType->getClientId()) && $storedClientId != $clientId) { throw Oauth2_Exception::factory(400, 'invalid_grant', sprintf('%s doesn\'t exist or is invalid for the client', $grantTypeIdentifier)); return null; } } $requestedScope = NULL; /* * Validate the scope of the token * If the grant type returns a value for the scope, * as is the case with the "Authorization Code" grant type, * this value must be verified with the scope being requested */ /* $availableScope = $grantType->getScope(); if (!$requestedScope = $this->getScopeFromRequest($request)) { if (!$availableScope) { if (false === $defaultScope = $this->getDefaultScope($clientId)) { throw Oauth2_Exception::factory(400, 'invalid_scope', 'This application requires you specify a scope parameter'); return null; } } $requestedScope = $availableScope ? $availableScope : $defaultScope; } if (($requestedScope && !$this->scopeExists($requestedScope, $clientId)) || ($availableScope && !$this->checkScope($requestedScope, $availableScope))) { throw Oauth2_Exception::factory(400, 'invalid_scope', 'An unsupported scope was requested'); return null; }*/ return $grantType->createAccessToken($clientId, $grantType->getUserId(), $requestedScope); }
/** * Pull the authorization request data out of the HTTP request. * - The redirect_uri is OPTIONAL as per draft 20. But your implementation can enforce it * by setting $config['enforce_redirect'] to true. * - The state is OPTIONAL but recommended to enforce CSRF. Draft 21 states, however, that * CSRF protection is MANDATORY. You can enforce this by setting the $config['enforce_state'] to true. * * The draft specifies that the parameters should be retrieved from GET, override the Response * object to change this * * @return * The authorization parameters so the authorization server can prompt * the user for approval if valid. * * @see http://tools.ietf.org/html/rfc6749#section-4.1.1 * @see http://tools.ietf.org/html/rfc6749#section-10.12 * */ protected function validateAuthorizeRequest() { // Make sure a valid client id was supplied (we can not redirect because we were unable to verify the URI) if (!($client_id = $this->request->query("client_id"))) { // We don't have a good URI to use throw Oauth2_Exception::factory(400, 'invalid_client', "No client id supplied"); return false; } // Get client details if (!($clientData = $this->getClientDetails($client_id))) { throw Oauth2_Exception::factory(400, 'invalid_client', 'The client id supplied is invalid'); return false; } $this->client = $clientData; $registered_redirect_uri = isset($clientData['redirect_uri']) ? $clientData['redirect_uri'] : ''; // Make sure a valid redirect_uri was supplied. If specified, it must match the clientData URI. // @see http://tools.ietf.org/html/rfc6749#section-3.1.2 // @see http://tools.ietf.org/html/rfc6749#section-4.1.2.1 // @see http://tools.ietf.org/html/rfc6749#section-4.2.2.1 if ($supplied_redirect_uri = $this->request->query('redirect_uri')) { // validate there is no fragment supplied $parts = parse_url($supplied_redirect_uri); if (isset($parts['fragment']) && $parts['fragment']) { throw Oauth2_Exception::factory(400, 'invalid_uri', 'The redirect URI must not contain a fragment'); return false; } // validate against the registered redirect uri(s) if available if ($registered_redirect_uri && !$this->validateRedirectUri($supplied_redirect_uri, $registered_redirect_uri)) { throw Oauth2_Exception::factory(400, 'redirect_uri_mismatch', 'The redirect URI provided is missing or does not match'); return false; } $redirect_uri = $supplied_redirect_uri; } else { // use the registered redirect_uri if none has been supplied, if possible if (!$registered_redirect_uri) { throw Oauth2_Exception::factory(400, 'invalid_uri', 'No redirect URI was supplied or stored'); return false; } if (count(explode(' ', $registered_redirect_uri)) > 1) { throw Oauth2_Exception::factory(400, 'invalid_uri', 'A redirect URI must be supplied when multiple redirect URIs are registered'); return false; } $redirect_uri = $registered_redirect_uri; } // Select the redirect URI $response_type = $this->request->query('response_type'); $state = $this->request->query('state'); //if (!$scope = $this->getScopeFromRequest($request)) { // $scope = $this->getDefaultScope($client_id); //} // type and client_id are required if (!$response_type || !in_array($response_type, array(self::RESPONSE_TYPE_AUTHORIZATION_CODE, self::RESPONSE_TYPE_ACCESS_TOKEN))) { $this->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'invalid_request', 'Invalid or missing response type'); return false; } if ($response_type == self::RESPONSE_TYPE_AUTHORIZATION_CODE) { if (!isset($this->responseTypes['code'])) { $this->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'unsupported_response_type', 'authorization code grant type not supported'); return false; } if (!$this->checkRestrictedGrantType($client_id, 'authorization_code')) { $this->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'unauthorized_client', 'The grant type is unauthorized for this client_id'); return false; } if ($this->config['enforce_redirect'] && !$redirect_uri) { throw Oauth2_Exception::factory(400, 'redirect_uri_mismatch', 'The redirect URI is mandatory and was not supplied'); return false; } } if ($response_type == self::RESPONSE_TYPE_ACCESS_TOKEN) { if (!$this->config['allow_implicit']) { $this->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'unsupported_response_type', 'implicit grant type not supported'); return false; } if (!$this->checkRestrictedGrantType($client_id, 'implicit')) { $this->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'unauthorized_client', 'The grant type is unauthorized for this client_id'); return false; } } // Validate that the requested scope is supported /* if (false === $scope) { $this->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'invalid_client', 'This application requires you specify a scope parameter'); return false; } if (!is_null($scope) && !$this->scopeExists($scope, $client_id)) { $this->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'invalid_scope', 'An unsupported scope was requested'); return false; }*/ // Validate state parameter exists (if configured to enforce this) if ($this->config['enforce_state'] && !$state) { $this->setRedirect($this->config['redirect_status_code'], $redirect_uri, null, 'invalid_request', 'The state parameter is required'); return false; } // save the input data and return true //$this->scope = $scope; $this->state = $state; $this->client_id = $client_id; // Only save the SUPPLIED redirect URI (@see http://tools.ietf.org/html/rfc6749#section-4.1.3) $this->redirect_uri = $supplied_redirect_uri; $this->response_type = $response_type; return true; }