parent
598f2f8024
commit
d74b76da3e
@ -1,76 +0,0 @@ |
||||
<?php namespace AdamWathan\EloquentOAuth; |
||||
|
||||
class Authenticator |
||||
{ |
||||
protected $auth; |
||||
protected $users; |
||||
protected $identities; |
||||
|
||||
public function __construct($auth, $users, $identities) |
||||
{ |
||||
$this->auth = $auth; |
||||
$this->users = $users; |
||||
$this->identities = $identities; |
||||
} |
||||
|
||||
public function login($providerAlias, $userDetails, $callback = null, $remember = false) |
||||
{ |
||||
$user = $this->getUser($providerAlias, $userDetails); |
||||
$user = $this->runCallback($callback, $user, $userDetails); |
||||
$this->updateUser($user, $providerAlias, $userDetails); |
||||
$this->auth->login($user, $remember); |
||||
} |
||||
|
||||
protected function getUser($providerAlias, $details) |
||||
{ |
||||
if ($this->identities->userExists($providerAlias, $details)) { |
||||
return $this->getExistingUser($providerAlias, $details); |
||||
} |
||||
return $this->users->create(); |
||||
} |
||||
|
||||
protected function runCallback($callback, $user, $userDetails) |
||||
{ |
||||
$callback = $callback ?: function () {}; |
||||
$callbackUser = $callback($user, $userDetails); |
||||
return $callbackUser ?: $user; |
||||
} |
||||
|
||||
protected function updateUser($user, $providerAlias, $details) |
||||
{ |
||||
$this->users->store($user); |
||||
$this->storeProviderIdentity($user, $providerAlias, $details); |
||||
} |
||||
|
||||
protected function getExistingUser($providerAlias, $details) |
||||
{ |
||||
$identity = $this->identities->getByProvider($providerAlias, $details); |
||||
return $this->users->findByIdentity($identity); |
||||
} |
||||
|
||||
protected function storeProviderIdentity($user, $providerAlias, $details) |
||||
{ |
||||
if ($this->identities->userExists($providerAlias, $details)) { |
||||
$this->updateProviderIdentity($providerAlias, $details); |
||||
} else { |
||||
$this->addProviderIdentity($user, $providerAlias, $details); |
||||
} |
||||
} |
||||
|
||||
protected function updateProviderIdentity($providerAlias, $details) |
||||
{ |
||||
$identity = $this->identities->getByProvider($providerAlias, $details); |
||||
$identity->access_token = $details->access_token; |
||||
$this->identities->store($identity); |
||||
} |
||||
|
||||
protected function addProviderIdentity($user, $providerAlias, $details) |
||||
{ |
||||
$identity = new OAuthIdentity; |
||||
$identity->user_id = $user->getKey(); |
||||
$identity->provider = $providerAlias; |
||||
$identity->provider_user_id = $details->id; |
||||
$identity->access_token = $details->access_token; |
||||
$this->identities->store($identity); |
||||
} |
||||
} |
@ -1,28 +0,0 @@ |
||||
<?php namespace AdamWathan\EloquentOAuth; |
||||
|
||||
class EloquentIdentityStore implements IdentityStore |
||||
{ |
||||
public function getByProvider($provider, $providerUser) |
||||
{ |
||||
return OAuthIdentity::where('provider', $provider) |
||||
->where('provider_user_id', $providerUser->id) |
||||
->first(); |
||||
} |
||||
|
||||
public function flush($user, $provider) |
||||
{ |
||||
OAuthIdentity::where('user_id', $user->getKey()) |
||||
->where('provider', $provider) |
||||
->delete(); |
||||
} |
||||
|
||||
public function store($identity) |
||||
{ |
||||
$identity->save(); |
||||
} |
||||
|
||||
public function userExists($provider, $providerUser) |
||||
{ |
||||
return (bool) $this->getByProvider($provider, $providerUser); |
||||
} |
||||
} |
@ -1,11 +0,0 @@ |
||||
<?php namespace AdamWathan\EloquentOAuth\Facades; |
||||
|
||||
use Illuminate\Support\Facades\Facade; |
||||
|
||||
class OAuth extends Facade |
||||
{ |
||||
protected static function getFacadeAccessor() |
||||
{ |
||||
return 'adamwathan.oauth'; |
||||
} |
||||
} |
@ -1,9 +0,0 @@ |
||||
<?php namespace AdamWathan\EloquentOAuth; |
||||
|
||||
interface IdentityStore |
||||
{ |
||||
public function getByProvider($provider, $providerUser); |
||||
public function flush($user, $provider); |
||||
public function store($identity); |
||||
public function userExists($provider, $providerUser); |
||||
} |
@ -1,26 +0,0 @@ |
||||
<?php namespace AdamWathan\EloquentOAuth; |
||||
|
||||
use Illuminate\Database\Eloquent\Model as Eloquent; |
||||
use Config; |
||||
|
||||
/** |
||||
* @property $id |
||||
* @property $user_id |
||||
* @property $provider |
||||
* @property $provider_user_id |
||||
* @property $access_token |
||||
*/ |
||||
class OAuthIdentity extends Eloquent |
||||
{ |
||||
protected static $configuredTable = 'oauth_identities'; |
||||
|
||||
public static function configureTable($table) |
||||
{ |
||||
static::$configuredTable = $table; |
||||
} |
||||
|
||||
public function getTable() |
||||
{ |
||||
return static::$configuredTable; |
||||
} |
||||
} |
@ -1,37 +0,0 @@ |
||||
<?php namespace AdamWathan\EloquentOAuth; |
||||
|
||||
class OAuthManager |
||||
{ |
||||
protected $redirect; |
||||
protected $authenticator; |
||||
protected $socialnorm; |
||||
|
||||
public function __construct($redirect, $authenticator, $socialnorm) |
||||
{ |
||||
$this->redirect = $redirect; |
||||
$this->authenticator = $authenticator; |
||||
$this->socialnorm = $socialnorm; |
||||
} |
||||
|
||||
public function authorize($providerAlias) |
||||
{ |
||||
return $this->redirect->to($this->socialnorm->authorize($providerAlias)); |
||||
} |
||||
|
||||
public function login($providerAlias, $callback = null) |
||||
{ |
||||
$details = $this->socialnorm->getUser($providerAlias); |
||||
return $this->authenticator->login($providerAlias, $details, $callback, $remember = false); |
||||
} |
||||
|
||||
public function loginForever($providerAlias, $callback = null) |
||||
{ |
||||
$details = $this->socialnorm->getUser($providerAlias); |
||||
return $this->authenticator->login($providerAlias, $details, $callback, $remember = true); |
||||
} |
||||
|
||||
public function registerProvider($alias, $provider) |
||||
{ |
||||
$this->socialnorm->registerProvider($alias, $provider); |
||||
} |
||||
} |
@ -1,23 +0,0 @@ |
||||
<?php namespace AdamWathan\EloquentOAuth; |
||||
|
||||
use SocialNorm\Session as SocialNormSession; |
||||
|
||||
class Session implements SocialNormSession |
||||
{ |
||||
private $store; |
||||
|
||||
public function __construct($store) |
||||
{ |
||||
$this->store = $store; |
||||
} |
||||
|
||||
public function get($key) |
||||
{ |
||||
return $this->store->get($key); |
||||
} |
||||
|
||||
public function put($key, $value) |
||||
{ |
||||
return $this->store->put($key, $value); |
||||
} |
||||
} |
@ -1,27 +0,0 @@ |
||||
<?php namespace AdamWathan\EloquentOAuth; |
||||
|
||||
class UserStore |
||||
{ |
||||
protected $model; |
||||
|
||||
public function __construct($model) |
||||
{ |
||||
$this->model = $model; |
||||
} |
||||
|
||||
public function create() |
||||
{ |
||||
$user = new $this->model; |
||||
return $user; |
||||
} |
||||
|
||||
public function store($user) |
||||
{ |
||||
return $user->save(); |
||||
} |
||||
|
||||
public function findByIdentity($identity) |
||||
{ |
||||
return $identity->belongsTo($this->model, 'user_id')->firstOrFail(); |
||||
} |
||||
} |
@ -1,28 +1,58 @@ |
||||
<?php namespace AdamWathan\EloquentOAuth; |
||||
<?php |
||||
namespace AdamWathan\EloquentOAuth; |
||||
|
||||
use App\Models\User; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
use SocialNorm\ProviderUser; |
||||
|
||||
class EloquentIdentityStore implements IdentityStore |
||||
{ |
||||
public function getByProvider($provider, $providerUser) |
||||
public function getByProvider(string $provider, ProviderUser $providerUser) |
||||
{ |
||||
return OAuthIdentity::where('provider', $provider) |
||||
->where('provider_user_id', $providerUser->id) |
||||
->first(); |
||||
} |
||||
|
||||
public function flush($user, $provider) |
||||
/** |
||||
* Try to retrieve user by their e-mail |
||||
* (!!! this is coupled to the application code !!!) |
||||
* |
||||
* @param ProviderUser $providerUser |
||||
* @return User|Model|null|object |
||||
*/ |
||||
public function getByEmail(ProviderUser $providerUser) |
||||
{ |
||||
$first = User::where('email', $providerUser->email)->first(); |
||||
|
||||
if($first->email) return $first; |
||||
return null; |
||||
} |
||||
|
||||
public function flush(Model $user, string $provider) |
||||
{ |
||||
OAuthIdentity::where('user_id', $user->getKey()) |
||||
->where('provider', $provider) |
||||
->delete(); |
||||
} |
||||
|
||||
public function store($identity) |
||||
public function store(OAuthIdentity $identity) |
||||
{ |
||||
$identity->save(); |
||||
} |
||||
|
||||
public function userExists($provider, $providerUser) |
||||
public function userExists(string $provider, ProviderUser $providerUser, bool $allowByEmail) |
||||
{ |
||||
return (bool) $this->getByProvider($provider, $providerUser); |
||||
$byProvider = (bool) $this->getByProvider($provider, $providerUser); |
||||
if ($byProvider) return true; |
||||
|
||||
if (!$allowByEmail) return false; |
||||
|
||||
if ($providerUser->email) { |
||||
$byEmail = $this->getByEmail($providerUser); |
||||
if ($byEmail) return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
} |
||||
|
@ -1,9 +1,13 @@ |
||||
<?php namespace AdamWathan\EloquentOAuth; |
||||
|
||||
use Illuminate\Database\Eloquent\Model; |
||||
use SocialNorm\ProviderUser; |
||||
|
||||
interface IdentityStore |
||||
{ |
||||
public function getByProvider($provider, $providerUser); |
||||
public function flush($user, $provider); |
||||
public function store($identity); |
||||
public function userExists($provider, $providerUser); |
||||
public function getByProvider(string $provider, ProviderUser $providerUser); |
||||
public function flush(Model $user, string $provider); |
||||
public function getByEmail(ProviderUser $providerUser); |
||||
public function store(OAuthIdentity $identity); |
||||
public function userExists(string $provider, ProviderUser $providerUser, bool $allowByEmail); |
||||
} |
||||
|
@ -1,27 +1,35 @@ |
||||
<?php namespace AdamWathan\EloquentOAuth; |
||||
|
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class UserStore |
||||
{ |
||||
protected $model; |
||||
/** @var string */ |
||||
protected $modelClass; |
||||
|
||||
public function __construct($model) |
||||
public function __construct(string $modelClass) |
||||
{ |
||||
$this->model = $model; |
||||
$this->modelClass = $modelClass; |
||||
} |
||||
|
||||
public function create() |
||||
{ |
||||
$user = new $this->model; |
||||
$user = new $this->modelClass; |
||||
return $user; |
||||
} |
||||
|
||||
public function store($user) |
||||
public function store(Model $user) |
||||
{ |
||||
return $user->save(); |
||||
} |
||||
|
||||
public function findByIdentity($identity) |
||||
public function findByIdentity(OAuthIdentity $identity) |
||||
{ |
||||
return $identity->belongsTo($this->modelClass, 'user_id')->firstOrFail(); |
||||
} |
||||
|
||||
public function findByEmail(string $email) |
||||
{ |
||||
return $identity->belongsTo($this->model, 'user_id')->firstOrFail(); |
||||
return $this->modelClass::where('email', $email)->firstOrFail(); |
||||
} |
||||
} |
||||
|
@ -1,14 +1,16 @@ |
||||
<?php namespace SocialNorm; |
||||
|
||||
/** |
||||
* @property-read string $accessToken |
||||
* @property-read string $access_token |
||||
* @property-read string $id |
||||
* @property-read string $nickname |
||||
* @property-read string $fullName |
||||
* @property-read string $imageUrl |
||||
* @property-read string $avatar |
||||
* @property-read string $email |
||||
* @property-read string $full_name |
||||
* @property-read array $raw |
||||
*/ |
||||
class User |
||||
class ProviderUser |
||||
{ |
||||
protected $access_token; |
||||
protected $id; |
@ -0,0 +1,4 @@ |
||||
/vendor |
||||
composer.phar |
||||
composer.lock |
||||
.DS_Store |
@ -0,0 +1,11 @@ |
||||
language: php |
||||
|
||||
php: |
||||
- 5.5 |
||||
- 5.6 |
||||
|
||||
before_script: |
||||
- curl -s http://getcomposer.org/installer | php |
||||
- php composer.phar install --dev |
||||
|
||||
script: phpunit |
@ -0,0 +1,29 @@ |
||||
{ |
||||
"name": "socialnorm/stackoverflow", |
||||
"description": "StackOverflow provider for SocialNorm", |
||||
"authors": [ |
||||
{ |
||||
"name": "MightyPork" |
||||
} |
||||
], |
||||
"license": "MIT", |
||||
"require": { |
||||
"php": ">=5.5.0", |
||||
"guzzlehttp/guzzle": "^6.0", |
||||
"socialnorm/socialnorm": "^0.2" |
||||
}, |
||||
"require-dev": { |
||||
"mockery/mockery": "~0.8", |
||||
"phpunit/phpunit": "^4.8" |
||||
}, |
||||
"autoload": { |
||||
"psr-4": { |
||||
"SocialNorm\\StackOverflow\\": "src/" |
||||
} |
||||
}, |
||||
"autoload-dev": { |
||||
"files": [ |
||||
"tests/TestCase.php" |
||||
] |
||||
} |
||||
} |
@ -0,0 +1,18 @@ |
||||
<?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" |
||||
stopOnFailure="false" |
||||
syntaxCheck="false" |
||||
> |
||||
<testsuites> |
||||
<testsuite name="Package Test Suite"> |
||||
<directory suffix="Test.php">./tests/</directory> |
||||
</testsuite> |
||||
</testsuites> |
||||
</phpunit> |
@ -0,0 +1,3 @@ |
||||
## SocialNorm Google Provider |
||||
|
||||
@todo: Add docs :) |
@ -0,0 +1,100 @@ |
||||
<?php namespace SocialNorm\StackOverflow; |
||||
|
||||
use SocialNorm\Providers\OAuth2Provider; |
||||
use GuzzleHttp\Client as HttpClient; |
||||
use SocialNorm\Request; |
||||
|
||||
// https://stackapps.com/apps/oauth/view/12789 |
||||
// https://api.stackexchange.com/docs/authentication |
||||
|
||||
// This is entirely untested; it might work, but since we don't get e-mail from it, |
||||
// it's use as an auth method is problematic. |
||||
class StackOverflowProvider extends OAuth2Provider |
||||
{ |
||||
protected $authorizeUrl = "https://stackoverflow.com/oauth"; |
||||
protected $accessTokenUrl = "https://stackoverflow.com/oauth/access_token"; |
||||
protected $userDataUrl = "https://api.stackexchange.com/2.2/me"; |
||||
protected $scope = []; |
||||
|
||||
private $key; |
||||
|
||||
protected $headers = [ |
||||
'authorize' => [], |
||||
'access_token' => [ |
||||
'Content-Type' => 'application/x-www-form-urlencoded' |
||||
], |
||||
'user_details' => [], |
||||
]; |
||||
|
||||
public function __construct(array $config, HttpClient $httpClient, Request $request) |
||||
{ |
||||
parent::__construct($config, $httpClient, $request); |
||||
$this->key = $config['key']; |
||||
} |
||||
|
||||
protected function compileScopes() |
||||
{ |
||||
return implode(' ', $this->scope); |
||||
} |
||||
|
||||
protected function getAuthorizeUrl() |
||||
{ |
||||
return $this->authorizeUrl; |
||||
} |
||||
|
||||
protected function getAccessTokenBaseUrl() |
||||
{ |
||||
return $this->accessTokenUrl; |
||||
} |
||||
|
||||
protected function getUserDataUrl() |
||||
{ |
||||
return $this->userDataUrl; |
||||
} |
||||
|
||||
protected function buildUserDataUrl() |
||||
{ |
||||
$url = $this->getUserDataUrl(); |
||||
|
||||
$url .= "?access_token=".$this->accessToken |
||||
. "&site=stackoverflow" |
||||
. "&key=".$this->key; |
||||
|
||||
return $url; |
||||
} |
||||
|
||||
protected function parseTokenResponse($response) |
||||
{ |
||||
return $this->parseJsonTokenResponse($response); |
||||
} |
||||
|
||||
protected function parseUserDataResponse($response) |
||||
{ |
||||
return json_decode($response, true); |
||||
} |
||||
|
||||
protected function userId() |
||||
{ |
||||
return array_get($this->providerUserData, 'items.0.account_id'); |
||||
} |
||||
|
||||
protected function nickname() |
||||
{ |
||||
return array_get($this->providerUserData, 'items.0.display_name'); |
||||
} |
||||
|
||||
protected function fullName() |
||||
{ |
||||
return array_get($this->providerUserData, 'items.0.display_name'); |
||||
} |
||||
|
||||
protected function avatar() |
||||
{ |
||||
return array_get($this->providerUserData, 'items.0.profile_image'); |
||||
} |
||||
|
||||
protected function email() |
||||
{ |
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,75 @@ |
||||
<?php |
||||
|
||||
use Mockery as M; |
||||
use SocialNorm\Google\GoogleProvider; |
||||
use SocialNorm\Request; |
||||
|
||||
use GuzzleHttp\HandlerStack; |
||||
use GuzzleHttp\Psr7\Response; |
||||
use GuzzleHttp\Handler\MockHandler; |
||||
use GuzzleHttp\Client as HttpClient; |
||||
|
||||
class GoogleProviderTest extends TestCase |
||||
{ |
||||
private function getStubbedHttpClient($fixtures = []) |
||||
{ |
||||
$mock = new MockHandler($this->createResponses($fixtures)); |
||||
$handler = HandlerStack::create($mock); |
||||
return new HttpClient(['handler' => $handler]); |
||||
} |
||||
|
||||
private function createResponses($fixtures) |
||||
{ |
||||
$responses = []; |
||||
foreach ($fixtures as $fixture) { |
||||
$response = require $fixture; |
||||
$responses[] = new Response($response['status'], $response['headers'], $response['body']); |
||||
} |
||||
|
||||
return $responses; |
||||
} |
||||
|
||||
/** @test */ |
||||
public function it_can_retrieve_a_normalized_user() |
||||
{ |
||||
$client = $this->getStubbedHttpClient([ |
||||
__DIR__ . '/_fixtures/google_accesstoken.php', |
||||
__DIR__ . '/_fixtures/google_user.php', |
||||
]); |
||||
|
||||
$provider = new GoogleProvider([ |
||||
'client_id' => 'abcdefgh', |
||||
'client_secret' => '12345678', |
||||
'redirect_uri' => 'http://example.com/login', |
||||
], $client, new Request(['code' => 'abc123'])); |
||||
|
||||
$user = $provider->getUser(); |
||||
|
||||
$this->assertEquals('103904294571447333816', $user->id); |
||||
$this->assertEquals('adam.wathan@example.com', $user->nickname); |
||||
$this->assertEquals('Adam Wathan', $user->full_name); |
||||
$this->assertEquals('adam.wathan@example.com', $user->email); |
||||
$this->assertEquals('https://lh3.googleusercontent.com/-w0_RpDnsIE4/AAAAAAAAAAI/AAAAAAAAAKM/NEiV3jig1HA/photo.jpg', $user->avatar); |
||||
$this->assertEquals('ya29.8xFOTYpQK48RgPH8KjQpSu9SrcANcOQx9JtRnEu52dNsXqai8VD4iY3nFzUBURWnAPeTPtPeIBNjIF', $user->access_token); |
||||
} |
||||
|
||||
/** |
||||
* @test |
||||
* @expectedException SocialNorm\Exceptions\ApplicationRejectedException |
||||
*/ |
||||
public function it_fails_to_retrieve_a_user_when_the_authorization_code_is_omitted() |
||||
{ |
||||
$client = $this->getStubbedHttpClient([ |
||||
__DIR__ . '/_fixtures/google_accesstoken.php', |
||||
__DIR__ . '/_fixtures/google_user.php', |
||||
]); |
||||
|
||||
$provider = new GoogleProvider([ |
||||
'client_id' => 'abcdefgh', |
||||
'client_secret' => '12345678', |
||||
'redirect_uri' => 'http://example.com/login', |
||||
], $client, new Request([])); |
||||
|
||||
$user = $provider->getUser(); |
||||
} |
||||
} |
@ -0,0 +1,12 @@ |
||||
<?php |
||||
|
||||
use Mockery as M; |
||||
|
||||
class TestCase extends PHPUnit_Framework_TestCase |
||||
{ |
||||
public function tearDown() |
||||
{ |
||||
M::close(); |
||||
parent::tearDown(); |
||||
} |
||||
} |
@ -0,0 +1,24 @@ |
||||
<?php |
||||
|
||||
return [ |
||||
'status' => 200, |
||||
'headers' => [ |
||||
'Content-Type' => 'application/json; charset=utf-8', |
||||
'Cache-Control' => 'no-cache, no-store, max-age=0, must-revalidate', |
||||
'Pragma' => 'no-cache', |
||||
'Expires' => 'Fri, 01 Jan 1990 00:00:00 GMT', |
||||
'Date' => 'Thu, 19 Mar 2015 13:14:56 GMT', |
||||
'Content-Disposition' => 'attachment; filename="json.txt"; filename*=UTF-8\'\'json.txt', |
||||
'X-Content-Type-Options' => 'nosniff', |
||||
'X-Frame-Options' => 'SAMEORIGIN', |
||||
'X-XSS-Protection' => '1; mode=block', |
||||
'Server' => 'GSE', |
||||
'Alternate-Protocol' => '443:quic,p=0.5', |
||||
'Accept-Ranges' => 'none', |
||||
'Vary' => 'Accept-Encoding', |
||||
'Transfer-Encoding' => 'chunked' |
||||
], |
||||
'body' => '{"access_token" :"ya29.8xFOTYpQK48RgPH8KjQpSu9SrcANcOQx9JtRnEu52dNsXqai8VD4iY3nFzUBURWnAPeTPtPeIBNjIF","token_type" :"Bearer","expires_in" :3600,"id_token" :"6XFIidpthpu8iFNhyo5xjcGa9bUdiTL1zKnZz2dN-35IFzlCJ_IcmHYcA1i03iA5YVMOM1nLGiAbRaLTaMoWM5X_j0MyFBknwGMs3MM2WmdiIhdC7uNiXY2US8mWvCiVNwMnchpkJJUGIMbTNNPQd5_08XQvNi3TINiYOwZLxOIJ6X3pi9hNVY0dNNtUYwYdiNgwIW3ClRNNY1jiZxciXSckj18jb2jbSMMYujDKbw9ipMOIUxlnm5zIzEjNLV1BcMFMbjQWBnhjFUW4li-QTjcSnfj5iMdUIkjlGvkWcoLQ3pNNOwMhwjZFhdv0G3DTyT2nyOIR3eejckDXGWGw4l2Ni3izRwMYctNF1I_VstkDwn1idZoMOdR3b-zEO5C9ItMzl0TyNJjeb73VFrQIwXpHcTTQMgym2o3mijwJTn2ypu9NP0jjM1lcjd0Euh0OLJYxIYTIfbBC5WuCDcDMZxCbcz7oYLMl2yYDmI0akcuiVZyDO2I1aS2DAIUip.oTuI0HnAbtiA5y.Tnywh3VU0JTZ2Iu9OhJnYkvYmhzOm2AYbu5P9Q71UQObK2tLNcYQmBDmZGsQNIMwh1tQtl0sDTXj9WTVETuYAx4WK9hoOzcOVEY8iNHcl"}' |
||||
]; |
||||
|
||||
|
@ -0,0 +1,23 @@ |
||||
<?php |
||||
|
||||
return [ |
||||
'status' => 200, |
||||
'headers' => [ |
||||
'Cache-Control' => 'no-cache, no-store, max-age=0, must-revalidate', |
||||
'Pragma' => 'no-cache', |
||||
'Expires' => 'Fri, 01 Jan 1990 00:00:00 GMT', |
||||
'Date' => 'Thu, 19 Mar 2015 13:15:29 GMT', |
||||
'Vary' => 'X-Origin, Origin,Accept-Encoding', |
||||
'Content-Type' => 'application/json; charset=UTF-8', |
||||
'X-Content-Type-Options' => 'nosniff', |
||||
'X-Frame-Options' => 'SAMEORIGIN', |
||||
'X-XSS-Protection' => '1; mode=block', |
||||
'Server' => 'GSE', |
||||
'Alternate-Protocol' => '443:quic,p=0.5', |
||||
'Accept-Ranges' => 'none', |
||||
'Transfer-Encoding' => 'chunked' |
||||
], |
||||
'body' => '{"id":"103904294571447333816","email":"adam.wathan@example.com","verified_email":true,"name":"Adam Wathan","given_name":"Adam","family_name":"Wathan","link":"https://plus.google.com/103904294571447333816","picture":"https://lh3.googleusercontent.com/-w0_RpDnsIE4/AAAAAAAAAAI/AAAAAAAAAKM/NEiV3jig1HA/photo.jpg","gender":"male","locale":"en"}' |
||||
]; |
||||
|
||||
|
Loading…
Reference in new issue