Bad credentials with Fosuser symfony2 - symfony

I'm trying since 3 hours to install and configure FOSuser, which many developpers adviced me to use it.I wanted actually to make a normal login form without to use FOS but I had a lot of problems.I followed all steps in the documentation. the installation was ok , the configuration also but everytime when I try to log in , it shows "Bad credentials".So i find somehow this command that I executed :php app/console fos:user:create i give name-email-password. it work somehow but only with what i write, I mean when I register user in my registration form and try to log in it shows "Bad credentials".I hope that I was clear else please tell me what do you need to know
Here are my Users.php where i have all my users info to login...
namespace test\indexBundle\Document;
use FOS\UserBundle\Model\User as BaseUser;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/**
*
* #MongoDB\Document
*/
class Users extends BaseUser
{
/**
* #MongoDB\Id
*/
protected $id;
/**
* #MongoDB\String
*/
protected $userId;
/**
* #MongoDB\String
*/
protected $userEmail;
/**
* #MongoDB\String
*/
protected $userPassword;
/**
* #MongoDB\String
*/
protected $salt;
/**
* #MongoDB\Int
*/
protected $isActive;
public function __construct()
{
parent::__construct();
$this->isActive = true;
$this->salt = md5(uniqid(null, true));
}
/**
* Set id
*
* #param id $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* Get id
*
* #return id $id
*/
public function getId()
{
return $this->id;
}
/**
* Set userId
*
* #param string $userId
*/
public function setUserId()
{
$this->userId = $this->salt;
}
/**
* Get userId
*
* #return string $userId
*/
public function getUserId()
{
return $this->userId;
}
/**
* Set userName
*
* #param string $userName
*/
public function setUserName($userName)
{
$this->userName = $userName;
}
/**
* Get userName
*
* #return string $userName
*/
public function getUserName()
{
return $this->username;
}
/**
* Set userEmail
*
* #param string $userEmail
*/
public function setUserEmail($userEmail)
{
$this->userEmail = $userEmail;
}
/**
* Get userEmail
*
* #return string $userEmail
*/
public function getUserEmail()
{
return $this->userEmail;
}
/**
* Set userPassword
*
* #param string $userPassword
*/
public function setPassword($userPassword)
{
$this->userPassword = $userPassword;
}
/**
* Get userPassword
*
* #return string $userPassword
*/
public function getPassword()
{
return $this->userPassword;
}
/**
* #inheritDoc
*/
public function getSalt()
{
return '';
}
/**
* #inheritDoc
*/
public function getRoles()
{
return array('ROLE_USER');
}
/**
* #inheritDoc
*/
public function eraseCredentials()
{
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
return serialize(array(
$this->id
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list (
$this->id
) = unserialize($serialized);
}
}
and here my security.yml:
jms_security_extra:
secure_all_services: false
expressions: true
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
test\indexBundle\Document\Users:
algorithm: sha1
encode_as_base64: false
iterations: 1
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
anonymous: true
form_login:
check_path: /login_check
login_path: /login
provider: fos_userbundle
post_only: true
use_forward: false
username_parameter: email
password_parameter: password
failure_path: null
failure_forward: false
target_path_parameter: redirect_url
logout:
path: /logout
target: /blog
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
and login function:
public function loginAction()
{
$request = $this->getRequest();
$session = $request->getSession();
if ($this->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY'))
{
return $this->redirect($this->generateUrl('index_homepage'));
}
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR))
{
$error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
}
else
{
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
return $this->render('indexBundle:index:logIn.html.twig', array(
'last_username' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error,
));
}

I might be wrong but I think FOSUserBundle requires a user to be activated after it's been created if you use the form registration, it's send out and email with a link I believe. I think you can use app/console fos:user:activate to activate if there is no email.

Related

Symfony 4 Security - how to configure a custom Guard authenticator?

I have setup my own login form in a security controller. to use the LoginForm I have configured this in the security configuration.
I want to use a custom login form authenticator to have more control over the authentication progress, register logins in the system,
and do anything I'd like to add (IP-check etc, etc...)
So there is also a LoginFormAuthenticator class in my application. somehow the authentication process doesn't even seem to use the methods of
the custom LoginFormAuthenticator. Is my security.yaml configured properly? how do I get all my configuration to work together?
The security in symfony seems so messy at some points, I can't begin to understand how people manage to properly configure it..
LoginFormAuthenticator:
class LoginFormAuthenticator extends AbstractGuardAuthenticator
{
/**
* Constructor
*
* #param Logger $logger
* #param LoginAttemptManagerInterface $loginAttemptManager
* #param LocationManagerInterface $locationManager
* #param RouterInterface $router
* #param UserPasswordEncoderInterface $userPasswordEncoder
* #param UserRepositoryInterface $userRepository
*/
public function __construct(Logger $logger, LoginAttemptManagerInterface $loginAttemptManager, LocationManagerInterface $locationManager, RouterInterface $router, UserPasswordEncoderInterface $userPasswordEncoder, UserRepositoryInterface $userRepository)
{
$this->_logger = $logger;
$this->_loginAttemptManager = $loginAttemptManager;
$this->_locationManager = $locationManager;
$this->_router = $router;
$this->_userPasswordEncoder = $userPasswordEncoder;
$this->_userRepository = $userRepository;
}
/**
* {#inheritdoc}
*/
protected function getLoginUrl()
{
return $this->_router->generate("login");
}
/**
* {#inheritdoc}
*/
public function getCredentials(Request $request)
{
$credentials = $request->get("login_form");
return [
"username" => $credentials["username"],
"password" => $credentials["password"],
"token" => $credentials["_token"],
];
}
/**
* {#inheritdoc}
*/
public function getUser($credentials, UserProviderInterface $userProvider)
{
$username = $credentials["username"];
try {
$user = $this->_userRepository->findOneByUsername($username);
if (null !== $user && $user instanceof UserInterface) {
/* #var LoginAttempt $loginAttempt */
$loginAttempt = $this->_loginAttemptManager->create();
$user->addLoginAttempt($loginAttempt);
}
}
catch (NoResultException $e) {
return null;
}
catch (NonUniqueResultException $e) {
return null;
}
catch (UsernameNotFoundException $e) {
return null;
}
}
/**
* {#inheritdoc}
*/
public function checkCredentials($credentials, UserInterface $user)
{
/* #var string $rawPassword the unencoded plain password */
$rawPassword = $credentials["password"];
if ($this->_userPasswordEncoder->isPasswordValid($user, $rawPassword)) {
return true;
}
return new CustomUserMessageAuthenticationException("Invalid credentials");
}
/**
* {#inheritdoc}
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
/* #var AbstractUser $user */
$user = $token->getUser();
/* #var LoginAttempt $loginAttempt */
$loginAttempt = $user->getLastLoginAttempt();
$loginAttempt->success();
this->_loginAttemptManager->saveOne($loginAttempt, true);
}
/**
* {#inheritdoc}
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
// without this method the authentication process becomes a loop
}
/**
* {#inheritdoc}
*/
public function start(Request $request, AuthenticationException $authException = null)
{
return new RedirectResponse($this->getLoginUrl());
}
/**
* {#inheritdoc}
*/
public function supports(Request $request)
{
return $request->getPathInfo() != $this->getLoginUrl() || !$request->isMethod(Request::METHOD_POST);
}
/**
* {#inheritdoc}
*/
public function supportsRememberMe()
{
return true;
}
}
SecurityController:
class SecurityController extends AbstractController
{
/**
* #Route(path = "login", name = "login", methods = {"GET", "POST"})
* #Template(template = "security/login.html.twig")
*
* #param AuthenticationUtils $authUtils
* #param Request $request
* #return array
*/
public function login(AuthenticationUtils $authUtils, Request $request)
{
$form = $this->createLoginForm();
if (null !== $authUtils->getLastAuthenticationError()) {
$form->addError(new FormError(
$this->_translator->trans("error.authentication.incorrect-credentials", [], "security")
));
}
if (null != $authUtils->getLastUsername()) {
$form->setData([
"username" => $authUtils->getLastUsername(),
]);
}
// settings are in config/packages/security.yaml
// configuration authenticates user in login form authenticator service
return [
"backgroundImages" => $this->_backgroundImageManager->findAll(),
"form" => $form->createView(),
];
}
/**
* #return FormInterface
*/
private function createLoginForm() : FormInterface
{
$form = $this->createForm(LoginForm::class, null, [
"action" => $this->generateUrl("login"),
"method" => Request::METHOD_POST,
]);
$form->add("submit", SubmitType::class, [
"label" => $this->_translator->trans("btn.login", [], "button"),
"icon_name" => "sign-in",
"translation_domain" => false,
]);
return $form;
}
}
security.yaml:
security:
providers:
user_provider:
entity:
class: App\Entity\Model\AbstractUser
property: username
oauth_provider:
entity:
class: App\Entity\Model\ApiClient
property: name
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
# The API-Oauth-Token-Firewall must be above the API-firewall
api_oauth_token:
pattern: ^/api/oauth/token$
security: false
# The API-firewall must be above the Main-firewall
api:
pattern: ^/api/*
security: true
stateless: true
oauth2: true
provider: oauth_provider
access_denied_handler: App\Service\Api\Security\ApiAccessDeniedHandler
main:
anonymous: true
guard:
authenticators:
- App\Service\Security\LoginFormAuthenticator
access_denied_handler: App\Service\Security\AccessDeniedHandler
provider: user_provider
form_login:
login_path: /login
check_path: /login
default_target_path: / #index
username_parameter: "login_form[username]"
password_parameter: "login_form[password]"
logout:
# the logout path overrides the implementation of the logout method
# in the security controller
path: /logout
target: / #index
remember_me:
secret: '%kernel.secret%'
lifetime: 43200 # 60 sec * 60 min * 12 hours
path: /
remember_me_parameter: "login_form[remember]"
encoders:
App\Entity\Model\AbstractUser:
algorithm: bcrypt
cost: 13
access_control:
# omitted from this question
role_hierarchy:
# omitted from this question
How did you come up with the logic of LoginFormAuthenticator::supports()?
shouldn't this be the opposite like:
return 'login' === $request->attributes->get('_route')
&& $request->isMethod('POST');
Apparently I had two forms of authentication configured in security.yaml
So I've removed the form_login key from the config:
security.yaml
security:
providers:
user_provider:
entity:
class: App\Entity\Model\AbstractUser
property: username
oauth_provider:
entity:
class: App\Entity\Model\ApiClient
property: name
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
# The API-Oauth-Token-Firewall must be above the API-firewall
api_oauth_token:
pattern: ^/api/oauth/token$
security: false
# The API-firewall must be above the Main-firewall
api:
pattern: ^/api/*
security: true
stateless: true
oauth2: true
provider: oauth_provider
access_denied_handler: App\Service\Api\Security\ApiAccessDeniedHandler
main:
anonymous: true
guard:
authenticators:
- App\Service\Security\LoginFormAuthenticator
access_denied_handler: App\Service\Security\AccessDeniedHandler
provider: user_provider
logout:
# the logout path overrides the implementation of the logout method
# in the security controller
path: /logout
target: / #index
remember_me:
secret: '%kernel.secret%'
lifetime: 43200 # 60 sec * 60 min * 12 hours
path: /
remember_me_parameter: "login_form[remember]"
And updated the LoginFormAuthenticator
- integrated
- also added checking CSRF token
LoginFormAuthenticator
class LoginFormAuthenticator extends AbstractGuardAuthenticator
{
const FORM = "login_form";
const USERNAME = "username";
const PASSWORD = "password";
const CSRF_TOKEN = "token";
/**
* Constructor
*
* #param CsrfTokenManagerInterface $csrfTokenManager
* #param Logger $logger
* #param LoginAttemptManagerInterface $loginAttemptManager
* #param LocationManagerInterface $locationManager
* #param RouterInterface $router
* #param UserPasswordEncoderInterface $userPasswordEncoder
* #param UserRepositoryInterface $userRepository
*/
public function __construct(CsrfTokenManagerInterface $csrfTokenManager, Logger $logger, LoginAttemptManagerInterface $loginAttemptManager, LocationManagerInterface $locationManager, RouterInterface $router, UserPasswordEncoderInterface $userPasswordEncoder, UserRepositoryInterface $userRepository)
{
$this->_csrfTokenManager = $csrfTokenManager;
$this->_logger = $logger;
$this->_loginAttemptManager = $loginAttemptManager;
$this->_locationManager = $locationManager;
$this->_router = $router;
$this->_userPasswordEncoder = $userPasswordEncoder;
$this->_userRepository = $userRepository;
}
/**
* Get Login URL
*
* #return string
*/
protected function getLoginUrl()
{
return $this->_router->generate("login");
}
/**
* Get Target URL
*
* #return string
*/
protected function getTargetUrl()
{
return $this->_router->generate("index");
}
/**
* {#inheritdoc}
*/
public function getCredentials(Request $request)
{
$credentials = $request->request->get(self::FORM);
$request->getSession()->set(Security::LAST_USERNAME, $credentials["username"]);
return [
self::USERNAME => $credentials["username"],
self::PASSWORD => $credentials["password"],
self::CSRF_TOKEN => $credentials["_token"],
];
}
/**
* {#inheritdoc}
*/
public function getUser($credentials, UserProviderInterface $userProvider)
{
$username = $credentials[self::USERNAME];
try {
$user = $this->_userRepository->findOneByUsername($username);
if (null !== $user && $user instanceof UserInterface) {
/* #var LoginAttempt $loginAttempt */
$loginAttempt = $this->_loginAttemptManager->create();
$user->addLoginAttempt($loginAttempt);
}
return $user;
}
catch (NoResultException $e) {
throw new BadCredentialsException("Authentication failed");
}
catch (NonUniqueResultException $e) {
throw new BadCredentialsException("Authentication failed");
}
}
/**
* {#inheritdoc}
*/
public function checkCredentials($credentials, UserInterface $user)
{
$csrfToken = new CsrfToken(self::FORM, $credentials[self::CSRF_TOKEN]);
if (false === $this->_csrfTokenManager->isTokenValid($csrfToken)) {
throw new InvalidCsrfTokenException('Invalid CSRF token');
}
/* #var string $rawPassword the unencoded plain password */
$rawPassword = $credentials[self::PASSWORD];
if ($this->_userPasswordEncoder->isPasswordValid($user, $rawPassword)) {
return true;
}
/* #var AbstractUser $user */
$loginAttempt = $user->getLastLoginAttempt();
if (null !== $loginAttempt) {
$this->_loginAttemptManager->saveOne($loginAttempt);
}
return new CustomUserMessageAuthenticationException("Invalid credentials");
}
/**
* {#inheritdoc}
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
/* #var AbstractUser $user */
$user = $token->getUser();
/* #var LoginAttempt $loginAttempt */
$loginAttempt = $user->getLastLoginAttempt();
$loginAttempt->setStatus(LoginAttempt::STATUS_AUTHENTICATION_SUCCESS);
if (null !== $loginAttempt) {
$this->_loginAttemptManager->saveOne($loginAttempt);
}
return new RedirectResponse($this->getTargetUrl());
}
/**
* {#inheritdoc}
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception->getMessage());
return new RedirectResponse($this->getLoginUrl());
}
/**
* {#inheritdoc}
*/
public function start(Request $request, AuthenticationException $authException = null)
{
return new RedirectResponse($this->getLoginUrl());
}
/**
* {#inheritdoc}
*/
public function supports(Request $request)
{
return $request->getPathInfo() === $this->getLoginUrl() && $request->isMethod(Request::METHOD_POST);
}
/**
* {#inheritdoc}
*/
public function supportsRememberMe()
{
return true;
}
}

