laravel-6 support

This commit is contained in:
RafficMohammed
2023-01-08 01:17:22 +05:30
parent 1a5c16ae4b
commit 774eed8b0e
4962 changed files with 279380 additions and 297961 deletions

View File

@@ -1,7 +1,7 @@
<p align="center"><img src="https://laravel.com/assets/img/components/logo-socialite.svg"></p>
<p align="center">
<a href="https://travis-ci.org/laravel/socialite"><img src="https://travis-ci.org/laravel/socialite.svg" alt="Build Status"></a>
<a href="https://github.com/laravel/socialite/actions"><img src="https://github.com/laravel/socialite/workflows/tests/badge.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/laravel/socialite"><img src="https://poser.pugx.org/laravel/socialite/d/total.svg" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/laravel/socialite"><img src="https://poser.pugx.org/laravel/socialite/v/stable.svg" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/laravel/socialite"><img src="https://poser.pugx.org/laravel/socialite/license.svg" alt="License"></a>
@@ -9,18 +9,28 @@
## Introduction
Laravel Socialite provides an expressive, fluent interface to OAuth authentication with Facebook, Twitter, Google, LinkedIn, GitHub and Bitbucket. It handles almost all of the boilerplate social authentication code you are dreading writing.
Laravel Socialite provides an expressive, fluent interface to OAuth authentication with Facebook, Twitter, Google, LinkedIn, GitHub, GitLab and Bitbucket. It handles almost all of the boilerplate social authentication code you are dreading writing.
**We are not accepting new adapters.**
**If you are using Laravel 5.3 or below, please use [Socialite 2.0](https://github.com/laravel/socialite/tree/2.0).**
Adapters for other platforms are listed at the community driven [Socialite Providers](https://socialiteproviders.github.io/) website.
Adapters for other platforms are listed at the community driven [Socialite Providers](https://socialiteproviders.netlify.com/) website.
## Official Documentation
Documentation for Socialite can be found on the [Laravel website](http://laravel.com/docs/socialite).
Documentation for Socialite can be found on the [Laravel website](https://laravel.com/docs/socialite).
## Contributing
Thank you for considering contributing to Socialite! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
## Code of Conduct
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
## Security Vulnerabilities
Please review [our security policy](https://github.com/laravel/socialite/security/policy) on how to report security vulnerabilities.
## License
Laravel Socialite is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
Laravel Socialite is open-sourced software licensed under the [MIT license](LICENSE.md).

View File

@@ -3,6 +3,11 @@
"description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.",
"keywords": ["oauth", "laravel"],
"license": "MIT",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/socialite/issues",
"source": "https://github.com/laravel/socialite"
},
"authors": [
{
"name": "Taylor Otwell",
@@ -10,16 +15,18 @@
}
],
"require": {
"php": ">=5.4.0",
"guzzlehttp/guzzle": "~6.0",
"illuminate/contracts": "~5.4",
"illuminate/http": "~5.4",
"illuminate/support": "~5.4",
"league/oauth1-client": "~1.0"
"php": "^7.1.3",
"ext-json": "*",
"guzzlehttp/guzzle": "^6.0|^7.0",
"illuminate/http": "~5.7.0|~5.8.0|^6.0|^7.0",
"illuminate/support": "~5.7.0|~5.8.0|^6.0|^7.0",
"league/oauth1-client": "^1.0"
},
"require-dev": {
"mockery/mockery": "~0.9",
"phpunit/phpunit": "~4.0|~5.0"
"illuminate/contracts": "~5.7.0|~5.8.0|^6.0|^7.0",
"mockery/mockery": "^1.0",
"orchestra/testbench": "^3.7|^3.8|^4.0|^5.0",
"phpunit/phpunit": "^7.0|^8.0"
},
"autoload": {
"psr-4": {
@@ -28,12 +35,12 @@
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
"Laravel\\Socialite\\Tests\\": "tests/"
}
},
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
"dev-master": "4.x-dev"
},
"laravel": {
"providers": [

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
syntaxCheck="true"
verbose="true"
>
<testsuites>
<testsuite name="Package Test Suite">
<directory suffix=".php">./tests/</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@@ -3,8 +3,9 @@
namespace Laravel\Socialite;
use ArrayAccess;
use Laravel\Socialite\Contracts\User;
abstract class AbstractUser implements ArrayAccess, Contracts\User
abstract class AbstractUser implements ArrayAccess, User
{
/**
* The unique identifier for the user.

View File

@@ -6,6 +6,7 @@ use Illuminate\Support\Facades\Facade;
use Laravel\Socialite\Contracts\Factory;
/**
* @method static \Laravel\Socialite\Contracts\Provider driver(string $driver = null)
* @see \Laravel\Socialite\SocialiteManager
*/
class Socialite extends Facade

View File

@@ -2,12 +2,12 @@
namespace Laravel\Socialite\One;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use InvalidArgumentException;
use Illuminate\Http\RedirectResponse;
use League\OAuth1\Client\Server\Server;
use League\OAuth1\Client\Credentials\TokenCredentials;
use Laravel\Socialite\Contracts\Provider as ProviderContract;
use League\OAuth1\Client\Credentials\TokenCredentials;
use League\OAuth1\Client\Server\Server;
abstract class AbstractProvider implements ProviderContract
{
@@ -25,6 +25,13 @@ abstract class AbstractProvider implements ProviderContract
*/
protected $server;
/**
* A hash representing the last requested user.
*
* @var string
*/
protected $userHash;
/**
* Create a new provider instance.
*
@@ -55,8 +62,9 @@ abstract class AbstractProvider implements ProviderContract
/**
* Get the User instance for the authenticated user.
*
* @throws \InvalidArgumentException
* @return \Laravel\Socialite\One\User
*
* @throws \InvalidArgumentException
*/
public function user()
{
@@ -64,14 +72,21 @@ abstract class AbstractProvider implements ProviderContract
throw new InvalidArgumentException('Invalid request. Missing OAuth verifier.');
}
$user = $this->server->getUserDetails($token = $this->getToken());
$token = $this->getToken();
$user = $this->server->getUserDetails(
$token, $this->shouldBypassCache($token->getIdentifier(), $token->getSecret())
);
$instance = (new User)->setRaw($user->extra)
->setToken($token->getIdentifier(), $token->getSecret());
return $instance->map([
'id' => $user->uid, 'nickname' => $user->nickname,
'name' => $user->name, 'email' => $user->email, 'avatar' => $user->imageUrl,
'id' => $user->uid,
'nickname' => $user->nickname,
'name' => $user->name,
'email' => $user->email,
'avatar' => $user->imageUrl,
]);
}
@@ -89,14 +104,19 @@ abstract class AbstractProvider implements ProviderContract
$tokenCredentials->setIdentifier($token);
$tokenCredentials->setSecret($secret);
$user = $this->server->getUserDetails($tokenCredentials);
$user = $this->server->getUserDetails(
$tokenCredentials, $this->shouldBypassCache($token, $secret)
);
$instance = (new User)->setRaw($user->extra)
->setToken($tokenCredentials->getIdentifier(), $tokenCredentials->getSecret());
return $instance->map([
'id' => $user->uid, 'nickname' => $user->nickname,
'name' => $user->name, 'email' => $user->email, 'avatar' => $user->imageUrl,
'id' => $user->uid,
'nickname' => $user->nickname,
'name' => $user->name,
'email' => $user->email,
'avatar' => $user->imageUrl,
]);
}
@@ -124,6 +144,28 @@ abstract class AbstractProvider implements ProviderContract
return $this->request->has('oauth_token') && $this->request->has('oauth_verifier');
}
/**
* Determine if the user information cache should be bypassed.
*
* @param string $token
* @param string $secret
* @return bool
*/
protected function shouldBypassCache($token, $secret)
{
$newHash = sha1($token.'_'.$secret);
if (! empty($this->userHash) && $newHash !== $this->userHash) {
$this->userHash = $newHash;
return true;
}
$this->userHash = $this->userHash ?: $newHash;
return false;
}
/**
* Set the request instance.
*

View File

@@ -15,7 +15,7 @@ class TwitterProvider extends AbstractProvider
throw new InvalidArgumentException('Invalid request. Missing OAuth verifier.');
}
$user = $this->server->getUserDetails($token = $this->getToken());
$user = $this->server->getUserDetails($token = $this->getToken(), $this->shouldBypassCache($token->getIdentifier(), $token->getSecret()));
$extraDetails = [
'location' => $user->location,
@@ -26,8 +26,11 @@ class TwitterProvider extends AbstractProvider
->setToken($token->getIdentifier(), $token->getSecret());
return $instance->map([
'id' => $user->uid, 'nickname' => $user->nickname,
'name' => $user->name, 'email' => $user->email, 'avatar' => $user->imageUrl,
'id' => $user->uid,
'nickname' => $user->nickname,
'name' => $user->name,
'email' => $user->email,
'avatar' => $user->imageUrl,
'avatar_original' => str_replace('_normal', '', $user->imageUrl),
]);
}

View File

@@ -3,15 +3,16 @@
namespace Laravel\Socialite;
use Illuminate\Support\Arr;
use Illuminate\Support\Manager;
use Illuminate\Support\Str;
use InvalidArgumentException;
use Illuminate\Support\Manager;
use Laravel\Socialite\Two\GithubProvider;
use Laravel\Socialite\Two\GoogleProvider;
use Laravel\Socialite\One\TwitterProvider;
use Laravel\Socialite\Two\FacebookProvider;
use Laravel\Socialite\Two\LinkedInProvider;
use Laravel\Socialite\Two\BitbucketProvider;
use Laravel\Socialite\Two\FacebookProvider;
use Laravel\Socialite\Two\GithubProvider;
use Laravel\Socialite\Two\GitlabProvider;
use Laravel\Socialite\Two\GoogleProvider;
use Laravel\Socialite\Two\LinkedInProvider;
use League\OAuth1\Client\Server\Twitter as TwitterServer;
class SocialiteManager extends Manager implements Contracts\Factory
@@ -34,7 +35,7 @@ class SocialiteManager extends Manager implements Contracts\Factory
*/
protected function createGithubDriver()
{
$config = $this->app['config']['services.github'];
$config = $this->app->make('config')['services.github'];
return $this->buildProvider(
GithubProvider::class, $config
@@ -48,7 +49,7 @@ class SocialiteManager extends Manager implements Contracts\Factory
*/
protected function createFacebookDriver()
{
$config = $this->app['config']['services.facebook'];
$config = $this->app->make('config')['services.facebook'];
return $this->buildProvider(
FacebookProvider::class, $config
@@ -62,7 +63,7 @@ class SocialiteManager extends Manager implements Contracts\Factory
*/
protected function createGoogleDriver()
{
$config = $this->app['config']['services.google'];
$config = $this->app->make('config')['services.google'];
return $this->buildProvider(
GoogleProvider::class, $config
@@ -76,7 +77,7 @@ class SocialiteManager extends Manager implements Contracts\Factory
*/
protected function createLinkedinDriver()
{
$config = $this->app['config']['services.linkedin'];
$config = $this->app->make('config')['services.linkedin'];
return $this->buildProvider(
LinkedInProvider::class, $config
@@ -90,13 +91,27 @@ class SocialiteManager extends Manager implements Contracts\Factory
*/
protected function createBitbucketDriver()
{
$config = $this->app['config']['services.bitbucket'];
$config = $this->app->make('config')['services.bitbucket'];
return $this->buildProvider(
BitbucketProvider::class, $config
);
}
/**
* Create an instance of the specified driver.
*
* @return \Laravel\Socialite\Two\AbstractProvider
*/
protected function createGitlabDriver()
{
$config = $this->app->make('config')['services.gitlab'];
return $this->buildProvider(
GitlabProvider::class, $config
);
}
/**
* Build an OAuth 2 provider instance.
*
@@ -107,7 +122,7 @@ class SocialiteManager extends Manager implements Contracts\Factory
public function buildProvider($provider, $config)
{
return new $provider(
$this->app['request'], $config['client_id'],
$this->app->make('request'), $config['client_id'],
$config['client_secret'], $this->formatRedirectUrl($config),
Arr::get($config, 'guzzle', [])
);
@@ -120,10 +135,10 @@ class SocialiteManager extends Manager implements Contracts\Factory
*/
protected function createTwitterDriver()
{
$config = $this->app['config']['services.twitter'];
$config = $this->app->make('config')['services.twitter'];
return new TwitterProvider(
$this->app['request'], new TwitterServer($this->formatConfig($config))
$this->app->make('request'), new TwitterServer($this->formatConfig($config))
);
}
@@ -153,16 +168,16 @@ class SocialiteManager extends Manager implements Contracts\Factory
$redirect = value($config['redirect']);
return Str::startsWith($redirect, '/')
? $this->app['url']->to($redirect)
? $this->app->make('url')->to($redirect)
: $redirect;
}
/**
* Get the default driver name.
*
* @throws \InvalidArgumentException
*
* @return string
*
* @throws \InvalidArgumentException
*/
public function getDefaultDriver()
{

View File

@@ -7,13 +7,6 @@ use Laravel\Socialite\Contracts\Factory;
class SocialiteServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = true;
/**
* Register the service provider.
*
@@ -35,4 +28,14 @@ class SocialiteServiceProvider extends ServiceProvider
{
return [Factory::class];
}
/**
* Determine if the provider is deferred.
*
* @return bool
*/
public function isDeferred()
{
return true;
}
}

View File

@@ -3,11 +3,10 @@
namespace Laravel\Socialite\Two;
use GuzzleHttp\Client;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use GuzzleHttp\ClientInterface;
use Illuminate\Http\RedirectResponse;
use Laravel\Socialite\Contracts\Provider as ProviderContract;
abstract class AbstractProvider implements ProviderContract
@@ -156,7 +155,7 @@ abstract class AbstractProvider implements ProviderContract
}
/**
* Get the authentication URL for the provider.
* Build the authentication URL for the provider from the given base URL.
*
* @param string $url
* @param string $state
@@ -176,7 +175,8 @@ abstract class AbstractProvider implements ProviderContract
protected function getCodeFields($state = null)
{
$fields = [
'client_id' => $this->clientId, 'redirect_uri' => $this->redirectUrl,
'client_id' => $this->clientId,
'redirect_uri' => $this->redirectUrl,
'scope' => $this->formatScopes($this->getScopes(), $this->scopeSeparator),
'response_type' => 'code',
];
@@ -257,11 +257,9 @@ abstract class AbstractProvider implements ProviderContract
*/
public function getAccessTokenResponse($code)
{
$postKey = (version_compare(ClientInterface::VERSION, '6') === 1) ? 'form_params' : 'body';
$response = $this->getHttpClient()->post($this->getTokenUrl(), [
'headers' => ['Accept' => 'application/json'],
$postKey => $this->getTokenFields($code),
'form_params' => $this->getTokenFields($code),
]);
return json_decode($response->getBody(), true);
@@ -276,8 +274,10 @@ abstract class AbstractProvider implements ProviderContract
protected function getTokenFields($code)
{
return [
'client_id' => $this->clientId, 'client_secret' => $this->clientSecret,
'code' => $code, 'redirect_uri' => $this->redirectUrl,
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'code' => $code,
'redirect_uri' => $this->redirectUrl,
];
}

View File

@@ -3,7 +3,7 @@
namespace Laravel\Socialite\Two;
use Exception;
use GuzzleHttp\ClientInterface;
use Illuminate\Support\Arr;
class BitbucketProvider extends AbstractProvider implements ProviderInterface
{
@@ -86,9 +86,11 @@ class BitbucketProvider extends AbstractProvider implements ProviderInterface
protected function mapUserToObject(array $user)
{
return (new User)->setRaw($user)->map([
'id' => $user['uuid'], 'nickname' => $user['username'],
'name' => array_get($user, 'display_name'), 'email' => array_get($user, 'email'),
'avatar' => array_get($user, 'links.avatar.href'),
'id' => $user['uuid'],
'nickname' => $user['username'],
'name' => Arr::get($user, 'display_name'),
'email' => Arr::get($user, 'email'),
'avatar' => Arr::get($user, 'links.avatar.href'),
]);
}
@@ -100,12 +102,10 @@ class BitbucketProvider extends AbstractProvider implements ProviderInterface
*/
public function getAccessToken($code)
{
$postKey = (version_compare(ClientInterface::VERSION, '6') === 1) ? 'form_params' : 'body';
$response = $this->getHttpClient()->post($this->getTokenUrl(), [
'auth' => [$this->clientId, $this->clientSecret],
'headers' => ['Accept' => 'application/json'],
$postKey => $this->getTokenFields($code),
'form_params' => $this->getTokenFields($code),
]);
return json_decode($response->getBody(), true)['access_token'];

View File

@@ -3,7 +3,6 @@
namespace Laravel\Socialite\Two;
use Illuminate\Support\Arr;
use GuzzleHttp\ClientInterface;
class FacebookProvider extends AbstractProvider implements ProviderInterface
{
@@ -19,7 +18,7 @@ class FacebookProvider extends AbstractProvider implements ProviderInterface
*
* @var string
*/
protected $version = 'v3.0';
protected $version = 'v3.3';
/**
* The user fields being requested.
@@ -70,14 +69,10 @@ class FacebookProvider extends AbstractProvider implements ProviderInterface
*/
public function getAccessTokenResponse($code)
{
$postKey = (version_compare(ClientInterface::VERSION, '6') === 1) ? 'form_params' : 'body';
$response = $this->getHttpClient()->post($this->getTokenUrl(), [
$postKey => $this->getTokenFields($code),
'form_params' => $this->getTokenFields($code),
]);
$data = [];
$data = json_decode($response->getBody(), true);
return Arr::add($data, 'expires_in', Arr::pull($data, 'expires'));
@@ -113,10 +108,13 @@ class FacebookProvider extends AbstractProvider implements ProviderInterface
$avatarUrl = $this->graphUrl.'/'.$this->version.'/'.$user['id'].'/picture';
return (new User)->setRaw($user)->map([
'id' => $user['id'], 'nickname' => null, 'name' => isset($user['name']) ? $user['name'] : null,
'email' => isset($user['email']) ? $user['email'] : null, 'avatar' => $avatarUrl.'?type=normal',
'id' => $user['id'],
'nickname' => null,
'name' => $user['name'] ?? null,
'email' => $user['email'] ?? null,
'avatar' => $avatarUrl.'?type=normal',
'avatar_original' => $avatarUrl.'?width=1920',
'profileUrl' => isset($user['link']) ? $user['link'] : null,
'profileUrl' => $user['link'] ?? null,
]);
}
@@ -174,4 +172,17 @@ class FacebookProvider extends AbstractProvider implements ProviderInterface
return $this;
}
/**
* Specify which graph version should be used.
*
* @param string $version
* @return $this
*/
public function usingGraphVersion(string $version)
{
$this->version = $version;
return $this;
}
}

View File

@@ -35,10 +35,10 @@ class GithubProvider extends AbstractProvider implements ProviderInterface
*/
protected function getUserByToken($token)
{
$userUrl = 'https://api.github.com/user?access_token='.$token;
$userUrl = 'https://api.github.com/user';
$response = $this->getHttpClient()->get(
$userUrl, $this->getRequestOptions()
$userUrl, $this->getRequestOptions($token)
);
$user = json_decode($response->getBody(), true);
@@ -58,11 +58,11 @@ class GithubProvider extends AbstractProvider implements ProviderInterface
*/
protected function getEmailByToken($token)
{
$emailsUrl = 'https://api.github.com/user/emails?access_token='.$token;
$emailsUrl = 'https://api.github.com/user/emails';
try {
$response = $this->getHttpClient()->get(
$emailsUrl, $this->getRequestOptions()
$emailsUrl, $this->getRequestOptions($token)
);
} catch (Exception $e) {
return;
@@ -81,21 +81,26 @@ class GithubProvider extends AbstractProvider implements ProviderInterface
protected function mapUserToObject(array $user)
{
return (new User)->setRaw($user)->map([
'id' => $user['id'], 'nickname' => $user['login'], 'name' => Arr::get($user, 'name'),
'email' => Arr::get($user, 'email'), 'avatar' => $user['avatar_url'],
'id' => $user['id'],
'nickname' => $user['login'],
'name' => Arr::get($user, 'name'),
'email' => Arr::get($user, 'email'),
'avatar' => $user['avatar_url'],
]);
}
/**
* Get the default options for an HTTP request.
*
* @param string $token
* @return array
*/
protected function getRequestOptions()
protected function getRequestOptions($token)
{
return [
'headers' => [
'Accept' => 'application/vnd.github.v3+json',
'Authorization' => 'token '.$token,
],
];
}

View File

@@ -0,0 +1,58 @@
<?php
namespace Laravel\Socialite\Two;
class GitlabProvider extends AbstractProvider implements ProviderInterface
{
/**
* {@inheritdoc}
*/
protected function getAuthUrl($state)
{
return $this->buildAuthUrlFromBase('https://gitlab.com/oauth/authorize', $state);
}
/**
* {@inheritdoc}
*/
protected function getTokenUrl()
{
return 'https://gitlab.com/oauth/token';
}
/**
* {@inheritdoc}
*/
protected function getUserByToken($token)
{
$userUrl = 'https://gitlab.com/api/v3/user?access_token='.$token;
$response = $this->getHttpClient()->get($userUrl);
$user = json_decode($response->getBody(), true);
return $user;
}
/**
* {@inheritdoc}
*/
protected function mapUserToObject(array $user)
{
return (new User)->setRaw($user)->map([
'id' => $user['id'],
'nickname' => $user['username'],
'name' => $user['name'],
'email' => $user['email'],
'avatar' => $user['avatar_url'],
]);
}
/**
* {@inheritdoc}
*/
protected function getTokenFields($code)
{
return parent::getTokenFields($code) + ['grant_type' => 'authorization_code'];
}
}

View File

@@ -37,7 +37,7 @@ class GoogleProvider extends AbstractProvider implements ProviderInterface
*/
protected function getTokenUrl()
{
return 'https://accounts.google.com/o/oauth2/token';
return 'https://www.googleapis.com/oauth2/v4/token';
}
/**
@@ -48,7 +48,7 @@ class GoogleProvider extends AbstractProvider implements ProviderInterface
*/
protected function getTokenFields($code)
{
return array_add(
return Arr::add(
parent::getTokenFields($code), 'grant_type', 'authorization_code'
);
}
@@ -58,7 +58,7 @@ class GoogleProvider extends AbstractProvider implements ProviderInterface
*/
protected function getUserByToken($token)
{
$response = $this->getHttpClient()->get('https://www.googleapis.com/plus/v1/people/me?', [
$response = $this->getHttpClient()->get('https://www.googleapis.com/oauth2/v3/userinfo', [
'query' => [
'prettyPrint' => 'false',
],
@@ -76,10 +76,18 @@ class GoogleProvider extends AbstractProvider implements ProviderInterface
*/
protected function mapUserToObject(array $user)
{
// Deprecated: Fields added to keep backwards compatibility in 4.0. These will be removed in 5.0
$user['id'] = Arr::get($user, 'sub');
$user['verified_email'] = Arr::get($user, 'email_verified');
$user['link'] = Arr::get($user, 'profile');
return (new User)->setRaw($user)->map([
'id' => $user['id'], 'nickname' => Arr::get($user, 'nickname'), 'name' => $user['displayName'],
'email' => $user['emails'][0]['value'], 'avatar' => Arr::get($user, 'image')['url'],
'avatar_original' => preg_replace('/\?sz=([0-9]+)/', '', Arr::get($user, 'image')['url']),
'id' => Arr::get($user, 'sub'),
'nickname' => Arr::get($user, 'nickname'),
'name' => Arr::get($user, 'name'),
'email' => Arr::get($user, 'email'),
'avatar' => $avatarUrl = Arr::get($user, 'picture'),
'avatar_original' => $avatarUrl,
]);
}
}

View File

@@ -11,7 +11,7 @@ class LinkedInProvider extends AbstractProvider implements ProviderInterface
*
* @var array
*/
protected $scopes = ['r_basicprofile', 'r_emailaddress'];
protected $scopes = ['r_liteprofile', 'r_emailaddress'];
/**
* The separating character for the requested scopes.
@@ -20,17 +20,6 @@ class LinkedInProvider extends AbstractProvider implements ProviderInterface
*/
protected $scopeSeparator = ' ';
/**
* The fields that are included in the profile.
*
* @var array
*/
protected $fields = [
'id', 'first-name', 'last-name', 'formatted-name',
'email-address', 'headline', 'location', 'industry',
'public-profile-url', 'picture-url', 'picture-urls::(original)',
];
/**
* {@inheritdoc}
*/
@@ -63,18 +52,50 @@ class LinkedInProvider extends AbstractProvider implements ProviderInterface
*/
protected function getUserByToken($token)
{
$fields = implode(',', $this->fields);
$basicProfile = $this->getBasicProfile($token);
$emailAddress = $this->getEmailAddress($token);
$url = 'https://api.linkedin.com/v1/people/~:('.$fields.')';
return array_merge($basicProfile, $emailAddress);
}
/**
* Get the basic profile fields for the user.
*
* @param string $token
* @return array
*/
protected function getBasicProfile($token)
{
$url = 'https://api.linkedin.com/v2/me?projection=(id,firstName,lastName,profilePicture(displayImage~:playableStreams))';
$response = $this->getHttpClient()->get($url, [
'headers' => [
'x-li-format' => 'json',
'Authorization' => 'Bearer '.$token,
'X-RestLi-Protocol-Version' => '2.0.0',
],
]);
return json_decode($response->getBody(), true);
return (array) json_decode($response->getBody(), true);
}
/**
* Get the email address for the user.
*
* @param string $token
* @return array
*/
protected function getEmailAddress($token)
{
$url = 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))';
$response = $this->getHttpClient()->get($url, [
'headers' => [
'Authorization' => 'Bearer '.$token,
'X-RestLi-Protocol-Version' => '2.0.0',
],
]);
return (array) Arr::get((array) json_decode($response->getBody(), true), 'elements.0.handle~');
}
/**
@@ -82,23 +103,27 @@ class LinkedInProvider extends AbstractProvider implements ProviderInterface
*/
protected function mapUserToObject(array $user)
{
$preferredLocale = Arr::get($user, 'firstName.preferredLocale.language').'_'.Arr::get($user, 'firstName.preferredLocale.country');
$firstName = Arr::get($user, 'firstName.localized.'.$preferredLocale);
$lastName = Arr::get($user, 'lastName.localized.'.$preferredLocale);
$images = (array) Arr::get($user, 'profilePicture.displayImage~.elements', []);
$avatar = Arr::first($images, function ($image) {
return $image['data']['com.linkedin.digitalmedia.mediaartifact.StillImage']['storageSize']['width'] === 100;
});
$originalAvatar = Arr::first($images, function ($image) {
return $image['data']['com.linkedin.digitalmedia.mediaartifact.StillImage']['storageSize']['width'] === 800;
});
return (new User)->setRaw($user)->map([
'id' => $user['id'], 'nickname' => null, 'name' => Arr::get($user, 'formattedName'),
'email' => Arr::get($user, 'emailAddress'), 'avatar' => Arr::get($user, 'pictureUrl'),
'avatar_original' => Arr::get($user, 'pictureUrls.values.0'),
'id' => $user['id'],
'nickname' => null,
'name' => $firstName.' '.$lastName,
'first_name' => $firstName,
'last_name' => $lastName,
'email' => Arr::get($user, 'emailAddress'),
'avatar' => Arr::get($avatar, 'identifiers.0.identifier'),
'avatar_original' => Arr::get($originalAvatar, 'identifiers.0.identifier'),
]);
}
/**
* Set the user fields to request from LinkedIn.
*
* @param array $fields
* @return $this
*/
public function fields(array $fields)
{
$this->fields = $fields;
return $this;
}
}