Skip to content

Commit 95da753

Browse files
OXDEV-9889 Login or create user with facebook
1 parent 3214b8e commit 95da753

16 files changed

Lines changed: 234 additions & 59 deletions

File tree

metadata.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@
4040
],
4141
'controllers' => [
4242
'captcha' => \OxidEsales\SecurityModule\Captcha\Controller\CaptchaController::class,
43-
'password' => \OxidEsales\SecurityModule\PasswordPolicy\Controller\PasswordAjaxController::class
43+
'password' => \OxidEsales\SecurityModule\PasswordPolicy\Controller\PasswordAjaxController::class,
44+
45+
'oauth' => \OxidEsales\SecurityModule\Authentication\OAuth2\Controller\OAuthController::class
4446
],
4547
'templates' => [
4648
],
@@ -122,19 +124,19 @@
122124
[
123125
'group' => 'oauth',
124126
'name' => ModuleSettingsService::FACEBOOK_CLIENT_ID,
125-
'type' => 'string',
127+
'type' => 'str',
126128
'value' => ''
127129
],
128130
[
129131
'group' => 'oauth',
130132
'name' => ModuleSettingsService::FACEBOOK_CLIENT_SECRET,
131-
'type' => 'string',
133+
'type' => 'str',
132134
'value' => ''
133135
],
134136
[
135137
'group' => 'oauth',
136138
'name' => ModuleSettingsService::FACEBOOK_REDIRECT_URL,
137-
'type' => 'string',
139+
'type' => 'str',
138140
'value' => ''
139141
],
140142
],

src/Authentication/OAuth2/Controller/OAuthController.php

Lines changed: 19 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,71 +4,40 @@
44

55
use OxidEsales\Eshop\Application\Controller\FrontendController;
66
use OxidEsales\Eshop\Core\Registry;
7-
use League\OAuth2\Client\Token\AccessTokenInterface;
87
use OxidEsales\SecurityModule\Authentication\OAuth2\Service\ProviderCollectorInterface;
8+
use OxidEsales\SecurityModule\Authentication\OAuth2\Service\UserServiceInterface;
99

1010
class OAuthController extends FrontendController
1111
{
12-
public function redirect()
12+
public function render()
1313
{
14-
$providerName = Registry::getRequest()->getRequestEscapedParameter('provider');
15-
$collector = $this->getService(ProviderCollectorInterface::class);
16-
$provider = $collector->getProvider($providerName);
14+
$providerCollector = $this->getService(ProviderCollectorInterface::class);
1715

18-
if (!$provider) {
19-
Registry::getUtilsView()->addErrorToDisplay("Unknown provider: $providerName");
20-
return;
21-
}
16+
$provider = $providerCollector
17+
->getProvider($_GET['provider'])
18+
->getClient();
2219

23-
$state = bin2hex(random_bytes(16));
24-
$_SESSION['oauth_state'] = $state;
20+
Registry::getUtils()->redirect($provider->getAuthorizationUrl(), 302);
2521

26-
$authUrl = $provider->getAuthorizationUrl($state);
27-
Registry::getUtils()->redirect($authUrl);
22+
exit;
2823
}
2924

30-
public function callback()
25+
public function redirect()
3126
{
32-
$providerName = Registry::getRequest()->getRequestEscapedParameter('provider');
33-
$collector = $this->getService(ProviderCollectorInterface::class);
34-
$provider = $collector->getProvider($providerName);
35-
36-
if (!$provider) {
37-
Registry::getUtilsView()->addErrorToDisplay("Unknown provider: $providerName");
38-
return;
39-
}
40-
41-
$state = Registry::getRequest()->getRequestEscapedParameter('state');
42-
if ($state !== ($_SESSION['oauth_state'] ?? null)) {
43-
Registry::getUtilsView()->addErrorToDisplay('Invalid OAuth state');
44-
return;
45-
}
27+
$provider = $this
28+
->getService(ProviderCollectorInterface::class)
29+
->getProvider('facebook');
4630

47-
try {
48-
$code = Registry::getRequest()->getRequestEscapedParameter('code');
49-
$token = $provider->getAccessToken($code);
31+
$provider->getClient();
5032

51-
if (!$provider->validateToken($token)) {
52-
throw new \RuntimeException('Token invalid or expired');
53-
}
33+
$accessToken = $provider->getAccessToken($_GET['code']);
5434

55-
$userInfo = $provider->getUserInfo($token);
35+
$userDataType = $provider->getUserInfo($accessToken);
5636

57-
// Now handle login or registration (customize this part)
58-
$this->handleUserLogin($providerName, $userInfo);
37+
$this
38+
->getService(UserServiceInterface::class)
39+
->login($userDataType);
5940

60-
Registry::getUtils()->redirect('index.php?cl=account');
61-
62-
} catch (\Throwable $e) {
63-
Registry::getLogger()->error('OAuth callback error: ' . $e->getMessage());
64-
Registry::getUtilsView()->addErrorToDisplay('OAuth login failed. Please try again.');
65-
Registry::getUtils()->redirect('index.php?cl=login');
66-
}
67-
}
68-
69-
protected function handleUserLogin(string $providerName, array $userInfo): void
70-
{
71-
// TODO: check if user exists by provider ID or email, then log in or create
72-
// Example: $userService->loginOrRegisterViaOAuth($providerName, $userInfo);
41+
Registry::getUtils()->redirect('', 302);
7342
}
7443
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/**
4+
* Copyright © OXID eSales AG. All rights reserved.
5+
* See LICENSE file for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace OxidEsales\SecurityModule\Authentication\OAuth2\Factory;
11+
12+
use OxidEsales\Eshop\Application\Model\User;
13+
14+
class UserFactory implements UserFactoryInterface
15+
{
16+
/**
17+
* @inheritDoc
18+
*/
19+
public function create(): User
20+
{
21+
return oxNew(User::class);
22+
}
23+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
/**
4+
* Copyright © OXID eSales AG. All rights reserved.
5+
* See LICENSE file for license details.
6+
*/
7+
8+
namespace OxidEsales\SecurityModule\Authentication\OAuth2\Factory;
9+
10+
use OxidEsales\Eshop\Application\Model\User;
11+
12+
interface UserFactoryInterface
13+
{
14+
public function create(): User;
15+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/**
4+
* Copyright © OXID eSales AG. All rights reserved.
5+
* See LICENSE file for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace OxidEsales\SecurityModule\Authentication\OAuth2\Infrastructure;
11+
12+
use Doctrine\DBAL\Result;
13+
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
14+
15+
readonly class UserRepository implements UserRepositoryInterface
16+
{
17+
public function __construct(
18+
private QueryBuilderFactoryInterface $queryBuilderFactory,
19+
) {
20+
}
21+
22+
public function getUserByEmail(string $username): string|bool
23+
{
24+
$queryBuilder = $this->queryBuilderFactory->create();
25+
26+
$queryBuilder
27+
->select('u.oxid')
28+
->from('oxuser', 'u')
29+
->where('u.oxusername = :oxusername')
30+
->setParameter('oxusername', $username);
31+
32+
/** @var Result<array> $result */
33+
$result = $queryBuilder->execute();
34+
35+
return $result->fetchOne();
36+
}
37+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
/**
4+
* Copyright © OXID eSales AG. All rights reserved.
5+
* See LICENSE file for license details.
6+
*/
7+
8+
namespace OxidEsales\SecurityModule\Authentication\OAuth2\Infrastructure;
9+
10+
interface UserRepositoryInterface
11+
{
12+
public function getUserByEmail(string $username): string|bool;
13+
}

src/Authentication/OAuth2/Service/Provider/Facebook/Facebook.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ public function getClient(): AbstractProvider
4343
return $this->facebookProvider;
4444
}
4545

