How to manage Full authentication is required to access this resource.?
I want to redirect user when he is not authenticated.
I have custom uthenticater which authenticate user depending on session data, and i want to redirect user when hes not authenticatet.
My authenticator class:
/**
* #Service("sso_authenticator")
*/
class SsoAuthenticator implements SimplePreAuthenticatorInterface
{
/**
* #var SsoUserProvider
*/
protected $userProvider;
/**
* #InjectParams({
* "userProvider" = #Inject("sso_user_provider")
* })
*/
public function __construct(SsoUserProvider $userProvider)
{
$this->userProvider = $userProvider;
}
public function createToken(Request $request, $providerKey)
{
$user = $request->getSession()->get('sso_user');
if (!$user) {
throw new BadCredentialsException('No user found');
}
return new PreAuthenticatedToken(
'anon.', $user, $providerKey
);
}
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
{
$user = $token->getCredentials();
if (!is_array($user)) {
$user = $token->getUser();
}
if (!$user) {
throw new AuthenticationException('User does not exist.');
}
$ssoUser = $this->userProvider->loadUser($user);
return new PreAuthenticatedToken(
$ssoUser, $user, $providerKey, $ssoUser->getRoles()
);
}
public function supportsToken(TokenInterface $token, $providerKey)
{
return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey;
}
}
i set the login path to logout path like this:
secured_area:
form_login:
login_path : main_user_logout
then i wrote custom logout handler:
/**
* #Service("sso_authentication_handler")
*/
class SsoAuthenticationHandler implements LogoutSuccessHandlerInterface
{
/**
* #var Router
*/
private $router;
/**
* #var array
*/
protected $ssoUrls;
/**
* #InjectParams({
* "ssoUrls" = #Inject("%wordpress_sso%"),
* "router" = #Inject("router")
* })
*/
public function __construct(array $ssoUrls, Router $router)
{
$this->ssoUrls = $ssoUrls;
$this->router = $router;
}
public function onLogoutSuccess(Request $request)
{
$locale = $request->getLocale();
if ($locale === 'pl') {
$url = $this->ssoUrls[$locale];
} else {
$url = $this->ssoUrls['en'];
}
$url .= '?returnUrl=' . $this->router->generate('main');
return new RedirectResponse($url);
}
}
so with this combination i achive behavior like when youser is not authenticated or when he logout i will redirect him to other site to login, in my example to wordpress.
Related
I have a Guard Authentication in my Symfony Web Application. I would like to perform some unit tests. I'm unable to simulate an authentification in my tests. The token stays null when calling $tokenStorage->getToken().
Note:
The login authentification is working under dev and prod environnement.
I saw quite a lot of related topics without success and the doc.
Symfony version: 3.4.
Reproduce: you can reproduce the error from this repo (symfony project). This repo defined one entity User with a custom constraint validator ExampleValidator. In this constraint, I need to have the current logged user.
Code sample:
After manually creating an User, the login function used in tests:
private function logIn($firewallName = 'main'){
// dummy call to bypass the hasPreviousSession check
$crawler = $this->client->request('GET', '/');
$session = $this->client->getContainer()->get('session');
/** #var User $user */
$user = $this->entityManager->getRepository(User::class)
->findOneBy(['email' => 'user1#example.com']);
// you may need to use a different token class depending on your application.
// for example, when using Guard authentication you must instantiate PostAuthenticationGuardToken
$token = new PostAuthenticationGuardToken($user, $firewallName, [new Role('ROLE_CLIENT')]);
self::$kernel->getContainer()->get('security.token_storage')->setToken($token);
$session->set('_security_'.$firewallName, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
The User call from tokenStorage (from service function):
class ExampleValidator extends ConstraintValidator{
protected $requestStack;
protected $em;
protected $user_id;
public function __construct(RequestStack $request,
EntityManager $em,
TokenStorage $tokenStorage){
$this->requestStack = $request;
$this->em = $em;
/** #var User $user */
// Token is always null
$user = $tokenStorage->getToken()->getUser();
$this->user_id = $user != "anon." ? $user->getId() : null;
}
/**
* #param $value
* #param Constraint $constraint
*/
public function validate($value, Constraint $constraint)
{
// validation rules ...
}
}
LoginFormAuthenticator.php
<?php
namespace AppBundle\Security;
use AppBundle\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator{
use TargetPathTrait;
private $entityManager;
private $urlGenerator;
private $csrfTokenManager;
private $passwordEncoder;
private $loginAttemptRepository;
public function __construct(EntityManagerInterface $entityManager,
UrlGeneratorInterface $urlGenerator,
CsrfTokenManagerInterface $csrfTokenManager,
UserPasswordEncoderInterface $passwordEncoder){
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
$this->passwordEncoder = $passwordEncoder;
}
/**
* #param Request $request
* #return bool
*/
public function supports(Request $request){
return $request->getPathInfo() == '/login_check' &&
$request->isMethod('POST') &&
$request->request->get('_password') !== null;
}
/**
* #param Request $request
* #return array|mixed|void|null
*/
public function getCredentials(Request $request){
$isLoginSubmit = $request->getPathInfo() == '/login_check' &&
$request->isMethod('POST') &&
$request->request->get('_password') !== null;
$isCaptcha = $request->request->get('captcha_set');
if ($isCaptcha == 1 && $request->request->get('_password') !== null) {
$secret = ...;
if($_POST['g-recaptcha-response'] !== null){
// Paramètre renvoyé par le recaptcha
$response = $_POST['g-recaptcha-response'];
$remoteip = $_SERVER['REMOTE_ADDR'];
$api_url = "https://www.google.com/recaptcha/api/siteverify?secret="
. $secret
. "&response=" . $response
. "&remoteip=" . $remoteip ;
$decode = json_decode(file_get_contents($api_url), true);
if ($decode['success'] == true) {
$username = $request->request->get('_username');
$password = $request->request->get('_password');
$csrfToken = $request->request->get('_csrf_token');
if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken('authenticate', $csrfToken))) {
throw new InvalidCsrfTokenException('Invalid CSRF token.');
}
$request->getSession()->set(
Security::LAST_USERNAME,
$username
);
return [
'username' => $username,
'password' => $password,
];
}
else{
throw new CustomUserMessageAuthenticationException('Captcha invalids.');
}
}
else{
throw new CustomUserMessageAuthenticationException('Captcha invalids.');
}
}
else {
if (!$isLoginSubmit) {
// skip authentication
return;
}
$username = $request->request->get('_username');
$password = $request->request->get('_password');
$csrfToken = $request->request->get('_csrf_token');
if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken('authenticate', $csrfToken))) {
throw new InvalidCsrfTokenException('Invalid CSRF token.');
}
$request->getSession()->set(
Security::LAST_USERNAME,
$username
);
return [
'username' => $username,
'password' => $password,
];
}
}
/**
* #param mixed $credentials
* #param UserProviderInterface $userProvider
* #return User|object|UserInterface|null
*/
public function getUser($credentials, UserProviderInterface $userProvider){
$username = $credentials["username"];
$user = $this->entityManager->getRepository(User::class)
->findOneBy(['username' => $username]);
return $user;
}
/**
* #param mixed $credentials
* #param UserInterface $user
* #return bool
*/
public function checkCredentials($credentials, UserInterface $user){
$password = $credentials["password"];
$rep = false;
if ($this->passwordEncoder->isPasswordValid($user, $password)){
$rep = true;
}
return $rep;
}
/**
* #param Request $request
* #param TokenInterface $token
* #param string $providerKey
* #return RedirectResponse
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey){
$targetPath = null;
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
return new RedirectResponse($targetPath);
}
return new RedirectResponse($this->urlGenerator->generate('map'));
}
/**
* #return string
*/
protected function getLoginUrl(){
return $this->urlGenerator->generate('fos_user_security_login');
}
}
I believe the root of your problem is that you are using multiple container instances. In particular, your logIn() function works on the container of the client, but the validator is from a different container that you boot up during setUp(). Thus, the changes you make in logIn() to the client container do not affect the validator you are actually testing.
Using the same container everywhere, e.g. the one from the client, should solve this. The following changes to your repository make the test pass:
diff --git a/tests/AppBundle/Validator/UserTest.php b/tests/AppBundle/Validator/UserTest.php
index f15c854..603e566 100644
--- a/tests/AppBundle/Validator/UserTest.php
+++ b/tests/AppBundle/Validator/UserTest.php
## -44,10 +44,7 ## class UserTest extends WebTestCase{
$this->container = $this->client->getContainer();
$this->entityManager = $this->container->get('doctrine.orm.entity_manager');
- // Set validator
- $kernel = $this->createKernel();
- $kernel->boot();
- $this->validator = $kernel->getContainer()->get('validator');
+ $this->validator = $this->client->getContainer()->get('validator');
// Create one user
$this->createOneUser();
## -100,7 +97,7 ## class UserTest extends WebTestCase{
// you may need to use a different token class depending on your application.
// for example, when using Guard authentication you must instantiate PostAuthenticationGuardToken
$token = new PostAuthenticationGuardToken($user, $firewallName, [new Role('ROLE_CLIENT')]);
- self::$kernel->getContainer()->get('security.token_storage')->setToken($token);
+ $this->client->getContainer()->get('security.token_storage')->setToken($token);
$session->set('_security_'.$firewallName, serialize($token));
$session->save();
Does anyone know how I can get the user email address?
My code is below:
require_once("sm/google/Google_Client.php");
require_once("sm/google/contrib/Google_PlusService.php");
require_once("sm/google/contrib/Google_Oauth2Service.php");
include_once("ErrorReporting.php");
$objError = new ErrorReporting();
$client = new Google_Client();
$client->setApplicationName("myproject");
//$client->setHttpClient($httpClient);
// Visit https://code.google.com/apis/console?api=plus to generate your
// client id, client secret, and to register your redirect uri.
$client->setClientId(GOOGLE_CLIENT_ID);
$client->setClientSecret(GOOGLE_CLIENT_SECRET);
$client->setRedirectUri($callbackurl);
$client->setDeveloperKey(GOOGLE_API_KEY);
$client->setAccessType("online");
$client->setApprovalPrompt("auto");
$client->setScopes(array('https://www.googleapis.com/auth/userinfo.email','https://www.googleapis.com/auth/userinfo.profile'));
$oauth2Service = new Google_Oauth2Service($client);
$plus = new Google_PlusService($client);
$userinfo = $oauth2Service->userinfo;
print_r($userinfo->get());
if (isset($_GET['code'])) {
try {
$client->authenticate();
} catch(Exception $e) {
$objError->reportError("Error! while authenticate through google",$e ,'dev');
}
$token = $client->getAccessToken();
try {
$userProfile = $plus->people->get("me");
print_r($userProfile);
exit();
} catch(Exception $e) {
//echo $e;
$objError->reportError("Error! while login through google",$e ,'dev');
}
$id = $userProfile['id'];
return array(
'user' => $id,
'network' => 'google',
'userprofile' => $userProfile,
'token' => $token,
'loginUrl' => null,
'logoutUrl' => null
);
} else {
$authUrl = $client->createAuthUrl();
return array(
'user' => 0,
'network' => 'google',
'userprofile' => $userProfile,
'token' => null,
'loginUrl' => $authUrl,
'logoutUrl' => null
);
}
}
So not sure how I can get the email address using google oauth2service. As I tried to access it but no error appearing on screen but also no email address is fatched. I looked at the contrib/Google_Oauth2Service.php class file and don't find the get() method so not sure what I am missing here.
Following two line of code is not returning any email information:
$userinfo = $oauth2Service->userinfo;
print_r($userinfo->get());
My PHP version is 5.3
My Google_Oauth2Service.php file looks like below:
<?php
/*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/**
* The "userinfo" collection of methods.
* Typical usage is:
* <code>
* $oauth2Service = new Google_Oauth2Service(...);
* $userinfo = $oauth2Service->userinfo;
* </code>
*/
class Google_UserinfoServiceResource extends Google_ServiceResource {
/**
* (userinfo.get)
*
* #param array $optParams Optional parameters.
* #return Google_Userinfo
*/
public function get($optParams = array()) {
$params = array();
$params = array_merge($params, $optParams);
$data = $this->__call('get', array($params));
if ($this->useObjects()) {
return new Google_Userinfo($data);
} else {
return $data;
}
}
}
/**
* The "v2" collection of methods.
* Typical usage is:
* <code>
* $oauth2Service = new Google_Oauth2Service(...);
* $v2 = $oauth2Service->v2;
* </code>
*/
class Google_UserinfoV2ServiceResource extends Google_ServiceResource {
}
/**
* The "me" collection of methods.
* Typical usage is:
* <code>
* $oauth2Service = new Google_Oauth2Service(...);
* $me = $oauth2Service->me;
* </code>
*/
class Google_UserinfoV2MeServiceResource extends Google_ServiceResource {
/**
* (me.get)
*
* #param array $optParams Optional parameters.
* #return Google_Userinfo
*/
public function get($optParams = array()) {
$params = array();
$params = array_merge($params, $optParams);
$data = $this->__call('get', array($params));
if ($this->useObjects()) {
return new Google_Userinfo($data);
} else {
return $data;
}
}
}
/**
* Service definition for Google_Oauth2 (v2).
*
* <p>
* Lets you access OAuth2 protocol related APIs.
* </p>
*
* <p>
* For more information about this service, see the
* API Documentation
* </p>
*
* #author Google, Inc.
*/
class Google_Oauth2Service extends Google_Service {
public $userinfo;
public $userinfo_v2_me;
/**
* Constructs the internal representation of the Oauth2 service.
*
* #param Google_Client $client
*/
public function __construct(Google_Client $client) {
$this->servicePath = '';
$this->version = 'v2';
$this->serviceName = 'oauth2';
$client->addService($this->serviceName, $this->version);
$this->userinfo = new Google_UserinfoServiceResource($this,
$this->serviceName, 'userinfo', json_decode('{"methods": {"get": {"id": "oauth2.userinfo.get", "path": "oauth2/v2/userinfo", "httpMethod": "GET", "response": {"$ref": "Userinfo"}, "scopes": ["https://www.googleapis.com/auth/plus.login", "https://www.googleapis.com/auth/plus.me", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"]}}}', true));
$this->userinfo_v2_me = new Google_UserinfoV2MeServiceResource($this, $this->serviceName, 'me', json_decode('{"methods": {"get": {"id": "oauth2.userinfo.v2.me.get", "path": "userinfo/v2/me", "httpMethod": "GET", "response": {"$ref": "Userinfo"}, "scopes": ["https://www.googleapis.com/auth/plus.login", "https://www.googleapis.com/auth/plus.me", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"]}}}', true));
}
}
class Google_Tokeninfo extends Google_Model {
public $access_type;
public $audience;
public $email;
public $expires_in;
public $issued_to;
public $scope;
public $user_id;
public $verified_email;
public function setAccess_type( $access_type) {
$this->access_type = $access_type;
}
public function getAccess_type() {
return $this->access_type;
}
public function setAudience( $audience) {
$this->audience = $audience;
}
public function getAudience() {
return $this->audience;
}
public function setEmail( $email) {
$this->email = $email;
}
public function getEmail() {
return $this->email;
}
public function setExpires_in( $expires_in) {
$this->expires_in = $expires_in;
}
public function getExpires_in() {
return $this->expires_in;
}
public function setIssued_to( $issued_to) {
$this->issued_to = $issued_to;
}
public function getIssued_to() {
return $this->issued_to;
}
public function setScope( $scope) {
$this->scope = $scope;
}
public function getScope() {
return $this->scope;
}
public function setUser_id( $user_id) {
$this->user_id = $user_id;
}
public function getUser_id() {
return $this->user_id;
}
public function setVerified_email( $verified_email) {
$this->verified_email = $verified_email;
}
public function getVerified_email() {
return $this->verified_email;
}
}
class Google_Userinfo extends Google_Model {
public $birthday;
public $email;
public $family_name;
public $gender;
public $given_name;
public $hd;
public $id;
public $link;
public $locale;
public $name;
public $picture;
public $timezone;
public $verified_email;
public function setBirthday( $birthday) {
$this->birthday = $birthday;
}
public function getBirthday() {
return $this->birthday;
}
public function setEmail( $email) {
$this->email = $email;
}
public function getEmail() {
return $this->email;
}
public function setFamily_name( $family_name) {
$this->family_name = $family_name;
}
public function getFamily_name() {
return $this->family_name;
}
public function setGender( $gender) {
$this->gender = $gender;
}
public function getGender() {
return $this->gender;
}
public function setGiven_name( $given_name) {
$this->given_name = $given_name;
}
public function getGiven_name() {
return $this->given_name;
}
public function setHd( $hd) {
$this->hd = $hd;
}
public function getHd() {
return $this->hd;
}
public function setId( $id) {
$this->id = $id;
}
public function getId() {
return $this->id;
}
public function setLink( $link) {
$this->link = $link;
}
public function getLink() {
return $this->link;
}
public function setLocale( $locale) {
$this->locale = $locale;
}
public function getLocale() {
return $this->locale;
}
public function setName( $name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function setPicture( $picture) {
$this->picture = $picture;
}
public function getPicture() {
return $this->picture;
}
public function setTimezone( $timezone) {
$this->timezone = $timezone;
}
public function getTimezone() {
return $this->timezone;
}
public function setVerified_email( $verified_email) {
$this->verified_email = $verified_email;
}
public function getVerified_email() {
return $this->verified_email;
}
}
Thanks
I don't know how you're using this but I've tried with v1-master branch of google apiclient and I'm able to fetch user's email address
$client = new Google_Client();
$client->setApplicationName('Login to Test Project');
$client->setClientId(GOOGLE_CLIENT_ID);
$client->setClientSecret(GOOGLE_CLIENT_SECRET);
$client->setRedirectUri(GOOGLE_REDIRECT_URL);
$client->addScope(['email', 'profile']);
if (isset($_GET['code'])) {
try {
$token = $client->authenticate($_GET['code']);
$Oauth = new Google_Service_Oauth2($client);
$info = $Oauth->userinfo->get();
print_r($info);
} catch (Exception $exception) {
print_r($exception->getMessage());
}
} else {
$authUrl = $client->createAuthUrl();
header('Location: '.$authUrl);
}
Please share your composer.json file, so that I can try with your configurations to provide a better solution.
I noticed a couple things on your end that could be causing you some grief. Your order of operations seems to be reversed. You shouldn't be calling this:
$userinfo = $oauth2Service->userinfo;
print_r($userinfo->get());
before this:
$client->authenticate();
Also, you should be sending the code along with the client.
So, something like this should get you some proper output:
if (isset($_GET['code'])) {
$code = $_GET['code'];
try {
$client->authenticate($code);
} catch(Exception $e) {
$objError->reportError("Error! while authenticate through google",$e ,'dev');
}
$userinfo = $oauth2Service->userinfo;
print_r($userinfo->get());
}
Give that a try, and then let us know if you're on the right track. Also, Google Plus has been deprecated, so I would recommend you don't use those libraries any longer.
i have a problem i dont know how to stop it. i have an infinite loop on a redirect route, i tried to redirect a user if he has not accept some condition
this is my code :
/**
* AcceptanceListener constructor.
* #param $router
* #param TokenStorageInterface $tokenStorage
* #param UserManager $userManager
* #param AuthorizationChecker $checker
*/
public function __construct(
$router,
TokenStorageInterface $tokenStorage,
UserManager $userManager,
AuthorizationChecker $checker
) {
$this->router = $router;
$this->tokenStorage = $tokenStorage;
$this->userManager = $userManager;
$this->role = $checker;
}
/**
* To checked all the routes
*
* #param GetResponseEvent $event
*/
public function onKernelRequest(GetResponseEvent $event)
{
$user = $this->tokenStorage->getToken()->getUser();
if ($this->role->isGranted('ROLE_USER')
&& !$this->userManager->hasAccepted($user)
) {
$this->redirect = $this->router->generate('accept_');
$event->setResponse(new RedirectResponse($this->redirect));
}
}
someone can help me please?
Check if the route is not the same, then redirect
public function onKernelRequest(GetResponseEvent $event)
{
$route_name = $event->getRequest()->get('_route');
if ($route_name != 'accept_') {
$user = $this->tokenStorage->getToken()->getUser();
if ($this->role->isGranted('ROLE_USER')
&& !$this->userManager->hasAccepted($user)
) {
$this->redirect = $this->router->generate('accept_');
$event->setResponse(new RedirectResponse($this->redirect));
}
}
}
The problem
I want users to be authenticated via an access token that is supplied as a GET parameter to the first request.
I have never implemented such a thing in Symfony, so I followed the steps outlined in How to Create a custom Authentication Provider, but it 'doesn't work'. The authenticate method of the AuthenticationProviderInterface is not triggered.
What I have tried
Because it is a lot of configuration mostly, I don't even know how to debug this. This is what I have concluded so far: Only the AccessTokenProvider gets constructed, nothing else.
The code
These are the relevant parts of the system:
security.yml
security:
# Snip default (empty) in_memory provider
firewalls:
# Snip dev and main (symfony default)
accesstoken_secured:
pattern: ^/admin/
accesstoken: true
services.yml
services:
accesstoken.security.authentication.provider:
class: AppBundle\Security\Authentication\Provider\AccessTokenProvider
arguments:
- '' # User Provider
- '%kernel.cache_dir%/security/nonces'
public: false
accesstoken.security.authentication.listener:
class: AppBundle\Security\Firewall\AccessTokenListener
arguments: ['#security.token_storage', '#security.authentication.manager']
public: false
AccessTokenFactory
class AccessTokenFactory implements SecurityFactoryInterface
{
public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
{
$providerId = 'security.authentication.provider.accesstoken.'.$id;
$container
->setDefinition($providerId, new DefinitionDecorator('accesstoken.security.authentication.provider'))
->replaceArgument(0, new Reference($userProvider))
;
$listenerId = 'security.authentication.listener.accesstoken.'.$id;
$container->setDefinition($listenerId, new DefinitionDecorator('accesstoken.security.authentication.listener'));
return array($providerId, $listenerId, $defaultEntryPoint);
}
public function getPosition()
{
return 'pre_auth';
}
public function getKey()
{
return 'accesstoken';
}
public function addConfiguration(NodeDefinition $node)
{
}
}
AccessTokenProvider
class AccessTokenProvider implements AuthenticationProviderInterface
{
private $userProvider;
public function __construct(UserProviderInterface $userProvider)
{
$this->userProvider = $userProvider;
}
public function authenticate(TokenInterface $token)
{
$user = $this->userProvider->loadUserByAccessToken($token->getAttribute('token'));
if ($this->isTokenValid($token)) {
$authenticatedToken = new AccessToken(['role_user']);
$authenticatedToken->setUser($user);
return $authenticatedToken;
}
throw new AuthenticationException('The WSSE authentication failed.');
}
protected function isTokenValid(AccessToken $token)
{
//TODO: Implement
return (bool)$token->token;
}
public function supports(TokenInterface $token)
{
return $token instanceof AccessToken;
}
}
AccessTokenListener
class AccessTokenListener
{
protected $tokenStorage;
protected $authenticationManager;
/**
* AccessTokenListener constructor.
* #param TokenStorageInterface $tokenStorage
* #param AuthenticationManagerInterface $authenticationManager
*/
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager)
{
$this->tokenStorage = $tokenStorage;
$this->authenticationManager = $authenticationManager;
}
public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();
$accesstoken = $request->get('accesstoken');
$token = new AccessToken();
$token->token = $accesstoken;
try {
$authToken = $this->authenticationManager->authenticate($token);
$this->tokenStorage->setToken($authToken);
return;
} catch (AuthenticationException $failed) {
// ... you might log something here
}
// By default deny authorization
$response = new Response();
$response->setStatusCode(Response::HTTP_FORBIDDEN);
$event->setResponse($response);
}
}
AccessToken
class AccessToken extends AbstractToken
{
public $token;
/**
* AccessToken constructor.
* #param array $roles
*/
public function __construct(array $roles = array())
{
parent::__construct($roles);
// If the user has roles, consider it authenticated
$this->setAuthenticated(count($roles) > 0);
}
/**
* Returns the user credentials.
*
* #return mixed The user credentials
*/
public function getCredentials()
{
return '';
}
}
I eventually tried to implement it in another way, using the tutorial at How to Create a Custom Authentication System with Guard.
This uses Symfony's new Guard system. It was actually very easy to setup!
I have the following authentication handler:
class LoginAuthSuccessHandler implements AuthenticationSuccessHandlerInterface, AuthenticationFailureHandlerInterface
{
private $router;
private $container;
/**
* Constructor
* #param RouterInterface $router
*/
public function __construct(RouterInterface $router, $container)
{
$this->router = $router;
$this->container = $container;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
if ($request->isXmlHttpRequest()) {
$user = $this->container->get('security.context')->getToken()->getUser();
$result = array('success' => true, 'user' => $user);
return new Response(json_encode($result));
} else {
$route = $this->router->generate('ShopiousMainBundle_profile');
$referrer_url = $request->server->get('HTTP_REFERER');
if (strstr($referrer_url, '/items/')) {
$route = $referrer_url;
}
return new RedirectResponse($route);
}
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
if ($request->isXmlHttpRequest()) {
$result = array('success' => false, 'message' => $exception->getMessage());
return new Response(json_encode($result));
} else {
// Handle non XmlHttp request here
}
}
}
why is it that:
$user = $this->container->get('security.context')->getToken()->getUser();
returns null? how do i get the authenticated user at this point?
You should use the $token variable you are receiving as an argument instead of $this->container->get('security.context')->getToken().
$user = $token->getUser();
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
$user = $token->getUser();
}
that's all ;)
maibe you don't set your provider in security.yml.
security:
provider:
example:
entity: {class Acme\AuctionBundle\Entity\User, property: username}
Replace the Bundle and the entity by yours.
The only way I found was to inject the entityManager,
calls:
- [setEntityManager,[#doctrine.orm.entity_manager]]
get the username from the request and query for the user, using that username.
$userRepo->findByEmail($request->get('_username'));