Symfony secure login - No queries performed

I've been having trouble implementing Symfony's Security features in my project. I have configured my Security.yaml and created a securityController , my Userclass implements userInterface , and from what I can see on the docs I haven't missed anything out. My form renders fine, and I can input my username and password, but when I submit valid credentials it just refreshes the page. Profiler showed that no SQL queries had been made, and despite me configuring authenticationUtils to display errors (as per the tutorial on the docs) nothing is displayed.
Security.yaml
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
encoders:
App\Entity\User: sha256
providers:
in_memory: { memory: ~ }
main_db_provider:
entity:
class: App\Entity\User
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
# anonymous: true
pattern: ^/$ #test
form_login:
login_path: login
check_path: login
csrf_token_generator: security.csrf.token_manager
provider: main_db_provider
# activate different ways to authenticate
# http_basic: true
# https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
# form_login: true
# https://symfony.com/doc/current/security/form_login_setup.html
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/$, roles: ROLE_USER }
Security Controller
<?php
// src/Controller/SecurityController.php
namespace App\Controller;
use App\Entity\User;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class SecurityController extends Controller
{
/**
* #Route("/login", name="login")
*/
public function login(Request $request, AuthenticationUtils $authenticationUtils)
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('ad-lotto-theme/login.html.twig', array(
'last_username' => $lastUsername,
'error' => $error,
));
}
}
User class
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
* #UniqueEntity("email", message="This email is already in use.")
* #UniqueEntity("username", message="This username is already in use")
*/
class User implements UserInterface, \Serializable
{
/**
* #ORM\Column(name="roles",type="string", length=255)
*/
private $roles;
/**
* #ORM\Column(name="salt",type="string", length=255)
*/
private $salt = "saltyboye";
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(name="username",type="string", length=255, unique=true)
*/
private $username;
/**
* #ORM\Column(name = "password", type="string", length=255)
*/
private $password;
/**
* #ORM\Column(name="email", type="string", length=255, unique=true)
*/
private $email;
/**
* #ORM\Column(type="datetime")
*/
private $registeredOn;
/**
* #ORM\Column(type="integer", nullable=true)
*/
private $referrer;
/**
* #ORM\Column(type="smallint")
*/
private $entries;
/**
* #ORM\Column(type="string", length=3)
*/
private $currency;
/** #see \Serializable::serialize() */
public function serialize()
{
return serialize(array(
$this->registeredOn,
$this->id,
$this->email,
$this->username,
$this->password,
$this->roles,
$this->referrer,
$this->currency,
$this->entries,
$this->salt));
// see section on salt below
// ,
}
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->password,
// see section on salt below
// $this->salt
) = unserialize($serialized, array('allowed_classes' => false));
}
public function eraseCredentials()
{
}
public function getRoles()
{
return array("ROLE_USER");
}
public function getSalt()
{
return $this->salt;
}
public function getId()
{
return $this->id;
}
public function getUsername(): ?string
{
return $this->username;
}
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getRegisteredOn(): ?\DateTimeInterface
{
return $this->registeredOn;
}
public function setRegisteredOn(\DateTimeInterface $registeredOn): self
{
$this->registeredOn = $registeredOn;
return $this;
}
public function getReferrer(): ?interedThisWeek
{
return $this->referrer;
}
public function setReferrer(?int $referrer): self
{
$this->referrer = $referrer;
return $this;
}
public function getEntries(): ?bool
{
return $this->entries;
}
public function setEntries(bool $entries): self
{
$this->entries = $entries;
return $this;
}
public function setCurrency(bool $currency): self
{
$this->currency = $currency;
return $this;
}
public function getCurrency(): ?bool
{
return $this->currency;
}
}
that salt is temporary, don't worry :) I haven't figured out how to implement SHA256 yet, but I needed to fill the field in the db :)
I'm assuming you follow this official tutorial: How to Build a Traditional Login Form
First of all your firewall configured to only 1 URI - / because of regex ^/$, so login form and other routes are not under the firewall.
Try to follow the tutorial from start to end just as it says there, make sure everything works and only then make changes.

