From 9d1d208d63e3564dc82b0cc44cf9bfc7e4ee97b3 Mon Sep 17 00:00:00 2001 From: sink Date: Mon, 24 Feb 2020 21:20:51 +0800 Subject: [PATCH] feat: coding.net oauth #15 --- Coding/README.md | 161 +++++++++++++++++++++++++++ Coding/composer.json | 33 ++++++ Coding/src/CodingExtendSocialite.php | 16 +++ Coding/src/Provider.php | 65 +++++++++++ composer.json | 5 +- 5 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 Coding/README.md create mode 100644 Coding/composer.json create mode 100644 Coding/src/CodingExtendSocialite.php create mode 100644 Coding/src/Provider.php diff --git a/Coding/README.md b/Coding/README.md new file mode 100644 index 0000000..d968931 --- /dev/null +++ b/Coding/README.md @@ -0,0 +1,161 @@ +--- +title: "CODING" +--- + +## 1. Installation + +```bash +// This assumes that you have composer installed globally +composer require laravel-socialite-providers/coding +``` + +## 2. Service Provider + +* Remove `Laravel\Socialite\SocialiteServiceProvider` from your `providers[]` array in `config\app.php` if you have added it already. + +* Add `\SocialiteProviders\Manager\ServiceProvider::class` to your `providers[]` array in `config\app.php`. + +For example: + +``` php +'providers' => [ + // a whole bunch of providers + // remove 'Laravel\Socialite\SocialiteServiceProvider', + \SocialiteProviders\Manager\ServiceProvider::class, // add +]; +``` + +* Note: If you would like to use the Socialite Facade, you need to [install it.](https://github.com/laravel/socialite) + +## 3. Event Listener + +* Add `SocialiteProviders\Manager\SocialiteWasCalled` event to your `listen[]` array in `app/Providers/EventServiceProvider`. + +* Add your listeners (i.e. the ones from the providers) to the `SocialiteProviders\Manager\SocialiteWasCalled[]` that you just created. + +* The listener that you add for this provider is `'LaravelSocialiteProviders\\Coding\\CodingExtendSocialite@handle',`. + +* Note: You do not need to add anything for the built-in socialite providers unless you override them with your own providers. + +For example: + +```php +/** + * The event handler mappings for the application. + * + * @var array + */ +protected $listen = [ + \SocialiteProviders\Manager\SocialiteWasCalled::class => [ + // add your listeners (aka providers) here + 'LaravelSocialiteProviders\\Coding\\CodingExtendSocialite@handle', + ], +]; +``` + +#### Reference + +* [Laravel docs about events](http://laravel.com/docs/5.0/events) +* [Laracasts video on events in Laravel 5](https://laracasts.com/lessons/laravel-5-events) + +## 4. Configuration setup + +You will need to add an entry to the services configuration file so that after config files are cached for usage in production environment (Laravel command `artisan config:cache`) all config is still available. + +#### Add to `config/services.php`. + +```php +'coding' => [ + 'client_id' => env('CODING_CLIENT_ID'), + 'client_secret' => env('CODING_CLIENT_SECRET'), + 'redirect' => env('CODING_CALLBACK_URL'), + 'guzzle' => [ + 'base_uri' => 'https://' . env('CODING_TEAM') . '.coding.net/', + ], + 'scopes' => preg_split('/,/', env('CODING_SCOPES'), null, PREG_SPLIT_NO_EMPTY), // optional, can not use explode, see vlucas/phpdotenv#175 +], +``` + +## 5. Usage + +* [Laravel docs on configuration](http://laravel.com/docs/master/configuration) + +* You should now be able to use it like you would regularly use Socialite (assuming you have the facade installed): + +```php +return Socialite::with('coding')->redirect(); +``` + +### Lumen Support + +You can use Socialite providers with Lumen. Just make sure that you have facade support turned on and that you follow the setup directions properly. + +**Note:** If you are using this with Lumen, all providers will automatically be stateless since **Lumen** does not keep track of state. + +Also, configs cannot be parsed from the `services[]` in Lumen. You can only set the values in the `.env` file as shown exactly in this document. If needed, you can + also override a config (shown below). + +### Stateless + +* You can set whether or not you want to use the provider as stateless. Remember that the OAuth provider (Twitter, Tumblr, etc) must support whatever option you choose. + +**Note:** If you are using this with Lumen, all providers will automatically be stateless since **Lumen** does not keep track of state. + +```php +// to turn off stateless +return Socialite::with('coding')->stateless(false)->redirect(); + +// to use stateless +return Socialite::with('coding')->stateless()->redirect(); +``` + +### Overriding a config + +If you need to override the providers environment or config variables dynamically anywhere in your application, you may use the following: + +```php +$clientId = "secret"; +$clientSecret = "secret"; +$redirectUrl = "http://yourdomain.com/api/redirect"; +$additionalProviderConfig = [ + // Add additional configuration values here. +]; +$config = new \SocialiteProviders\Manager\Config( + $clientId, + $clientSecret, + $redirectUrl, + $additionalProviderConfig +); + +return Socialite::with('coding')->setConfig($config)->redirect(); +``` + +### Retrieving the Access Token Response Body + +Laravel Socialite by default only allows access to the `access_token`. Which can be accessed +via the `\Laravel\Socialite\User->token` public property. Sometimes you need access to the whole response body which +may contain items such as a `refresh_token`. + +You can get the access token response body, after you called the `user()` method in Socialite, by accessing the property `$user->accessTokenResponseBody`; + +```php +// default use openid as $user->id +$user = Socialite::driver('coding')->user(); +$accessTokenResponseBody = $user->accessTokenResponseBody; + +// use unionid as $user->id +$user = Socialite::driver('coding')->scopes('unionid')->user(); +``` + +### Retrieving User Details From A Token (OAuth2) + +If you already have a valid access token for a user, you can retrieve their details using the `userFromToken` method, but Tencent breaks OAuth2, need set "openid" first: + +```php +$user = Socialite::driver('coding')->setOpenId($openId)->userFromToken($token); +``` + +#### Reference + +* [Laravel Socialite Docs](https://github.com/laravel/socialite) +* [CODING OAuth](https://help.coding.net/docs/project/open/oauth.html) diff --git a/Coding/composer.json b/Coding/composer.json new file mode 100644 index 0000000..42d81ec --- /dev/null +++ b/Coding/composer.json @@ -0,0 +1,33 @@ +{ + "name": "laravel-socialite-providers/coding", + "description": "CODING OAuth2 Provider for Laravel Socialite", + "version": "0.1.0", + "license": "MIT", + "authors": [{ + "name": "sink", + "email": "sinkcup@gmail.com" + }], + "require": { + "php": ">=5.5", + "socialiteproviders/manager": "^3.3.6", + "ext-json": "*" + }, + "extra": { + "component": { + "id": "coding", + "target": "laravel-socialite-providers/socialite-coding.git", + "path": "Coding", + "entry": "src/Provider.php" + } + }, + "autoload": { + "psr-4": { + "LaravelSocialiteProviders\\Coding\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "LaravelSocialiteProviders\\Coding\\Tests\\": "tests" + } + } +} diff --git a/Coding/src/CodingExtendSocialite.php b/Coding/src/CodingExtendSocialite.php new file mode 100644 index 0000000..2ac8aec --- /dev/null +++ b/Coding/src/CodingExtendSocialite.php @@ -0,0 +1,16 @@ +extendSocialite('coding', __NAMESPACE__.'\Provider'); + } +} diff --git a/Coding/src/Provider.php b/Coding/src/Provider.php new file mode 100644 index 0000000..0427b70 --- /dev/null +++ b/Coding/src/Provider.php @@ -0,0 +1,65 @@ +buildAuthUrlFromBase($this->guzzle['base_uri'] . 'oauth_authorize.html', $state); + } + + /** + * {@inheritdoc} + */ + protected function getTokenUrl() + { + return '/api/oauth/access_token'; + } + + /** + * {@inheritdoc} + */ + protected function getUserByToken($token) + { + $response = $this->getHttpClient()->get('/api/account/current_user', [ + 'query' => [ + 'access_token' => $token, + ], + ]); + + return json_decode($response->getBody(), true)['data']; + } + + /** + * {@inheritdoc} + */ + protected function mapUserToObject(array $user) + { + return (new User())->setRaw($user)->map([ + 'id' => $user['id'], + 'nickname' => null, + 'name' => $user['name'], + 'email' => isset($user['email']) ? $user['email'] : null, + 'avatar' => $user['avatar'], + ]); + } +} diff --git a/composer.json b/composer.json index 6613b16..e97df23 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "laravel-socialite-providers/socialite-providers", "description": "Providers for Laravel Socialite", - "version": "0.2.0", + "version": "0.3.0", "license": "MIT", "authors": [{ "name": "sink", @@ -16,17 +16,20 @@ "dflydev/dot-access-data": "^2.0" }, "replace": { + "laravel-socialite-providers/coding": "0.1.0", "laravel-socialite-providers/socialite-wechat-service-account": "0.2.0", "laravel-socialite-providers/socialite-wechat-web": "0.2.0" }, "autoload": { "psr-4": { + "LaravelSocialiteProviders\\Coding\\": "Coding/src", "LaravelSocialiteProviders\\WeChatServiceAccount\\": "WeChatServiceAccount/src", "LaravelSocialiteProviders\\WeChatWeb\\": "WeChatWeb/src" } }, "autoload-dev": { "psr-4": { + "LaravelSocialiteProviders\\Coding\\Tests\\": "Coding/tests", "LaravelSocialiteProviders\\WeChatServiceAccount\\Tests\\": "WeChatServiceAccount/tests", "LaravelSocialiteProviders\\WeChatWeb\\Tests\\": "WeChatWeb/tests" }