OAuth: Save auth tokens

This commit is contained in:
Igor Scheller 2020-12-26 18:24:20 +01:00 committed by msquare
parent 304b599cf4
commit d423bb07d3
5 changed files with 116 additions and 10 deletions

View File

@ -0,0 +1,41 @@
<?php
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class OauthAddTokens extends Migration
{
use Reference;
/**
* Run the migration
*/
public function up()
{
$this->schema->table(
'oauth',
function (Blueprint $table) {
$table->string('access_token')->nullable()->default(null)->after('identifier');
$table->string('refresh_token')->nullable()->default(null)->after('access_token');
$table->dateTime('expires_at')->nullable()->default(null)->after('refresh_token');
}
);
}
/**
* Reverse the migration
*/
public function down()
{
$this->schema->table(
'oauth',
function (Blueprint $table) {
$table->dropColumn('access_token');
$table->dropColumn('refresh_token');
$table->dropColumn('expires_at');
}
);
}
}

View File

@ -227,8 +227,11 @@ function guest_register()
if ($session->has('oauth2_connect_provider') && $session->has('oauth2_user_id')) {
$oauth = new OAuth([
'provider' => $session->get('oauth2_connect_provider'),
'identifier' => $session->get('oauth2_user_id'),
'provider' => $session->get('oauth2_connect_provider'),
'identifier' => $session->get('oauth2_user_id'),
'access_token' => $session->get('oauth2_access_token'),
'refresh_token' => $session->get('oauth2_refresh_token'),
'expires_at' => $session->get('oauth2_expires_at'),
]);
$oauth->user()
->associate($user)
@ -236,6 +239,9 @@ function guest_register()
$session->remove('oauth2_connect_provider');
$session->remove('oauth2_user_id');
$session->remove('oauth2_access_token');
$session->remove('oauth2_refresh_token');
$session->remove('oauth2_expires_at');
}
// Assign user-group and set password

View File

@ -16,6 +16,7 @@ use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Provider\GenericProvider;
use League\OAuth2\Client\Provider\ResourceOwnerInterface as ResourceOwner;
use League\OAuth2\Client\Token\AccessTokenInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Session\Session as Session;
@ -136,6 +137,16 @@ class OAuthController extends BaseController
->where('identifier', $resourceOwner->getId())
->first();
$expirationTime = $accessToken->getExpires();
$expirationTime = $expirationTime ? Carbon::createFromTimestamp($expirationTime) : null;
if ($oauth) {
$oauth->access_token = $accessToken->getToken();
$oauth->refresh_token = $accessToken->getRefreshToken();
$oauth->expires_at = $expirationTime;
$oauth->save();
}
$user = $this->auth->user();
if ($oauth && $user && $user->id != $oauth->user_id) {
throw new HttpNotFound('oauth.already-connected');
@ -144,7 +155,13 @@ class OAuthController extends BaseController
$connectProvider = $this->session->get('oauth2_connect_provider');
$this->session->remove('oauth2_connect_provider');
if (!$oauth && $user && $connectProvider && $connectProvider == $providerName) {
$oauth = new OAuth(['provider' => $providerName, 'identifier' => $resourceOwner->getId()]);
$oauth = new OAuth([
'provider' => $providerName,
'identifier' => $resourceOwner->getId(),
'access_token' => $accessToken->getToken(),
'refresh_token' => $accessToken->getRefreshToken(),
'expires_at' => $expirationTime,
]);
$oauth->user()
->associate($user)
->save();
@ -156,10 +173,16 @@ class OAuthController extends BaseController
$this->addNotification('oauth.connected');
}
$config = ($this->config->get('oauth')[$providerName]);
$config = $this->config->get('oauth')[$providerName];
$userdata = new Collection($resourceOwner->toArray());
if (!$oauth) {
return $this->redirectRegisterOrThrowNotFound($providerName, $resourceOwner->getId(), $config, $userdata);
return $this->redirectRegisterOrThrowNotFound(
$providerName,
$resourceOwner->getId(),
$accessToken,
$config,
$userdata
);
}
if (isset($config['mark_arrived']) && $config['mark_arrived']) {
@ -282,16 +305,18 @@ class OAuthController extends BaseController
}
/**
* @param string $providerName
* @param string $providerUserIdentifier
* @param array $config
* @param Collection $userdata
* @param string $providerName
* @param string $providerUserIdentifier
* @param AccessTokenInterface $accessToken
* @param array $config
* @param Collection $userdata
*
* @return Response
*/
protected function redirectRegisterOrThrowNotFound(
string $providerName,
string $providerUserIdentifier,
AccessTokenInterface $accessToken,
array $config,
Collection $userdata
): Response {
@ -315,6 +340,12 @@ class OAuthController extends BaseController
$this->session->set('oauth2_connect_provider', $providerName);
$this->session->set('oauth2_user_id', $providerUserIdentifier);
$expirationTime = $accessToken->getExpires();
$expirationTime = $expirationTime ? Carbon::createFromTimestamp($expirationTime) : null;
$this->session->set('oauth2_access_token', $accessToken->getToken());
$this->session->set('oauth2_refresh_token', $accessToken->getRefreshToken());
$this->session->set('oauth2_expires_at', $expirationTime);
return $this->redirector->to('/register');
}
}