46-
public function getAuthorizationUrl(string $state): string
46+
public function getAuthorizationUrl(): string
4747
{
48-
return $this->facebookProvider->getAuthorizationUrl(['state' => $state]);
48+
return $this->facebookProvider->getAuthorizationUrl();
4949
}
5050

5151
public function getAccessToken(string $code): AccessTokenInterface
@@ -55,7 +55,6 @@ public function getAccessToken(string $code): AccessTokenInterface
5555

5656
public function getUserInfo(AccessTokenInterface $token): UserDataTypeInterface
5757
{
58-
//todo: move to service
5958
$user = $this->facebookProvider->getResourceOwner($token);
6059

6160
return new UserDataType(
@@ -67,5 +66,6 @@ public function getUserInfo(AccessTokenInterface $token): UserDataTypeInterface
6766

6867
public function validateToken(AccessTokenInterface $token): bool
6968
{
69+
return true;
7070
}
7171
}

src/Authentication/OAuth2/Service/ProviderInterface.php renamed to src/Authentication/OAuth2/Service/Provider/ProviderInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace OxidEsales\SecurityModule\Authentication\OAuth2\Service;
3+
namespace OxidEsales\SecurityModule\Authentication\OAuth2\Service\Provider;
44

55
use League\OAuth2\Client\Provider\AbstractProvider;
66
use League\OAuth2\Client\Token\AccessTokenInterface;

src/Authentication/OAuth2/Service/ProviderCollector.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
namespace OxidEsales\SecurityModule\Authentication\OAuth2\Service;
1111

12+
use OxidEsales\SecurityModule\Authentication\OAuth2\Service\Provider\ProviderInterface;
13+
1214
class ProviderCollector implements ProviderCollectorInterface
1315
{
1416
public function __construct(

src/Authentication/OAuth2/Service/ProviderCollectorInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
namespace OxidEsales\SecurityModule\Authentication\OAuth2\Service;
99

10+
use OxidEsales\SecurityModule\Authentication\OAuth2\Service\Provider\ProviderInterface;
11+
1012
interface ProviderCollectorInterface
1113
{
1214
public function getProviders(): array;

0 commit comments

Comments
 (0)