I don't understand my problem. I just want :
/ redirected /home
/home is not secured but logged user is able to navigate into
the whole website.
Non authenticated user is only able to see the homepage
People can register an account to access the whole website
So it's my security.yml config :
security:
encoders:
Siriru\AntBundle\Entity\User: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
main:
entity: { class: Siriru\AntBundle\Entity\User, property: username }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
root:
pattern: ^/$
security: false
home:
pattern: ^/home$
security: false
login:
pattern: ^/login$
security: false
register:
pattern: ^/account/
security: false
secured_area:
pattern: ^/
form_login:
check_path: /login_check
login_path: /login
username_parameter: username
password_parameter: password
logout:
path: /logout
target: /home
Registration is ok, login too. But after the redirection to the homepage, user is not authenticated (in the symfony profiler "You are not authenticated."). If I reach the secured area, i'm logged but not authenticated.
<?php
namespace Siriru\AntBundle\Controller;
use Siriru\AntBundle\Form\Model\Registration;
use Siriru\AntBundle\Form\Type\RegistrationType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use JMS\SecurityExtraBundle\Annotation\Secure;
class AccountController extends Controller
{
/**
* #Route("/login", name="login")
* #Template()
*/
public function loginAction()
{
if ($this->get('request')->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $this->get('request')->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} else {
$error = $this->get('request')->getSession()->get(SecurityContext::AUTHENTICATION_ERROR);
}
return array(
'last_username' => $this->get('request')->getSession()->get(SecurityContext::LAST_USERNAME),
'error' => $error,
);
}
/**
* #Route("/login_check", name="login_check")
*/
public function securityCheckAction()
{
// The security layer will intercept this request
}
/**
* #Route("/logout", name="logout")
*/
public function logoutAction()
{
// The security layer will intercept this request
}
/**
* #Route("/account/register", name="account_register")
* #Template()
*/
public function registerAction()
{
$form = $this->createForm(new RegistrationType(), new Registration());
return array('form' => $form->createView());
}
/**
* #Route("/account/create", name="account_create")
* #Template()
*/
public function createAction()
{
$em = $this->getDoctrine()->getEntityManager();
$form = $this->createForm(new RegistrationType(), new Registration());
$form->bind($this->getRequest());
if ($form->isValid()) {
$registration = $form->getData();
$user = $registration->getUser();
$factory = $this->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$password = $encoder->encodePassword($user->getPassword(), $user->getSalt());
$user->setPassword($password);
$em->persist($user);
$em->flush();
return $this->redirect($this->generateUrl('homepage'));
}
return $this->render('SiriruAntBundle:Account:register.html.twig', array('form' => $form->createView()));
}
}
I need some help =) Thank you.
Try to change your firewall configuration to catch all the urls, then set anonymous: ~ and use access_control to restrict all the urls to ROLE_USER.
The problem is that the security session is not shared by default between different firewalls.
Something like this should work:
security:
encoders:
Siriru\AntBundle\Entity\User: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
main:
entity: { class: Siriru\AntBundle\Entity\User, property: username }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
anonymous: ~
form_login:
check_path: /login_check
login_path: /login
username_parameter: username
password_parameter: password
logout:
path: /logout
target: /home
access_control:
- { path: ^/$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/home$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
Related
I'm using HWIOAuthBundle with Symfony 4.1.
My custom user provider gets called and returns a valid user, however the user is not logged in after the redirect. The web profiler shows: logged in as anon; anonymous token; firewall main
I've simplified the provider class below for brevity and it's only considering twitter right now. The conditions around $source are so I can add more later.
I have used xdebug to make sure loadUserByOauthuserResponse() is being called and that users are both being created in the case of a new user, or the existing user is being returned when it exists.
Question: If loadUserbyOauthUserResponse() IS returning a valid user entity, then what could be preventing it from creating a valid session with this user?
<?php
namespace App\Security;
...
class OAuthProvider extends OAuthUserProvider
{
...
public function loadUserByOAuthUserResponse(UserResponseInterface $response): User
{
/** #var EntityManager $em */
$em = $this->container->get('doctrine.orm.entity_manager');
$repo = $em->getRepository('App:User');
$source = $response->getResourceOwner()->getName();
$email = null;
$data = [];
$newUser = false;
// Set email and socialUser.
if ($source === 'twitter') {
$data = $response->getData();
$email = $data['email'];
}
// Check if this user already exists in our app.
$user = $repo->findOneBy(['email' => $email]);
if ($user === null) {
$newUser = true;
$user = new User();
$user->setPassword($this->strand(32));
}
// Set session and user data based on source.
if ($source === 'twitter') {
$name = $data['name'];
if ($newUser) {
$user->setNickName($name);
$user->setEmail($email);
$em->persist($user);
$em->flush();
}
}
return $user;
}
}
hwi_oauth.yaml
hwi_oauth:
# list of names of the firewalls in which this bundle is active, this setting MUST be set
firewall_names: [main]
# https://github.com/hwi/HWIOAuthBundle/blob/master/Resources/doc/2-configuring_resource_owners.md
resource_owners:
twitter:
type: twitter
client_id: '%env(TWITTER_ID)%'
client_secret: '%env(TWITTER_SECRET)%'
options:
include_email: true
services.yaml:
app.oauth_aware.user_provider.service:
class: App\Security\OAuthProvider
arguments: ['#service_container']
security.yaml:
security:
# https://symfony.com/doc/current/book/security.html#where-do-users-come-from-user-providers
encoders:
App\Entity\User: bcrypt
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
app_users:
entity: { class: App\Entity\User, property: email }
hwi:
id: app.oauth_aware.user_provider.service
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
provider: app_users
anonymous: ~
remember_me:
secret: "%env(APP_SECRET)%"
lifetime: 2592000
path: /
guard:
authenticators:
- App\Security\LoginFormAuthenticator
entry_point: App\Security\LoginFormAuthenticator
logout:
path: /logout
target: /
oauth:
resource_owners:
twitter: "/login/check-twitter"
default_target_path: /
login_path: /
failure_path: /user-login
oauth_user_provider:
service: app.oauth_aware.user_provider.service
switch_user: ~
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/recover, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
I had the same problem until I found in logs "Token was deauthenticated after trying to refresh it."
And after that I found this solution.
Token was deauthenticated after trying to refresh it
I added isEqualTo and did not logged me out.
To get started with security, check out the documentation:
https://symfony.com/doc/current/security.html
security:
encoders:
AppBundle\Entity\Usuario:
algorithm: bcrypt
# https://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded
providers:
db_provider:
entity:
class: AppBundle:Usuario
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
form_login:
login_path: login
check_path: login
default_target_path: admin
logout:
path: logout
target: index
remember_me:
secret: '%secret%'
lifetime: 604800 # 1 week in seconds
path: /
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONIMOUSLY }
- { path: ^/admin, roles: IS_AUTHENTICATED_FULLY }
/**
* #Route("/login", name="login")
*/
public function loginAction(AuthenticationUtils $authUtils)
{
// get the login error if there is one
$error = $authUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authUtils->getLastUsername();
$msg = '';
if ($error != null) {
$msg = 'Login ou Senha Inválidos!';
}
return $this->render($this->urlPage.'index.html.twig', array(
'errorMsg' => $msg,
));
}
/**
* #Route("/admin", name="admin")
*/
public function adminAction(AuthorizationCheckerInterface $authChecker)
{
$authChecker = $this->get('security.authorization_checker');
if ($authChecker->isGranted('ROLE_USUARIO')) {
return $this->redirectToRoute('principal');
} else if ($authChecker->isGranted('ROLE_CLIENTE')){
return $this->redirectToRoute('principal');
} else {
return $this->redirectToRoute('index');
}
}
Authenticated: No appears in the Symfony2 dev toolbar after a successful login.
In my success handler I can access $token->getRoles() and see the role objects assigned to the user so it appears to be serializing okay.
So I'm not sure why it's not authenticating.
Here is my security.yml:
security:
encoders:
FixedApp\Model\User:
algorithm: sha1
encode_as_base64: false
iterations: 1
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_LIMITED_ADMIN]
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
administrators:
entity: { class: FixedApp\Model\User, property: username }
firewalls:
dev:
pattern: ^/(_(profiler|wdt|error)|css|images|js)/
security: false
login:
pattern: ^/$
security: false
secured_area:
pattern: ^/
form_login:
check_path: fixed_app_authentication_login
login_path: fixed_app_homepage
username_parameter: form[username]
password_parameter: form[password]
default_target_path: fixed_app_hub_homepage
always_use_default_target_path: true
success_handler: security.authentication.success_handler
logout:
path: fixed_app_authentication_logout
target: fixed_app_homepage
access_control:
- { path: ^/log-in$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /users/edit, roles: ROLE_ADMIN }
It not authenticating is a problem, because when I go to /users/edit as an admin it says Access Denied. So I need to figure out what is going on here. Any ideas would be most appreciated.
I saw a number of other people online with this same problem but I've never seen a solution put anywhere before - so hopefully this helps someone.
In UserRole.php class I was missing this function:
/**
* #see RoleInterface
*/
public function getRole()
{
return $this->role;
}
And secondly, in User.php class I made it implement EquatableInterface:
use Symfony\Component\Security\Core\User\EquatableInterface;
use Symfony\Component\Security\Core\User\UserInterface;
...
class User implements AdvancedUserInterface, EquatableInterface, \Serializable
{
...
public function isEqualTo(UserInterface $user)
{
if ($this->getId() == $user->getId())
{
return true;
}
else
{
return false;
}
}
And then it started working. The Symfony toolbar button went green, it says Authenticated: Yes and it lists all the roles for that user.
I want to programmatically log in an user using the FOSRestBundle (I am not using FOSUserBundle). It seems to work, but when I logged in successfully and try to access an secured endpoint, Symfony throws an AccessDeniedException.
This is my security.yml:
security:
providers:
main:
entity:
class: DepartureMonitor\RestBundle\Entity\User
property: email
role_hierarchy:
ROLE_EDITOR: [ ROLE_USER ]
ROLE_VU_ADMIN: [ ROLE_EDITOR, ROLE_USER ]
ROLE_ADMIN: [ ROLE_VU_ADMIN ]
encoders:
DepartureMonitor\RestBundle\Entity\User:
algorithm: bcrypt
cost: 13
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
rest:
pattern: ^/api
provider: main
anonymous: true
form_login:
login_path: login
check_path: login_check
logout: ~
access_control:
- { path: ^/api/users/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/users/password, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: ROLE_USER }
In my UsersController I have the following action:
/**
* #Post("/users/login")
*/
public function loginAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('DepartureMonitorRestBundle:User')->findOneBy(array('email' => $request->request->get('username')));
if ($user instanceof User) {
$factory = $this->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$pw = $encoder->encodePassword($request->request->get('password'), $user->getSalt());
if($pw === $user->getPassword()) {
$token = new UsernamePasswordToken($user, $pw, "main", $user->getRoles());
$this->get('security.context')->setToken($token);
$event = new \Symfony\Component\Security\Http\Event\InteractiveLoginEvent($request, $token);
$this->get('event_dispatcher')->dispatch('security.interactive_login', $event);
if(!($this->getUser() instanceof User)) {
return $this->view(array('code' => HttpStatusCode::NOT_FOUND, 'message' => $this->get('translator')->trans('error.messages.bad_credentials')), HttpStatusCode::NOT_FOUND);
}
$view = $this->view($user, HttpStatusCode::CREATED);
$view->setSerializationContext(SerializationContext::create()->setGroups(array('login')));
return $this->handleView($view);
}
}
return $this->view(array('code' => HttpStatusCode::NOT_FOUND, 'message' => $this->get('translator')->trans('error.messages.bad_credentials')), HttpStatusCode::NOT_FOUND);
}
I don't know what the problem here is.
Any help is very appreciated.
I try to authenticate user:
<?php
/**
* #Route("/testLogin", name="testLogin")
*/
public function testLoginAction()
{
$em = $this->getDoctrine()->getEntityManager();
$user = $em->getRepository('ApplicationDefaultBundle:User')->findOneBy(array('id' => 126));
$providerKey = 'main';
$token = new UsernamePasswordToken($user, null, $providerKey, $user->getRoles());
$this->container->get('security.context')->setToken($token);
return $this->redirect($this->generateUrl('testCheck'));
}
/**
* #Route("/testCheck", name="testCheck")
*/
public function testCheckAction()
{
if (false === $this->get('security.context')->isGranted(
'IS_AUTHENTICATED_REMEMBERED'
)) {
return new Response('Not logged');
}
$user = $this->container->get('security.context')->getToken()->getUser();
return new Response($user->getUsername.' is logged');
}
But I get permanent 302 redirect to /login page.
security:
encoders:
Application\Bundle\DefaultBundle\Entity\User:
algorithm: sha512
iterations: 24
encode_as_base64: true
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SPECIALIST: ROLE_USER
ROLE_EMPLOYER: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
main:
entity: { class: Application\Bundle\DefaultBundle\Entity\User, property: username }
firewalls:
secured_area:
remember_me:
key: MySecretKeyBlablabla
lifetime: 36000000
path: /
domain: ~
pattern: ^/
form_login:
check_path: /login_check
login_path: /login
provider: main
logout:
path: /logout
target: /
anonymous: true
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
Code for authenticate I take from https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Controller/RegistrationController.php
Error in app/logs/dev.log:
redirecting to authentication entry point (No Authentication Provider found for token of class "Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken".) [] []
I can't access to site until I clean cookies.
Try code from this answer. In your case firewall name is secured_area:
// your controller action
public function myAction()
{
// Authenticating user
$token = new UsernamePasswordToken($user, null, 'secured_area', $user->getRoles());
$this->get('security.token_storage')->setToken($token);
//For Symfony <= 2.3
//$this->get('security.context')->setToken($token);
$this->get('session')->set('_security_secured_area', serialize($token));
}
Verify that you have configured encoders section in security.yml, as configuration there has changed not very long time ago and it affects your problem.