The token storage contains no authentication token

I'm stack heeeere in security, help me please!!
I got this error 2 days ago and couldn't solve it : "The token storage contains no authentication token. One possible reason may be that there is no firewall configured for this URL." My login in the index page, and the login and login_check are in the same function (indexAction).This is my security.yml file, my controller, and my entity "user" :
# you can read more about security in the related section of the documentation
# http://symfony.com/doc/current/book/security.html
security:
# http://symfony.com/doc/current/book/security.html#encoding-the-user-s-password
encoders:
#Symfony\Component\Security\Core\User\User: plaintext
CNAM\CMSBundle\Entity\user: bcrypt
# http://symfony.com/doc/current/book/security.html#hierarchical-roles
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
# http://symfony.com/doc/current/book/security.html#where-do-users-come-from-user-providers
providers:
in_memory:
memory:
users:
user: { password: userpass, roles: [ 'ROLE_USER' ] }
admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
database:
entity:
class: CNAM\CMSBundle\Entity\user
property: username
# the main part of the security, where you can set up firewalls
# for specific sections of your app
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
admin_area:
pattern: ^/admin
form_login:
check_path: _default_index
login_path: _default_index
access_control:
#- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY}
- { path: ^/admin, roles: ROLE_ADMIN}
<?php
namespace CNAM\CMSBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use CNAM\CMSBundle\Entity\user;
use CNAM\CMSBundle\Entity\userprof;
use CNAM\CMSBundle\Entity\profil;
use CNAM\CMSBundle\Entity\privilege;
use Symfony\Component\BrowserKit\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Security\Core\Security;
class DefaultController extends Controller
{
/**
* #Route("/")
* #Template()
*/
public function indexAction(Request $request)
{
$user = new user();
$form = $this->createFormBuilder($user)
->add('id', 'text',array('attr'=>array('name'=>'login_user','required'=>'required',
'maxlength'=>'255','placeholder'=>'Votre matricule','id'=>'login_user')))
->add('password', 'password',array('attr'=>array('name'=>'login_password','required'=>'required',
'maxlength'=>'20','placeholder'=>'Mot de passe','id'=>'login_password')))
->add('Connexion', 'submit',array('attr'=>array('class'=>'btn btn-primary btn-block rounded_btn','id'=>'login_btn',
'style'=>"width:8vw;height:5vh;padding:0px 0px; position:relative;left:5vmin;top:1vmin;font-size:2vmin;")))
->getForm();
$form->handleRequest($request);
//$b_search=$this->get('session')->get('search');
$id = $request->request->get('id');
$session = $request->getSession();
if ($form->isValid()) {
$data = $form->getData();
$repository = $this
->getDoctrine()
->getManager()
->getRepository("CNAMCMSBundle:user");
$rep = $this
->getDoctrine()
->getManager()
->getRepository("CNAMCMSBundle:userprof");
$search = $repository->find($data);
$p_search=$rep->find($data);
$helper = $this->get('security.authentication_utils');
if (!$search) {
//throw $this->createNotFoundException('Utilisateur introuvable!');
}
else {
//$session=$this->get("session");
//$session->start();
// $session->set('search', $search);
$user->setEtat(1);
$em = $this->getDoctrine()->getManager();
$user=$em->merge($user);
$em->flush();
$id_prof=$p_search->getIdProfil();
switch ($id_prof)
{
case 1: return $this->redirect($this->generateUrl('cnam_cms_default_webmaster'),301);break;
case 2: $user->setRole("ROLE_ADMIN");$em = $this->getDoctrine()->getManager();$user=$em->merge($user);
$em->flush();return $this->redirect($this->generateUrl('cnam_cms_default_admin'),301);break;
case 3: return $this->redirect($this->generateUrl('cnam_cms_default_sup_med'),301);break;
case 4: return $this->redirect($this->generateUrl('cnam_cms_default_med'),301);break;
case 5: return $this->redirect($this->generateUrl('cnam_cms_default_gest_mp'),301);break;
}
}
//return $this->render('CNAMCMSBundle:Default:profile.html.twig', array(
//'search' => $search,
//'b_search'=>$b_search
// ));
}
return array('form'=>$form->createView());
}
/**
* #Route("/admin")
* #Template()
*/
public function adminAction()
{
return $this->render('CNAMCMSBundle:Default:admin.html.twig', array());
}
/**
* #Route("/admin/gestEtat",name="gestEtat")
* #Template()
*/
public function gestEtatAction()
{
return $this->render('CNAMCMSBundle:Default:gestEtat.html.twig', array());
}
}
<?php
namespace CNAM\CMSBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* user
*
* #ORM\Table(name="user")
* #ORM\Entity
*/
class user implements UserInterface
{
/**
* #var integer
*#Assert\NotBlank()
* #ORM\Column(name="id", type="integer")
* #ORM\Id
*/
private $id;
/**
* #var string
*#Assert\NotBlank()
* #ORM\Column(name="password", type="string", length=40)
*/
private $password;
/*
* #ORM\ManyToOne(targetEntity="profil" , inversedBy="users")
* #ORM\JoinColumn(name="id_profil", referencedColumnName="id_profil")
*/
private $profil;
public function __construct()
{
$this->profil = new ArrayCollection();
}
/**
* #var boolean
*
* #ORM\Column(name="etat", type="boolean")
*/
private $etat;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set id
*
* #param integer $id
* #return user
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Set password
*
* #param string $password
* #return user
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set etat
*
* #param boolean $etat
* #return user
*/
public function setEtat($etat)
{
$this->etat = $etat;
return $this;
}
/**
* Get etat
*
* #return boolean
*/
public function getEtat()
{
return $this->etat;
}
/**
* Get profil
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getProfil()
{
return $this->profil;
}
/**
* Add profil
*
* #param \CNAM\CMSBundle\Entity\user $profil
* #return user
*/
public function addProfil(\CNAM\CMSBundle\Entity\profil $profil)
{
$this->profil[] = $profil;
return $this;
}
/**
* Remove profil
*
* #param \CNAM\CMSBundle\Entity\profil $profil
*/
public function removeProfil(\CNAM\CMSBundle\Entity\profil $profil)
{
$this->profil->removeElement($profil);
}
public function getUsername()
{
return $this->id;
}
public function getRoles()
{
return array('ROLE_USER');
}
public function getSalt()
{
return null;
}
public function eraseCredentials()
{
}
public function equals(UserInterface $user)
{
return $user->getId() == $this->getId();
}
}

Symfony3 Security - Load User from database does not work

I have a Invalid credentials error when I'm trying to load my user form the database.
Here is my security.yml
security:
providers:
database:
entity: { class: AppBundle\Entity\User, property: username }
encoders:
AppBundle\Entity\User: plaintext
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
# pattern: ^/
form_login:
login_path: /login
check_path: /login_check
# default_target_path: /admin
provider: database
logout:
path: /logout
target: /login
My User Entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User implements UserInterface
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", unique=true)
*/
private $username;
/**
* #ORM\Column(type="string")
*/
private $password;
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* Returns the password used to authenticate the user.
*
* This should be the encoded password. On authentication, a plain-text
* password will be salted, encoded, and then compared to this value.
*
* #return string The password
*/
public function getPassword()
{
return $this->password;
}
/**
* Set password
*
* #param string $password
*
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Returns the salt that was originally used to encode the password.
*
* This can return null if the password was not encoded using a salt.
*
* #return string|null The salt
*/
public function getSalt()
{
}
/**
* Returns the username used to authenticate the user.
*
* #return string The username
*/
public function getUsername()
{
return $this->getUsername();
}
/**
* Set username
*
* #param string $username
*
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Removes sensitive data from the user.
*
* This is important if, at any given point, sensitive information like
* the plain-text password is stored on this object.
*/
public function eraseCredentials()
{
// TODO: Implement eraseCredentials() method.
}
/**
* Returns the roles granted to the user.
*
* <code>
* public function getRoles()
* {
* return array('ROLE_USER');
* }
* </code>
*
* Alternatively, the roles might be stored on a ``roles`` property,
* and populated in any number of different ways when the user object
* is created.
*
* #return (Role|string)[] The user roles
*/
public function getRoles()
{
// TODO: Implement getRoles() method.
}
}
My Controllers:
/**
* #Route("/login", name="login")
*/
public function loginAction(Request $request)
{
$authenticationUtils = $this->get('security.authentication_utils');
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
$form = $this->createForm(LoginType::class, array(
'_username' => $lastUsername,
));
return $this->render(':back/security:login.html.twig', array(
'error' => $error,
'form' => $form->createView(),
));
}
/**
* #Route("/login_check", name="login_check")
*/
public function loginCheckAction(){}
I don't understand why it does not work. I have tried to follow the documentation and make it very simple.
The user is in my database and the password is plaintext.
What did I do wrong?

symfony doctrine authentication bad credentials

I'm trying to follow the documentation but can't get it to work. I keep getting "Bad credentials" when trying to use the login form.
Here is my security.yml file
security:
encoders:
MyCompany\MyPoroject\UserBundle\Entity\User:
algorithm: sha1
encode_as_base64: false
iterations: 1
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
administrators:
entity: { class: MyCompanyMyProjectUserBundle:User, property: username }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: login
check_path: login_check
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: ROLE_ADMIN }
This is the code i've used to create some dummy users
$factory = $this->get('security.encoder_factory');
$user = new User;
$encoder = $factory->getEncoder($user);
$password = $encoder->encodePassword('testing', $user->getSalt());
$user->setPassword($password)
->setEmail('test#gmail.com')
->setUsername('testing');
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
Here is my User class
class User implements UserInterface, \Serializable
{
private $id;
private $username;
private $salt;
private $password;
private $email;
private $isActive;
public function __construct()
{
$this->isActive = true;
$this->salt = md5(uniqid(null, true));
}
/**
* Returns the roles granted to the user.
*
* <code>
* public function getRoles()
* {
* return array('ROLE_USER');
* }
* </code>
*
* Alternatively, the roles might be stored on a ``roles`` property,
* and populated in any number of different ways when the user object
* is created.
*
* #return Role[] The user roles
*/
public function getRoles()
{
return ['ROLE_USER'];
}
/**
* Returns the password used to authenticate the user.
*
* This should be the encoded password. On authentication, a plain-text
* password will be salted, encoded, and then compared to this value.
*
* #return string The password
*/
public function getPassword()
{
$this->password;
}
/**
* Returns the salt that was originally used to encode the password.
*
* This can return null if the password was not encoded using a salt.
*
* #return string|null The salt
*/
public function getSalt()
{
$this->salt;
}
/**
* Returns the username used to authenticate the user.
*
* #return string The username
*/
public function getUsername()
{
return $this->username;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* #param string $username
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Set salt
*
* #param string $salt
* #return User
*/
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
/**
* Set password
*
* #param string $password
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Set email
*
* #param string $email
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set is_active
*
* #param boolean $isActive
* #return User
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
/**
* Get is_active
*
* #return boolean
*/
public function getIsActive()
{
return $this->isActive;
}
/**
* (PHP 5 >= 5.1.0)<br/>
* String representation of object
* #link http://php.net/manual/en/serializable.serialize.php
* #return string the string representation of the object or null
*/
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->salt,
$this->password,
));
}
/**
* (PHP 5 >= 5.1.0)<br/>
* Constructs the object
* #link http://php.net/manual/en/serializable.unserialize.php
* #param string $serialized <p>
* The string representation of the object.
* </p>
* #return void
*/
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->salt,
$this->password,
) = unserialize($serialized);
}
/**
* Removes sensitive data from the user.
*
* This is important if, at any given point, sensitive information like
* the plain-text password is stored on this object.
*/
public function eraseCredentials()
{
}
}
My Security controller
class SecurityController extends Controller
{
public function loginAction(Request $request)
{
$session = $request->getSession();
// get the login error if there is one
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(
SecurityContext::AUTHENTICATION_ERROR
);
} else {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
return $this->render(
'MyCompanyMyProjectUserBundle:Security:login.html.twig',
array(
// last username entered by the user
'last_username' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error,
)
);
}
public function adminAction()
{
return $this->render('MyCompanyMyProjectUserBundle:Security:admin.html.twig');
}
}
This is the record in the database i'm attempting to login with using testing as both the username and password.
id: 3
username(25): testing
salt(32): 87a449194ebfe80bfa9f59da53dab0ea
password(64): dc724af18fbdd4e59189f5fe768a5f8311527050
email(60): test#gmail.com
Probably you missed return statement in getSalt() and getPassword() methods

Resources