View File

@ -12,12 +12,17 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
* @property int $id
* @property string $provider
* @property string $identifier
* @property string $access_token
* @property string $refresh_token
* @property Carbon|null $expires_at
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @method static QueryBuilder|OAuth[] whereId($value)
* @method static QueryBuilder|OAuth[] whereProvider($value)
* @method static QueryBuilder|OAuth[] whereIdentifier($value)
* @method static QueryBuilder|OAuth[] whereAccessToken($value)
* @method static QueryBuilder|OAuth[] whereRefreshToken($value)
*/
class OAuth extends BaseModel
{
@ -29,9 +34,17 @@ class OAuth extends BaseModel
/** @var bool Enable timestamps */
public $timestamps = true;
/** @var string[] */
protected $dates = [
'expires_at',
];
/** @var array */
protected $fillable = [
'provider',
'identifier',
'access_token',
'refresh_token',
'expires_at',
];
}

View File

@ -94,6 +94,9 @@ class OAuthControllerTest extends TestCase
$this->session->set('oauth2_connect_provider', 'testprovider');
$accessToken = $this->createMock(AccessToken::class);
$this->setExpects($accessToken, 'getToken', null, 'test-token', $this->atLeastOnce());
$this->setExpects($accessToken, 'getRefreshToken', null, 'test-refresh-token', $this->atLeastOnce());
$this->setExpects($accessToken, 'getExpires', null, 4242424242, $this->atLeastOnce());
/** @var ResourceOwnerInterface|MockObject $resourceOwner */
$resourceOwner = $this->createMock(ResourceOwnerInterface::class);
@ -153,7 +156,13 @@ class OAuthControllerTest extends TestCase
// Login using provider
$controller->index($request);
$this->assertFalse($this->session->has('oauth2_connect_provider'));
$this->assertFalse((bool)User::find(1)->state->arrived);
$this->assertFalse((bool)$this->otherUser->state->arrived);
// Tokens updated
$oauth = $this->otherUser->oauth[0];
$this->assertEquals('test-token', $oauth->access_token);
$this->assertEquals('test-refresh-token', $oauth->refresh_token);
$this->assertEquals(4242424242, $oauth->expires_at->unix());
// Mark as arrived
$oauthConfig = $this->config->get('oauth');
@ -321,6 +330,9 @@ class OAuthControllerTest extends TestCase
public function testIndexRedirectRegister()
{
$accessToken = $this->createMock(AccessToken::class);
$this->setExpects($accessToken, 'getToken', null, 'test-token', $this->atLeastOnce());
$this->setExpects($accessToken, 'getRefreshToken', null, 'test-refresh-token', $this->atLeastOnce());
$this->setExpects($accessToken, 'getExpires', null, 4242424242, $this->atLeastOnce());
/** @var ResourceOwnerInterface|MockObject $resourceOwner */
$resourceOwner = $this->createMock(ResourceOwnerInterface::class);
@ -374,6 +386,9 @@ class OAuthControllerTest extends TestCase
$controller->index($request);
$this->assertEquals('testprovider', $this->session->get('oauth2_connect_provider'));
$this->assertEquals('provider-not-connected-identifier', $this->session->get('oauth2_user_id'));
$this->assertEquals('test-token', $this->session->get('oauth2_access_token'));
$this->assertEquals('test-refresh-token', $this->session->get('oauth2_refresh_token'));
$this->assertEquals(4242424242, $this->session->get('oauth2_expires_at')->unix());
$this->assertEquals(
[
'name' => 'username',