From 9321ad8399ddfe96ff7e48b641e7f8bd197cfd13 Mon Sep 17 00:00:00 2001 From: Tim Verheul Date: Wed, 25 Sep 2019 14:00:05 +0200 Subject: [PATCH 1/2] updated --- src/Auth.php | 64 +++++++++++++++------ src/FortniteClient.php | 128 ++++++++++++++++++++++++++++++----------- 2 files changed, 140 insertions(+), 52 deletions(-) diff --git a/src/Auth.php b/src/Auth.php index 52375f1..b1c121d 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -1,12 +1,15 @@ access_token = $access_token; $this->in_app_id = $in_app_id; $this->refresh_token = $refresh_token; $this->account_id = $account_id; $this->expires_in = $expires_in; - $this->account = new Account($this->access_token,$this->account_id); + $this->account = new Account($this->access_token, $this->account_id); $this->status = new Status($this->access_token); - if ($this->status->allowedToPlay() === false){ + if ($this->status->allowedToPlay() === false) { $this->account->acceptEULA(); } $this->profile = new Profile($this->access_token, $this->account_id); @@ -53,7 +57,8 @@ private function __construct($access_token, $in_app_id, $refresh_token, $account * * @return self New Auth instance */ - public static function login($email, $password, $challenge = '', $code = '') { + public static function login($email, $password, $challenge = '', $code = '') + { $requestParams = [ 'includePerms' => 'false', // We don't need these here @@ -63,7 +68,8 @@ public static function login($email, $password, $challenge = '', $code = '') { if (empty($challenge) && empty($code)) { // Regular login $requestParams = array_merge($requestParams, [ - 'grant_type' => 'password', + 'grant_type' => 'exchange_code', + 'exchange_code' => 'test', 'username' => $email, 'password' => $password, ]); @@ -75,8 +81,23 @@ public static function login($email, $password, $challenge = '', $code = '') { ]); } + $client = new Client(['cookies' => true]); + + $dataToken = FortniteClient::sendUnrealXSRFClientPostRequest($client); + + $data = FortniteClient::sendUnrealClientLoginRequestPostRequest($client, $dataToken, $email, $password); + + $dataParam = FortniteClient::sendUnrealClientExchangePostRequest($client, $dataToken); + + $requestParams = array_merge($requestParams, [ + 'grant_type' => 'exchange_code', + 'exchange_code' => $dataParam->code, + 'includePerms' => 'true', + 'token_type' => 'eg1', + ]); + // First, we need to get a token for the Unreal Engine client - $data = FortniteClient::sendUnrealClientPostRequest(FortniteClient::EPIC_OAUTH_TOKEN_ENDPOINT, $requestParams); + $data = FortniteClient::sendUnrealClientPostRequest($client, FortniteClient::EPIC_OAUTH_TOKEN_ENDPOINT, $requestParams); if (!isset($data->access_token)) { if ($data->errorCode === 'errors.com.epicgames.common.two_factor_authentication.required') { @@ -87,14 +108,14 @@ public static function login($email, $password, $challenge = '', $code = '') { } // Now that we've got our Unreal Client launcher token, let's get an exchange token for Fortnite - $data = FortniteClient::sendUnrealClientGetRequest(FortniteClient::EPIC_OAUTH_EXCHANGE_ENDPOINT, $data->access_token, true); + $data = FortniteClient::sendUnrealClientGetRequest($client, FortniteClient::EPIC_OAUTH_EXCHANGE_ENDPOINT, $data->access_token, true); if (!isset($data->code)) { throw new \Exception($data->errorMessage); } // Should be good. Let's get our tokens for the Fortnite API - $data = FortniteClient::sendUnrealClientPostRequest(FortniteClient::EPIC_OAUTH_TOKEN_ENDPOINT, [ + $data = FortniteClient::sendUnrealClientPostRequest($client, FortniteClient::EPIC_OAUTH_TOKEN_ENDPOINT, [ 'grant_type' => 'exchange_code', 'exchange_code' => $data->code, 'includePerms' => false, // We don't need these here @@ -113,8 +134,9 @@ public static function login($email, $password, $challenge = '', $code = '') { * @param string $refresh_token Exisiting OAuth2 refresh token * @return self New Auth instance */ - public static function refresh($refresh_token) { - $data = FortniteClient::sendUnrealClientPostRequest(FortniteClient::EPIC_OAUTH_TOKEN_ENDPOINT, [ + public static function refresh($refresh_token) + { + $data = FortniteClient::sendUnrealClientPostRequest($client, FortniteClient::EPIC_OAUTH_TOKEN_ENDPOINT, [ 'grant_type' => 'refresh_token', 'refresh_token' => $refresh_token, 'includePerms' => "false", // We don't need these here @@ -125,14 +147,15 @@ public static function refresh($refresh_token) { throw new \Exception($data->errorMessage); } - return new self($data->access_token, $data->in_app_id, $data->refresh_token, $data->account_id, $data->expires_in); + return new self($data->access_token, $data->in_app_id, $data->refresh_token, $data->account_id, $data->expires_in); } /** * Returns current refresh token. * @return string OAuth2 refresh token */ - public function refreshToken() { + public function refreshToken() + { return $this->refresh_token; } @@ -140,7 +163,8 @@ public function refreshToken() { * Returns the time until the OAuth2 access token expires. * @return string Time until OAuth2 access token expires (in seconds) */ - public function expiresIn() { + public function expiresIn() + { return $this->expires_in; } @@ -148,11 +172,13 @@ public function expiresIn() { * Returns current access token. * @return string OAuth2 access token */ - public function accessToken() { + public function accessToken() + { return $this->access_token; } - public function inAppId() { + public function inAppId() + { return $this->in_app_id; } -} \ No newline at end of file +} diff --git a/src/FortniteClient.php b/src/FortniteClient.php index 2b04c1c..23eea18 100644 --- a/src/FortniteClient.php +++ b/src/FortniteClient.php @@ -1,16 +1,25 @@ get($endpoint, [ 'headers' => [ @@ -60,7 +67,59 @@ public static function sendUnrealClientGetRequest($endpoint, $authorization = se 'Authorization' => (!$oauth) ? 'basic ' . $authorization : 'bearer ' . $authorization ] ]); - + + return json_decode($response->getBody()->getContents()); + } catch (GuzzleException $e) { + throw $e; //Throw exception back up to caller + } + } + + public static function sendUnrealXSRFClientPostRequest($client) + { + try { + $response = $client->get(self::CSRF_TOKEN); + $cookieJar = $client->getConfig('cookies'); + foreach ($cookieJar->toArray() as $item) { + if ($item['Name'] == "XSRF-TOKEN") { + $token = $item['Value']; + } + } + return $token; + } catch (GuzzleException $e) { + throw $e; //Throw exception back up to caller + } + } + + public static function sendUnrealClientLoginRequestPostRequest($client, $token, $email, $password) + { + try { + $response = $client->post(self::API_LOGIN, [ + 'form_params' => [ + 'email' => $email, + 'password' => $password, + 'rememberMe' => 'true' + ], + 'headers' => [ + 'Content-Type' => 'application/x-www-form-urlencoded', + 'x-xsrf-token' => $token, + ] + ]); + + return json_decode($response->getBody()->getContents()); + } catch (GuzzleException $e) { + throw $e; //Throw exception back up to caller + } + } + + public static function sendUnrealClientExchangePostRequest($client, $token) + { + try { + $response = $client->get(self::API_EXCHANGE_CODE, [ + 'headers' => [ + 'x-xsrf-token' => $token, + ] + ]); + return json_decode($response->getBody()->getContents()); } catch (GuzzleException $e) { throw $e; //Throw exception back up to caller @@ -75,13 +134,13 @@ public static function sendUnrealClientGetRequest($endpoint, $authorization = se * @param boolean $oauth Is $authorization an OAuth2 token * @return object Decoded JSON response body */ - public static function sendUnrealClientPostRequest($endpoint, $params = null, $authorization = self::EPIC_LAUNCHER_AUTHORIZATION, $oauth = false) { - $client = new Client(['http_errors' => false]); - + public static function sendUnrealClientPostRequest($client, $endpoint, $params, $authorization = self::EPIC_LAUNCHER_AUTHORIZATION, $oauth = false) + { try { $response = $client->post($endpoint, [ 'form_params' => $params, 'headers' => [ + 'Content-Type' => 'application/x-www-form-urlencoded', 'User-Agent' => self::UNREAL_CLIENT_USER_AGENT, 'Authorization' => (!$oauth) ? 'basic ' . $authorization : 'bearer ' . $authorization, 'X-Epic-Device-ID' => self::generateDeviceId() @@ -101,7 +160,8 @@ public static function sendUnrealClientPostRequest($endpoint, $params = null, $a * @param array $extra_headers (optional) * @return object Decoded JSON response body */ - public static function sendFortniteGetRequest($endpoint, $access_token, $extra_headers = array()) { + public static function sendFortniteGetRequest($endpoint, $access_token, $extra_headers = array()) + { $client = new Client(); $headers = [ @@ -129,11 +189,12 @@ public static function sendFortniteGetRequest($endpoint, $access_token, $extra_h * @param array $params Request parameters, using the name as the array key and value as the array value * @return object Decoded JSON response body */ - public static function sendFortnitePostRequest($endpoint, $access_token, $params = null) { + public static function sendFortnitePostRequest($endpoint, $access_token, $params = null) + { $client = new Client(); try { - $response = $client->post($endpoint, [ + $response = $client->post($endpoint, [ 'json' => $params, 'headers' => [ 'User-Agent' => self::FORTNITE_USER_AGENT, @@ -141,18 +202,16 @@ public static function sendFortnitePostRequest($endpoint, $access_token, $params ] ]); - return json_decode($response->getBody()->getContents()); - } catch (GuzzleException$e) { + return json_decode($response->getBody()->getContents()); + } catch (GuzzleException $e) { throw $e; //Throw exception back up to caller } - } - public static function sendFortniteDeleteRequest($endpoint, $access_token) { - $client = new Client(); - + public static function sendFortniteDeleteRequest($endpoint, $access_token) + { try { - $response = $client->delete($endpoint, [ + $response = $client->delete($endpoint, [ 'json' => $params, 'headers' => [ 'User-Agent' => self::FORTNITE_USER_AGENT, @@ -160,23 +219,26 @@ public static function sendFortniteDeleteRequest($endpoint, $access_token) { ] ]); - return json_decode($response->getBody()->getContents()); - } catch (GuzzleException$e) { + return json_decode($response->getBody()->getContents()); + } catch (GuzzleException $e) { throw $e; //Throw exception back up to caller } - } - private static function generateSequence($length) { + private static function generateSequence($length) + { return strtoupper((bin2hex(random_bytes($length / 2)))); } - public static function generateDeviceId() { - return sprintf('%s-%s-%s-%s-%s', - self::generateSequence(8), - self::generateSequence(4), - self::generateSequence(4), - self::generateSequence(4), - self::generateSequence(12)); + public static function generateDeviceId() + { + return sprintf( + '%s-%s-%s-%s-%s', + self::generateSequence(8), + self::generateSequence(4), + self::generateSequence(4), + self::generateSequence(4), + self::generateSequence(12) + ); } -} \ No newline at end of file +} From 8ee694bc8856343fa12e5b2376e383668e2fc848 Mon Sep 17 00:00:00 2001 From: Tim Verheul Date: Tue, 1 Oct 2019 16:35:47 +0200 Subject: [PATCH 2/2] Updated sendFortniteDeleteRequest --- src/Account.php | 57 ++++++++++++++++++++++++++++-------------- src/Auth.php | 4 +-- src/FortniteClient.php | 3 +++ 3 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/Account.php b/src/Account.php index 62f700c..01f3db7 100644 --- a/src/Account.php +++ b/src/Account.php @@ -1,26 +1,32 @@ access_token = $access_token; $this->account_id = $account_id; } - public static function getDisplayNameFromID($id, $access_token) { + public static function getDisplayNameFromID($id, $access_token) + { try { - $data = FortniteClient::sendFortniteGetRequest(FortniteClient::FORTNITE_ACCOUNT_API . "public/account?accountId={$id}", - $access_token); + $data = FortniteClient::sendFortniteGetRequest( + FortniteClient::FORTNITE_ACCOUNT_API . "public/account?accountId={$id}", + $access_token + ); return $data[0]->displayName; } catch (GuzzleException $e) { @@ -29,10 +35,13 @@ public static function getDisplayNameFromID($id, $access_token) { } } - public function getDisplayNamesFromID($id) { + public function getDisplayNamesFromID($id) + { try { - $data = FortniteClient::sendFortniteGetRequest(FortniteClient::FORTNITE_ACCOUNT_API . "public/account?accountId=" . join('&accountId=', $id), - $this->access_token); + $data = FortniteClient::sendFortniteGetRequest( + FortniteClient::FORTNITE_ACCOUNT_API . "public/account?accountId=" . join('&accountId=', $id), + $this->access_token + ); return $data; } catch (GuzzleException $e) { @@ -41,20 +50,30 @@ public function getDisplayNamesFromID($id) { } } - public function killSession() { + public function killSession() + { FortniteClient::sendFortniteDeleteRequest(FortniteClient::FORTNITE_ACCOUNT_API . "oauth/sessions/kill/" . $this->access_token, $this->access_token); } - public function acceptEULA(){ + public function acceptEULA() + { try { - $data = FortniteClient::sendFortniteGetRequest(FortniteClient::FORTNITE_EULA_API . "public/agreements/fn/account/" . $this->account_id .'?locale=en-US', - $this->access_token); + $data = FortniteClient::sendFortniteGetRequest( + FortniteClient::FORTNITE_EULA_API . "public/agreements/fn/account/" . $this->account_id . '?locale=en-US', + $this->access_token + ); - FortniteClient::sendFortnitePostRequest(FortniteClient::FORTNITE_EULA_API . "public/agreements/fn/version/".$data->version."/account/".$this->account_id."/accept?locale=en", - $this->access_token,new \StdClass()); + FortniteClient::sendFortnitePostRequest( + FortniteClient::FORTNITE_EULA_API . "public/agreements/fn/version/" . $data->version . "/account/" . $this->account_id . "/accept?locale=en", + $this->access_token, + new \StdClass() + ); - FortniteClient::sendFortnitePostRequest(FortniteClient::FORTNITE_API.'game/v2/grant_access/'.$this->account_id, - $this->access_token,new \StdClass()); + FortniteClient::sendFortnitePostRequest( + FortniteClient::FORTNITE_API . 'game/v2/grant_access/' . $this->account_id, + $this->access_token, + new \StdClass() + ); return true; } catch (GuzzleException $e) { @@ -62,4 +81,4 @@ public function acceptEULA(){ throw $e; } } -} \ No newline at end of file +} diff --git a/src/Auth.php b/src/Auth.php index b1c121d..38dd66a 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -19,7 +19,6 @@ class Auth public $profile; - // TODO: Probably want to lazy load all of these object initializations. Although currently I'm not sure how to go about that with PHP. // @Tustin 7/28/2018 /** @@ -80,7 +79,6 @@ public static function login($email, $password, $challenge = '', $code = '') 'challenge' => $challenge, ]); } - $client = new Client(['cookies' => true]); $dataToken = FortniteClient::sendUnrealXSRFClientPostRequest($client); @@ -136,6 +134,8 @@ public static function login($email, $password, $challenge = '', $code = '') */ public static function refresh($refresh_token) { + $client = new Client(['cookies' => true]); + $data = FortniteClient::sendUnrealClientPostRequest($client, FortniteClient::EPIC_OAUTH_TOKEN_ENDPOINT, [ 'grant_type' => 'refresh_token', 'refresh_token' => $refresh_token, diff --git a/src/FortniteClient.php b/src/FortniteClient.php index 23eea18..a5e32dd 100644 --- a/src/FortniteClient.php +++ b/src/FortniteClient.php @@ -210,6 +210,9 @@ public static function sendFortnitePostRequest($endpoint, $access_token, $params public static function sendFortniteDeleteRequest($endpoint, $access_token) { + $client = new Client(); + $params = null; + try { $response = $client->delete($endpoint, [ 'json' => $params,