From 066063fec98237ceead3ad076967e4d0abb01915 Mon Sep 17 00:00:00 2001 From: Evan Sharp Date: Sat, 12 Apr 2025 22:22:33 -0700 Subject: [PATCH 1/2] Implement disucssion idea #37. I didn't review the code to see if it is up to date with Facebook's oauth flow. https://github.com/datamweb/shield-oauth/discussions/37 --- src/Config/ShieldOAuthConfig.php | 7 ++ src/Libraries/FacebookOAuth.php | 116 +++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 src/Libraries/FacebookOAuth.php diff --git a/src/Config/ShieldOAuthConfig.php b/src/Config/ShieldOAuthConfig.php index 6fb0107..34df98a 100644 --- a/src/Config/ShieldOAuthConfig.php +++ b/src/Config/ShieldOAuthConfig.php @@ -50,6 +50,13 @@ class ShieldOAuthConfig extends BaseConfig // 'client_id' => 'Get it from Yahoo', // 'client_secret' => 'Get it from Yahoo', + // 'allow_login' => true, + // 'allow_register' => true, + // ], + // 'facebook' => [ + // 'client_id' => 'Get it from Facebook', + // 'client_secret' => 'Get it from Facebook', + // 'allow_login' => true, // 'allow_register' => true, // ], diff --git a/src/Libraries/FacebookOAuth.php b/src/Libraries/FacebookOAuth.php new file mode 100644 index 0000000..358b706 --- /dev/null +++ b/src/Libraries/FacebookOAuth.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Datamweb\ShieldOAuth\Libraries; + +use Datamweb\ShieldOAuth\Libraries\Basic\AbstractOAuth; + +class FacebookOAuth extends AbstractOAuth +{ + + private static $API_CODE_URL = 'https://www.facebook.com/v16.0/dialog/oauth'; + private static $API_TOKEN_URL = 'https://graph.facebook.com/v16.0/oauth/access_token'; + private static $API_USER_INFO_URL = 'https://graph.facebook.com/me?fields'; + private static $APPLICATION_NAME = 'SheildOAuth'; + protected string $token; + protected string $client_id; + protected string $client_secret; + protected string $callbake_url; + protected string $fb_scope; + + + public function __construct(string $token = '') + { + $this->token = $token; + $this->client = \Config\Services::curlrequest(); + + $this->config = config('ShieldOAuthConfig'); + $this->callbake_url = base_url('oauth/' . $this->config->call_back_route); + $this->client_id = $this->config->oauthConfigs['facebook']['client_id']; + $this->client_secret = $this->config->oauthConfigs['facebook']['client_secret']; + $this->fb_scope = "id,first_name,last_name,middle_name,name,name_format,picture,short_name,email"; + } + + public function makeGoLink(string $state): string + { + return self::$API_CODE_URL . "?client_id={$this->client_id}&redirect_uri={$this->callbake_url}&state={$state}"; + } + + protected function fetchAccessTokenWithAuthCode(array $allGet): void + { + try { + // send request to API URL + $response = $this->client->request('POST', self::$API_TOKEN_URL, [ + 'form_params' => [ + 'client_id' => $this->client_id, + 'client_secret' => $this->client_secret, + 'code' => $allGet['code'], + 'redirect_uri' => $this->callbake_url, + 'grant_type' => 'authorization_code', + ], + 'headers' => [ + 'User-Agent' => self::$APPLICATION_NAME . '/1.0', + 'Accept' => 'application/json', + ], + ]); + } catch (Exception $e) { + exit($e->getMessage()); + } + $token = json_decode($response->getBody())->access_token; + $this->setToken($token); + } + + protected function fetchUserInfoWithToken(): object + { + // send request to API URL + try { + $response = $this->client->request('POST', self::$API_USER_INFO_URL.'='.$this->fb_scope, [ + 'headers' => [ + 'Accept' => 'application/json', + 'User-Agent' => self::$APPLICATION_NAME . '/1.0', + 'Authorization' => 'Bearer ' . $this->getToken(), + ], + 'http_errors' => false, + ]); + } catch (Exception $e) { + exit($e->getMessage()); + } + return json_decode($response->getBody()); + } + + protected function setColumnsName(string $nameOfProcess, $userInfo): array + { + if ($nameOfProcess === 'syncingUserInfo') { + $usersColumnsName = [ + $this->config->usersColumnsName['first_name'] => $userInfo->first_name, + $this->config->usersColumnsName['last_name'] => $userInfo->last_name, + $this->config->usersColumnsName['avatar'] => $userInfo->picture->data->url, + ]; + } + + if ($nameOfProcess === 'newUser') { + $usersColumnsName = [ + // users tbl // OAuth + 'username' => $userInfo->first_name, + 'email' => $userInfo->email, + 'password' => random_string('crypto', 32), + 'active' => '1', + $this->config->usersColumnsName['first_name'] => $userInfo->first_name, + $this->config->usersColumnsName['last_name'] => $userInfo->last_name, + $this->config->usersColumnsName['avatar'] => $userInfo->picture->data->url, + ]; + } + + return $usersColumnsName; + } +} From eb7ee17fd619883f93b6b7c2c3d8d0c10a4f2095 Mon Sep 17 00:00:00 2001 From: Evan Sharp Date: Sat, 12 Apr 2025 22:41:19 -0700 Subject: [PATCH 2/2] Update docs for Facebook driver. --- docs/get_keys.md | 3 +++ docs/index.md | 2 +- docs/install.md | 1 + docs/quickstart.md | 4 +--- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/get_keys.md b/docs/get_keys.md index 54a60ec..6944bee 100644 --- a/docs/get_keys.md +++ b/docs/get_keys.md @@ -34,3 +34,6 @@ The guide to get the `client_id` & `client_secret` keys on Google is [here](http # Get Yahoo Keys The guide to get the `client_id` & `client_secret` keys on Yahoo is [here](https://developer.yahoo.com/apps/create/). + +# Get Facebook Keys +The guide to get the `client_id` & `client_secret` keys on Facebook is [here](https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow#login). diff --git a/docs/index.md b/docs/index.md index 9eeb1c4..4f67152 100644 --- a/docs/index.md +++ b/docs/index.md @@ -9,7 +9,7 @@ [![Latest Stable Version](https://poser.pugx.org/datamweb/shield-oauth/v?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) [![Total Downloads](https://poser.pugx.org/datamweb/shield-oauth/downloads?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) [![Latest Unstable Version](https://poser.pugx.org/datamweb/shield-oauth/v/unstable?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) [![License](https://poser.pugx.org/datamweb/shield-oauth/license?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) [![PHP Version Require](https://poser.pugx.org/datamweb/shield-oauth/require/php?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) -`Shield OAuth` helps you to provide the possibility of login or registering users through the OAuth service. Currently, `Shield OAuth` supports `Google OAuth` and `GitHub OAuth` by default, but it allows you to implement it for any other service, including Yahoo, Facebook, Twitter, LinkedIn, GitLab and ..., this is very easy. Just create a class in route `app\Libraries\ShieldOAuth`! +`Shield OAuth` helps you to provide the possibility of login or registering users through the OAuth service. Currently, `Shield OAuth` supports `Google OAuth`, `GitHub OAuth`, and `Facebook OAuth` by default, but it allows you to implement it for any other service, including Yahoo, Twitter, LinkedIn, GitLab and ..., this is very easy. Just create a class in route `app\Libraries\ShieldOAuth`! more info see [How to add other services](add_other_oauth.md). ## Links: diff --git a/docs/install.md b/docs/install.md index 791d23a..70a7448 100644 --- a/docs/install.md +++ b/docs/install.md @@ -120,6 +120,7 @@ The last step is to, You can create your own buttons in views, what is important ```html http://localhost:8080/oauth/google http://localhost:8080/oauth/github +http://localhost:8080/oauth/facebook http://localhost:8080/oauth/yahoo