/** * */ public function grantAccessToken() { $filters = ["grant_type" => ["filter" => FILTER_VALIDATE_REGEXP, "options" => ["regexp" => OAUTH2_GRANT_TYPE_REGEXP], "flags" => FILTER_REQUIRE_SCALAR], "scope" => ["flags" => FILTER_REQUIRE_SCALAR], "code" => ["flags" => FILTER_REQUIRE_SCALAR], "redirect_uri" => ["filter" => FILTER_SANITIZE_URL], "username" => ["flags" => FILTER_REQUIRE_SCALAR], "password" => ["flags" => FILTER_REQUIRE_SCALAR], "assertion_type" => ["flags" => FILTER_REQUIRE_SCALAR], "assertion" => ["flags" => FILTER_REQUIRE_SCALAR], "refresh_token" => ["flags" => FILTER_REQUIRE_SCALAR]]; $input = filter_input_array(INPUT_POST, $filters); // Grant Type must be specified. if (!$input["grant_type"]) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST, 'Invalid grant_type parameter or parameter missing'); } // Make sure we've implemented the requested grant type if (!in_array($input["grant_type"], $this->getSupportedGrantTypes())) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_UNSUPPORTED_GRANT_TYPE); } // Authorize the client $client = $this->getClientCredentials(); if ($this->checkClientCredentials($client[0], $client[1]) === false) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_CLIENT); } if (!$this->checkRestrictedGrantType($client[0], $input["grant_type"])) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_UNAUTHORIZED_CLIENT); } if (!$this->checkRestrictedGrantType($client[0], $input["grant_type"])) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_UNAUTHORIZED_CLIENT); } // Do the granting switch ($input["grant_type"]) { case OAUTH2_GRANT_TYPE_AUTH_CODE: if (!$input["code"] || !$input["redirect_uri"]) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST); } $stored = $this->getAuthCode($input["code"]); // Ensure that the input uri starts with the stored uri if ($stored === null || strcasecmp(substr($input["redirect_uri"], 0, strlen($stored["redirect_uri"])), $stored["redirect_uri"]) !== 0 || $client[0] != $stored["client_id"]) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_GRANT); } if ($stored["expires"] < time()) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_EXPIRED_TOKEN); } break; case OAUTH2_GRANT_TYPE_USER_CREDENTIALS: $application = ApiApplication::load_from_client_id($this->app, $client[0]); if (!$application->is_password_granted()) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_UNSUPPORTED_GRANT_TYPE, 'Password grant type is not enable for your client'); } if (!$input["username"] || !$input["password"]) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST, 'Missing parameters. "username" and "password" required'); } $stored = $this->checkUserCredentials($client[0], $input["username"], $input["password"]); if ($stored === false) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_GRANT, 'Username/password mismatch or account locked, please try to log in via Web Application'); } break; case OAUTH2_GRANT_TYPE_ASSERTION: if (!$input["assertion_type"] || !$input["assertion"]) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST); } $stored = $this->checkAssertion($client[0], $input["assertion_type"], $input["assertion"]); if ($stored === false) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_GRANT); } break; case OAUTH2_GRANT_TYPE_REFRESH_TOKEN: if (!$input["refresh_token"]) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST, 'No "refresh_token" parameter found'); } $stored = $this->getRefreshToken($input["refresh_token"]); if ($stored === null || $client[0] != $stored["client_id"]) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_GRANT); } if ($stored["expires"] < time()) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_EXPIRED_TOKEN); } // store the refresh token locally so we can delete it when a new refresh token is generated $this->setVariable('_old_refresh_token', $stored["token"]); break; case OAUTH2_GRANT_TYPE_NONE: $stored = $this->checkNoneAccess($client[0]); if ($stored === false) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST); } } // Check scope, if provided if ($input["scope"] && (!is_array($stored) || !isset($stored["scope"]) || !$this->checkScope($input["scope"], $stored["scope"]))) { $this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_SCOPE); } if (!$input["scope"]) { $input["scope"] = null; } $token = $this->createAccessToken($stored['account_id'], $input["scope"]); $this->sendJsonHeaders(); echo json_encode($token); return; }