Skip to content

Commit

Permalink
[5.x] Add refreshToken method (#675)
Browse files Browse the repository at this point in the history
* Add refreshToken method

* Fix code style

* Fix naming

* Fix Twitter provider

* Remove unnecessary parameter from Twitter provider

* formatting

* fix comma

---------

Co-authored-by: Taylor Otwell <[email protected]>
  • Loading branch information
antoinelame and taylorotwell authored Dec 1, 2023
1 parent 7cec8ba commit dc14fca
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/Two/AbstractProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,43 @@ protected function getTokenFields($code)
return $fields;
}

/**
* Refresh a user's access token with a refresh token.
*
* @param string $refreshToken
* @return \Laravel\Socialite\Two\Token
*/
public function refreshToken($refreshToken)
{
$response = $this->getRefreshTokenResponse($refreshToken);

return new Token(
Arr::get($response, 'access_token'),
Arr::get($response, 'refresh_token'),
Arr::get($response, 'expires_in'),
explode($this->scopeSeparator, Arr::get($response, 'scope', ''))
);
}

/**
* Get the refresh token response for the given refresh token.
*
* @param string $refreshToken
* @return array
*/
protected function getRefreshTokenResponse($refreshToken)
{
return json_decode($this->getHttpClient()->post($this->getTokenUrl(), [
RequestOptions::HEADERS => ['Accept' => 'application/json'],
RequestOptions::FORM_PARAMS => [
'grant_type' => 'refresh_token',
'refresh_token' => $refreshToken,
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
],
])->getBody(), true);
}

/**
* Get the code from the request.
*
Expand Down
50 changes: 50 additions & 0 deletions src/Two/Token.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Laravel\Socialite\Two;

class Token
{
/**
* The user's access token.
*
* @var string
*/
public $token;

/**
* The refresh token that can be exchanged for a new access token.
*
* @var string
*/
public $refreshToken;

/**
* The number of seconds the access token is valid for.
*
* @var int
*/
public $expiresIn;

/**
* The scopes the user authorized. The approved scopes may be a subset of the requested scopes.
*
* @var array
*/
public $approvedScopes;

/**
* Create a new token instance.
*
* @param string $token
* @param string $refreshToken
* @param int $expiresIn
* @param array $approvedScopes
*/
public function __construct(string $token, string $refreshToken, int $expiresIn, array $approvedScopes)
{
$this->token = $token;
$this->refreshToken = $refreshToken;
$this->expiresIn = $expiresIn;
$this->approvedScopes = $approvedScopes;
}
}
18 changes: 18 additions & 0 deletions src/Two/TwitterProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,24 @@ public function getAccessTokenResponse($code)
return json_decode($response->getBody(), true);
}

/**
* {@inheritdoc}
*/
protected function getRefreshTokenResponse($refreshToken)
{
$response = $this->getHttpClient()->post($this->getTokenUrl(), [
RequestOptions::HEADERS => ['Accept' => 'application/json'],
RequestOptions::AUTH => [$this->clientId, $this->clientSecret],
RequestOptions::FORM_PARAMS => [
'grant_type' => 'refresh_token',
'refresh_token' => $refreshToken,
'client_id' => $this->clientId,
],
]);

return json_decode($response->getBody(), true);
}

/**
* {@inheritdoc}
*/
Expand Down
20 changes: 20 additions & 0 deletions tests/OAuthTwoTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Laravel\Socialite\Tests\Fixtures\OAuthTwoTestProviderStub;
use Laravel\Socialite\Tests\Fixtures\OAuthTwoWithPKCETestProviderStub;
use Laravel\Socialite\Two\InvalidStateException;
use Laravel\Socialite\Two\Token;
use Laravel\Socialite\Two\User;
use Mockery as m;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -178,4 +179,23 @@ public function testExceptionIsThrownIfStateIsNotSet()
$provider = new OAuthTwoTestProviderStub($request, 'client_id', 'client_secret', 'redirect');
$provider->user();
}

public function testUserRefreshesToken()
{
$request = Request::create('/');
$provider = new OAuthTwoTestProviderStub($request, 'client_id', 'client_secret', 'redirect_uri');
$provider->http = m::mock(stdClass::class);
$provider->http->expects('post')->with('http://token.url', [
'headers' => ['Accept' => 'application/json'],
'form_params' => ['grant_type' => 'refresh_token', 'client_id' => 'client_id', 'client_secret' => 'client_secret', 'refresh_token' => 'refresh_token'],
])->andReturns($response = m::mock(stdClass::class));
$response->expects('getBody')->andReturns('{ "access_token" : "access_token", "refresh_token" : "refresh_token", "expires_in" : 3600, "scope" : "scope1,scope2" }');
$token = $provider->refreshToken('refresh_token');

$this->assertInstanceOf(Token::class, $token);
$this->assertSame('access_token', $token->token);
$this->assertSame('refresh_token', $token->refreshToken);
$this->assertSame(3600, $token->expiresIn);
$this->assertSame(['scope1', 'scope2'], $token->approvedScopes);
}
}

0 comments on commit dc14fca

Please sign in to comment.