Skip to content

Instantly share code, notes, and snippets.

@sorenmalling
Created April 17, 2017 10:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sorenmalling/c63f5e80830c3b19e9b65e7bf9cf5c88 to your computer and use it in GitHub Desktop.
Save sorenmalling/c63f5e80830c3b19e9b65e7bf9cf5c88 to your computer and use it in GitHub Desktop.
<?php
namespace Vendor\Application\Security\Authentication\Oauth\Provider;
abstract class AbstractOauthProvider extends AbstractProvider {
/**
* Oauth manager
*
* @var OauthManager
* @Flow\Inject
*/
protected $oauthManager;
/**
* @Flow\Inject
* @var \Neos\Flow\Persistence\PersistenceManagerInterface
*/
protected $persistenceManager;
/**
* @var PropertyMapper
* @Flow\Inject
*/
protected $propertyMapper;
/**
* @var HashService
* @Flow\Inject
*/
protected $hashService;
/**
* Account repository
*
* @var AccountRepository
* @Flow\Inject
*/
protected $accountRepository;
/**
* User repository
*
* @var UserRepository
* @Flow\Inject
*/
protected $userRepository;
/**
* @Flow\Inject
* @var \Neos\Flow\Security\Context
*/
protected $securityContext;
/**
* @return string
*/
abstract protected function getResourceOwnerClassName();
/**
* Get oauth provider
*
* @return \League\OAuth2\Client\Provider\AbstractProvider
*/
protected function getOauthProvider() {
$strategy = $this->oauthManager->getStrategyNameByProviderName($this->name);
$provider = $this->oauthManager->getImplementedProviderByStrategyName($strategy);
return $provider;
}
/**
* @param TokenInterface $authenticationToken
* @return \League\OAuth2\Client\Provider\ResourceOwnerInterface
*/
protected function getResourceOwner(TokenInterface $authenticationToken) {
$credentials = $authenticationToken->getCredentials();
$provider = $this->getOauthProvider();
$resourceOwner = $provider->getResourceOwner($credentials['accessToken']);
return $resourceOwner;
}
public function authenticate(TokenInterface $authenticationToken)
{
$tokens = $this->getTokenClassNames();
$tokenClassName = $tokens[0];
if (!($authenticationToken instanceof $tokenClassName)) {
throw new UnsupportedAuthenticationTokenException(sprintf('This provider only supports %s', [$this->getTokenClassNames()[0]]));
}
$resourceOwner = $this->getResourceOwner($authenticationToken);
if (!(get_class($resourceOwner) === $this->getResourceOwnerClassName())) {
$authenticationToken->setAuthenticationStatus(TokenInterface::WRONG_CREDENTIALS);
return;
}
$providerName = $this->name;
$accountRepository = $this->accountRepository;
$account = NULL;
$this->securityContext->withoutAuthorizationChecks(function () use ($resourceOwner, $providerName, $accountRepository , &$account) {
$account = $accountRepository->findByAccountIdentifierAndAuthenticationProviderName($resourceOwner->getId(), $providerName);
});
if ($account === NULL) {
$user = User::signUp(
$resourceOwner->getId(),
$this->hashService->hashPassword(Algorithms::generateRandomString(32)),
$this->name
);
$this->userRepository->add($user);
$account = $user->getAccount();
}
$authenticationToken->setAccount($account);
$randomPassword = $this->hashService->hashPassword(Algorithms::generateRandomString(32));
$account->setCredentialsSource($randomPassword);
$authenticationToken->setAccount($account);
$authenticationToken->setAuthenticationStatus(TokenInterface::AUTHENTICATION_SUCCESSFUL);
$this->accountRepository->update($account);
$this->persistenceManager->persistAll();
}
}
<?php
namespace Vendor\Application\Security\Authentication\Oauth\Provider;
use League\OAuth2\Client\Provider\FacebookUser;
class FacebookProvider extends AbstractOauthProvider {
/**
* @return array
*/
public function getTokenClassNames()
{
return [FacebookToken::class];
}
/**
* @return string
*/
protected function getResourceOwnerClassName()
{
return FacebookUser::class;
}
}
<?php
namespace Vendor\Application\Security\Authentication\Token;
class FacebookToken extends AbstractToken {
/**
* Oauth manager
*
* @var OauthManager
* @Flow\Inject
*/
protected $oauthManager;
/**
* Object manager
*
* @var ObjectManagerInterface
* @Flow\Inject
*/
protected $objectManager;
/**
* @param \Neos\Flow\Mvc\ActionRequest $actionRequest
* @throws \Neos\Flow\Mvc\Exception\NoSuchArgumentException
* @throws \Neos\Flow\Security\Exception\InvalidAuthenticationStatusException
*/
public function updateCredentials(\Neos\Flow\Mvc\ActionRequest $actionRequest)
{
$strategy = $actionRequest->getInternalArgument('__oauthProvider');
if ($actionRequest->getHttpRequest()->getMethod() !== 'GET' || $this->oauthManager->getProviderNameByStrategyName($strategy) !== $this->authenticationProviderName) {
return;
}
if (!$actionRequest->hasArgument('code')) {
$this->setAuthenticationStatus(TokenInterface::WRONG_CREDENTIALS);
return;
}
if ($actionRequest->hasArgument('code')) {
$code = $actionRequest->getArgument('code');
try {
$provider = $this->oauthManager->getImplementedProviderByStrategyName($strategy);
$token = $provider->getAccessToken('authorization_code', ['code' => $code]);
$credentials = ['accessToken' => $token];
$this->credentials = $credentials;
$this->setAuthenticationStatus(TokenInterface::AUTHENTICATION_NEEDED);
} catch (\Exception $exception) {
$this->setAuthenticationProviderName(TokenInterface::WRONG_CREDENTIALS);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment