Skip to content

Commit

Permalink
feat: coding.net oauth #15
Browse files Browse the repository at this point in the history
  • Loading branch information
sinkcup authored Feb 24, 2020
1 parent 0cd427d commit 9d1d208
Show file tree
Hide file tree
Showing 5 changed files with 279 additions and 1 deletion.
161 changes: 161 additions & 0 deletions Coding/README.md
Original file line number Diff line number Diff line change
@@ -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)
33 changes: 33 additions & 0 deletions Coding/composer.json
Original file line number Diff line number Diff line change
@@ -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": "[email protected]"
}],
"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"
}
}
}
16 changes: 16 additions & 0 deletions Coding/src/CodingExtendSocialite.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace LaravelSocialiteProviders\Coding;

use SocialiteProviders\Manager\SocialiteWasCalled;

class CodingExtendSocialite
{
/**
* Execute the provider.
*/
public function handle(SocialiteWasCalled $socialiteWasCalled)
{
$socialiteWasCalled->extendSocialite('coding', __NAMESPACE__.'\Provider');
}
}
65 changes: 65 additions & 0 deletions Coding/src/Provider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace LaravelSocialiteProviders\Coding;

use Illuminate\Support\Arr;
use SocialiteProviders\Manager\OAuth2\AbstractProvider;
use SocialiteProviders\Manager\OAuth2\User;

class Provider extends AbstractProvider
{
/**
* Unique Provider Identifier.
*/
const IDENTIFIER = 'CODING';

/**
* {@inheritdoc}
*/
protected $scopes = ['user'];

/**
* {@inheritdoc}
*/
protected function getAuthUrl($state)
{
// HACK: CODING 每个注册团队都是单独的二级域名,需要传递进来,目前发现有 with 和 guzzle 两种方法可以实现,这里选择 guzzle。
return $this->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'],
]);
}
}
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -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",
Expand All @@ -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"
}
Expand Down

0 comments on commit 9d1d208

Please sign in to comment.