Skip to content

Commit

Permalink
feat: dispatch event when an OAuth login is successful (#4)
Browse files Browse the repository at this point in the history
* feat: dispatch event when an OAuth login is successful

* Apply fixes from StyleCI

---------

Co-authored-by: StyleCI Bot <[email protected]>
  • Loading branch information
imorland and StyleCIBot authored Jun 15, 2023
1 parent f02c71d commit 2dec4e8
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 10 deletions.
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
"psr-4": {
"FoF\\Extend\\": "src/"
}
},
"require-dev": {
"league/oauth2-client": "^2.7"
}
}
29 changes: 19 additions & 10 deletions src/Controllers/AbstractOAuthController.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
use Flarum\Settings\SettingsRepositoryInterface;
use Flarum\User\LoginProvider;
use Flarum\User\User;
use FoF\Extend\Events\OAuthLoginSuccessful;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Session\Store;
use Illuminate\Support\Arr;
use Laminas\Diactoros\Response\HtmlResponse;
Expand Down Expand Up @@ -47,16 +49,23 @@ abstract class AbstractOAuthController implements RequestHandlerInterface
*/
protected $url;

/**
* @var Dispatcher
*/
protected $events;

/**
* @param ResponseFactory $response
* @param SettingsRepositoryInterface $settings
* @param UrlGenerator $url
* @param Dispatcher $events
*/
public function __construct(ResponseFactory $response, SettingsRepositoryInterface $settings, UrlGenerator $url)
public function __construct(ResponseFactory $response, SettingsRepositoryInterface $settings, UrlGenerator $url, Dispatcher $events)
{
$this->response = $response;
$this->settings = $settings;
$this->url = $url;
$this->events = $events;
}

/**
Expand Down Expand Up @@ -95,19 +104,19 @@ public function handle(ServerRequestInterface $request): ResponseInterface
$token = $provider->getAccessToken('authorization_code', compact('code'));
$user = $provider->getResourceOwner($token);

if ($shouldLink = $session->remove('linkTo')) {
// Don't register a new user, just link to the existing account, else continue with registration.
$actor = RequestUtil::getActor($request);
$actor = RequestUtil::getActor($request);

if ($actor->exists) {
$actor->assertRegistered();
$this->events->dispatch(new OAuthLoginSuccessful($token, $user, $this->getProviderName(), $this->getIdentifier($user), $actor));

if ($actor->id !== (int) $shouldLink) {
throw new ValidationException(['linkAccount' => 'User data mismatch']);
}
// Don't register a new user, just link to the existing account, else continue with registration.
if ($shouldLink = $session->remove('linkTo') && $actor->exists) {
$actor->assertRegistered();

return $this->link($actor, $user);
if ($actor->id !== (int) $shouldLink) {
throw new ValidationException(['linkAccount' => 'User data mismatch']);
}

return $this->link($actor, $user);
}

return $this->response->make(
Expand Down
65 changes: 65 additions & 0 deletions src/Events/OAuthLoginSuccessful.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

/*
* This file is part of fof/extend.
*
* Copyright (c) FriendsOfFlarum.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FoF\Extend\Events;

use Flarum\User\User;
use League\OAuth2\Client\Provider\ResourceOwnerInterface;
use League\OAuth2\Client\Token\AccessToken;

class OAuthLoginSuccessful
{
/**
* The access token provided by the service.
*
* @var AccessToken
*/
public $token;

/**
* THe complete ResourceOwner object.
*
* @var ResourceOwnerInterface
*/
public $userResource;

/**
* The OAuth provider name. This is used in the `login_providers` table as the `provider` column.
*
* @var string
*/
public $providerName;

/**
* The providers unique identifier as given by the provider. This is used in the `login_providers` table as the `identifier` column.
*
* @var string
*/
public $identifier;

/**
* For a "normal" login, this value will always be `Guest`, as when this event is dispatched we have not yet completed the complete login flow.
*
* If a logged in user is attemping to link their existing Flarum account with a OAuth provider, this will contain the current user object.
*
* @var ?User
*/
public $actor;

public function __construct(AccessToken $token, ResourceOwnerInterface $userResource, string $providerName, string $identifier, ?User $actor)
{
$this->token = $token;
$this->userResource = $userResource;
$this->providerName = $providerName;
$this->identifier = $identifier;
$this->actor = $actor;
}
}

0 comments on commit 2dec4e8

Please sign in to comment.