diff --git a/Provider.php b/Provider.php new file mode 100644 index 0000000..cfd3481 --- /dev/null +++ b/Provider.php @@ -0,0 +1,124 @@ + $this->clientId, + 'state' => $state, + 'response_type' => 'code', + 'scope' => $this->formatScopes($this->getScopes(), $this->scopeSeparator), + 'redirect_uri' => $this->redirectUrl, + ]); + } + + /** + * {@inheritdoc} + */ + public function user() + { + if ($this->user) { + return $this->user; + } + + if ($this->hasInvalidState()) { + throw new InvalidStateException(); + } + + $response = $this->getAccessTokenResponse($this->getCode()); + + $token = Arr::get($response, 'data.access_token'); + + $this->user = $this->mapUserToObject( + $this->getUserByToken([ + 'access_token' => $token, + 'open_id' => Arr::get($response, 'data.open_id'), + ]) + ); + + return $this->user->setToken($token) + ->setExpiresIn(Arr::get($response, 'data.expires_in')) + ->setRefreshToken(Arr::get($response, 'data.refresh_token')); + } + + /** + * {@inheritdoc} + */ + public function getTokenUrl() + { + return 'https://open-api.tiktok.com/oauth/access_token/'; + } + + /** + * {@inheritdoc} + */ + protected function getTokenFields($code) + { + $fields = [ + 'client_key' => $this->clientId, + 'client_secret' => $this->clientSecret, + 'code' => $code, + 'grant_type' => 'authorization_code', + ]; + + return $fields; + } + + /** + * Get TikTok user by token. + * + * @param array $data + * + * @return mixed + */ + protected function getUserByToken($data) + { + // Note: The TikTok api does not have an endpoint to get a user by the access + // token only. Open id is also required therefore: + // $data['access_token'] = $token, $data['open_id'] = $open_id + + $response = $this->getHttpClient()->get( + 'https://open-api.tiktok.com/oauth/userinfo?'.http_build_query($data) + ); + + return json_decode($response->getBody()->getContents(), true); + } + + /** + * {@inheritdoc} + */ + protected function mapUserToObject($user) + { + $user = $user['data']; + + return (new User())->setRaw($user)->map([ + 'id' => $user['open_id'], + 'union_id' => $user['union_id'], + 'name' => $user['display_name'], + 'avatar' => $user['avatar_larger'], + ]); + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..8edaa4b --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +# TikTok + +```bash +composer require socialiteproviders/tiktok +``` + +## Installation & Basic Usage + +Please see the [Base Installation Guide](https://socialiteproviders.com/usage/), then follow the provider specific instructions below. + +### Add configuration to `config/services.php` + +```php +'tiktok' => [ + 'client_id' => env('TIKTOK_CLIENT_ID'), + 'client_secret' => env('TIKTOK_CLIENT_SECRET'), + 'redirect' => env('TIKTOK_REDIRECT_URI') +], +``` + +### Add provider event listener + +Configure the package's listener to listen for `SocialiteWasCalled` events. + +Add the event to your `listen[]` array in `app/Providers/EventServiceProvider`. See the [Base Installation Guide](https://socialiteproviders.com/usage/) for detailed instructions. + +```php +protected $listen = [ + \SocialiteProviders\Manager\SocialiteWasCalled::class => [ + // ... other providers + 'SocialiteProviders\\TikTok\\TikTokExtendSocialite@handle', + ], +]; +``` + +### Usage + +You should now be able to use the provider like you would regularly use Socialite (assuming you have the facade installed): + +```php +return Socialite::driver('tiktok')->redirect(); +``` + +# Returned User Fields + +- id +- union_id +- name +- avatar + +# Reference + +- [TikTok Login Kit](https://developers.tiktok.com/doc/login-kit-web) \ No newline at end of file diff --git a/TikTokExtendSocialite.php b/TikTokExtendSocialite.php new file mode 100644 index 0000000..00070cd --- /dev/null +++ b/TikTokExtendSocialite.php @@ -0,0 +1,18 @@ +extendSocialite('tiktok', Provider::class); + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..0970a80 --- /dev/null +++ b/composer.json @@ -0,0 +1,22 @@ +{ + "name": "socialiteproviders/tiktok", + "description": "TikTok (tiktok.com) OAuth2 Provider for Laravel Socialite", + "license": "MIT", + "authors": [ + { + "name": "Thomas Banks", + "email": "thomas@tombanks.me" + } + ], + "require": { + "php": "^7.2 || ^8.0", + "socialiteproviders/manager": "~4.0", + "laravel/socialite": "~4.0|~5.0", + "illuminate/support": "^6.0|^7.0|^8.0" + }, + "autoload": { + "psr-4": { + "SocialiteProviders\\TikTok\\": "" + } + } +}