Save crypt hash security:
$usuario = new User();
$usuario->password = $this->security->hash($this->request->getPost("pass"));
if (!$usuario->save()) {
foreach ($usuario->getMessages() as $message) {
$this->flash->error($message);
}
$this->dispatcher->forward([
'controller' => "usuario",
'action' => 'new'
]);
return;
}
now, How to decrypt hash security to send my form:
$usuario = User::findFirstByid($iduser);
$this->tag->setDefault("pass", $this->encryption->decrypt($usuario->password));
I having this: Notice: Access to undefined property encryption in ...
As #Juri said Hashes are only one way. You can however use encryptBase64() which is two way and you can decode it back. Do not use it for passwords, use it for some data you need to pass to someone and read it back, like api token etc..
Here is how to set it up:
$di->setShared('crypt', function () use ($config) {
$crypt = new \Phalcon\Crypt();
$crypt->setKey('i$4^&/:%2#k50ROQ<#{(e=*!<7u|rI~0');
return $crypt;
});
Helper functions I created, but you can use it directly:
...
...
private static $cryptKey = 'i$4^&/:%2#k50ROQ<#{(e=*!<7u|rI~0';
/**
* Generate url safe encoded string
*
* #param string $string string to be encoded
* #return encoded string
*/
public static function encodeString($string)
{
$crypt = new \Phalcon\Crypt();
return $crypt->encryptBase64($string, self::$cryptKey, true);
}
/**
* Decode string generated with Common::encodeString()
*
* #param string $string Encoded string
* #return decoded string
*/
public static function decodeString($string)
{
$crypt = new \Phalcon\Crypt();
return $crypt->decryptBase64($string, self::$cryptKey, true);
}
Related
I need to authenticate my WebDriver Client for functional tests.
For example,
In my integration tests, i'm doing something like that :
namespace Tests\Controller;
use App\Entity\Donor;
use App\Entity\User;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\SchemaTool;
use SebastianBergmann\Type\RuntimeException;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class DonorTest extends WebTestCase
{
private static $client;
/**
* #var EntityManager
*/
private $entityManager;
/**
* #var SchemaTool
*/
private $schemaTool;
public function __construct(?string $name = null, array $data = [], string $dataName = '')
{
parent::__construct($name, $data, $dataName);
static::ensureKernelShutdown();
if (!self::$client) {
self::$client = static::createClient([], [
'PHP_AUTH_USER' => 'Same Old User',
'PHP_AUTH_PW' => 'Same Old Password',
]);
}
$this->entityManager = self::bootKernel()
->getContainer()
->get('doctrine')
->getManager();
$this->schemaTool = new SchemaTool($this->entityManager);
/** Safeguard */
$connection = $this->entityManager->getConnection()->getParams();
if ($connection['driver'] != 'pdo_sqlite' || $connection['path'] != '/tmp/test_db.sqlite') {
throw new RuntimeException('Wrong database, darling ! Please set-up your testing database correctly. See /config/packages/test/doctrine.yaml and /tests/README.md');
}
}
I'm just passing the credentials in paramaters, and it works.
But, in my functional tests, i'm using the WebDriver. It didn't accept credentials in arguments :
<?php
namespace App\Tests\Functional\Entities\Donor;
use App\Entity\Donor;
use App\Tests\Functional\Helpers\Carrier\CarrierHelper;
use App\Tests\Functional\Helpers\Donor\DonorHelper;
use Doctrine\ORM\EntityManager;
use Facebook\WebDriver\WebDriverBy;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Panther\PantherTestCase;
use Symfony\Component\Panther\Client;
class DonorTest extends PantherTestCase
{
/**
* #var EntityManager
*/
private $entityManager;
/**
* #var CarrierHelper
*/
private $helper;
/**
* #var Client
*/
private $client;
public function __construct(?string $name = null, array $data = [], string $dataName = '')
{
parent::__construct($name, $data, $dataName);
$this->entityManager = self::bootKernel()
->getContainer()
->get('doctrine')
->getManager();
$this->helper = new DonorHelper();
}
public static function setUpBeforeClass(): void
{
// Do something
}
public function setUp(): void
{
parent::setUp(); // TODO: Change the autogenerated stub
$this->client = Client::createChromeClient();
$this->client->manage()->window()->maximize();
}
I can't pass any login arguments in createChromeClient() method.
I think i have to play with cookies in cookieJar, or token, but i don't know how.
Feel free to ask me my ahtentication method, but i've followed the documentation :
https://symfony.com/doc/current/security/form_login_setup.html
EDIT
I've just tried something else. Log in with my browser, for generate a cookie, and tried to handcraft an other with same PHPSESSID
public function setUp(): void
{
parent::setUp(); // TODO: Change the autogenerated stub
$this->client = Client::createChromeClient();
$this->client->manage()->window()->maximize();
$cookie = new Cookie('PHPSESSID', 'pafvg5nommcooa60q14nqhool0');
$cookie->setDomain('127.0.0.1');
$cookie->setHttpOnly(true);
$cookie->setSecure(false);
$cookie->setPath('/');
$this->client->manage()->addCookie($cookie);
}
But get this error :
Facebook\WebDriver\Exception\InvalidCookieDomainException: invalid cookie domain
Domain is good, same as my web browser.
I will update as my investigations progressed.
EDIT 2
Ok... Got It.
According to this thread : Unable to set cookies in Selenium Webdriver
For setting-up cookie['domain'], you have to request firstly on the domain, THEN set-up the cookie...
SO, this is almost working :
public function setUp(): void
{
parent::setUp(); // TODO: Change the autogenerated stub
$this->client = Client::createChromeClient();
$this->client->manage()->window()->maximize();
$this->client->request('GET', 'http://127.0.0.1/randompage');
$handcookie = Cookie::createFromArray([
'name' => 'PHPSESSID',
'value' => 'pcvbf3sjlla16rfb1b1274qk01',
'domain' => '127.0.0.1',
'path' => '/'
]);
$this->client->manage()->addCookie($handcookie);
}
Next step : Find a way to generate a permanent cookie, without lifetime.
I think nobody will read this but i will update it in case someone else gets stuck.
I have implemented Laravel 6 API and used Laravel's inbuilt Illuminate\Foundation\Auth\VerifiesEmails based on tutorial here but the email verification link is not expired and still accessible after successful email verification. I have found many tutorials regarding laravel frontend but how to implement it on API.
VerificationApiController
class VerificationApiController extends Controller
{
use VerifiesEmails;
/**
* Mark the authenticated user's email address as verified.
* #param Request $request
* #return JsonResponse
*/
public function verify(Request $request): JsonResponse
{
$userID = $request['id'];
$user = User::findOrFail($userID);
$date = date('Y-m-d g:i:s');
// to enable the “email_verified_at field of that
// user be a current time stamp by mimicking the
// must verify email feature
$user->email_verified_at = $date;
$user->save();
return response()->json('Email verified!');
}
/**
* Resend the email verification notification.
* #param Request $request
* #return JsonResponse|Response
*/
public function resend(Request $request)
{
if ($request->user()->hasVerifiedEmail()) {
return response()->json('User already have verified email!', 422);
}
$request->user()->sendEmailVerificationNotification();
return response()->json('The notification has been resubmitted');
// return back()->with(‘resent’, true);
}
}
User model
class User extends Authenticatable implements MustVerifyEmail
{
use HasApiTokens, Notifiable;
protected $fillable = [
'name', 'email', 'password'
];
/**
* The attributes that should be hidden for arrays.
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* Send email verification notification
*/
public function sendApiEmailVerificationNotification()
{
$this->notify(new VerifyApiEmail); // my notification
}
}
Here are verification api routes
Route::get(‘email/verify/{id}’, ‘VerificationApiController#verify’)->name(‘verificationapi.verify’);
Route::get(‘email/resend’, ‘VerificationApiController#resend’)->name(‘verificationapi.resend’)
Here is UsersApiController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use Illuminate\Support\Facades\Hash;
use Auth;
use Validator;
use Illuminate\Foundation\Auth\VerifiesEmails;
use Illuminate\Auth\Events\Verified;
class UsersApiController extends Controller
{
use VerifiesEmails;
public $successStatus = 200;
/**
* login api
*
* #return \Illuminate\Http\Response
*/
public function login(){
if(Auth::attempt([‘email’ => request(‘email’), ‘password’ => request(‘password’)])){
$user = Auth::user();
if($user->email_verified_at !== NULL){
$success[‘message’] = “Login successfull”;
return response()->json([‘success’ => $success], $this-> successStatus);
}else{
return response()->json([‘error’=>’Please Verify Email’], 401);
}
}
else{
return response()->json([‘error’=>’Unauthorised’], 401);
}
}
/**
* Register api
*
* #return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
‘name’ => ‘required’,
‘email’ => ‘required|email’,
‘password’ => ‘required’,
‘c_password’ => ‘required|same:password’,
]);
if ($validator->fails()) {
return response()->json([‘error’=>$validator->errors()], 401);
}
$input = $request->all();
$input[‘password’] = Hash::make($input[‘password’]);
$user = User::create($input);
$user->sendApiEmailVerificationNotification();
$success[‘message’] = ‘Please confirm yourself by clicking on verify user button sent to you on your email’;
return response()->json([‘success’=>$success], $this-> successStatus);
}
/**
* details api
*
* #return \Illuminate\Http\Response
*/
public function details()
{
$user = Auth::user();
return response()->json([‘success’ => $user], $this-> successStatus);
}
}
Here are user and auth routes
Route::post(‘login’, ‘UsersApiController#login’);
Route::post(‘register’, ‘UsersApiController#register’);
Route::group([‘middleware’ => ‘auth:api’], function(){
Route::post(‘details’, ‘UsersApiController#details’)->middleware(‘verified’);
}); // will work only when user has verified the email
so the problem is that when I click on verification link on email the user is verified but the link is not expired . I want the link to be expired as soon as user is verified. How to do that?
Have you implemented the VerifyApiEmail class?
namespace App\Notifications;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\URL;
use Illuminate\Auth\Notifications\VerifyEmail as VerifyEmailBase;
class VerifyApiEmail extends VerifyEmailBase
{
protected function verificationUrl($notifiable)
{
return URL::temporarySignedRoute(
'api.auth.verify', Carbon::now()->addMinutes(60), ['id' => $notifiable->getKey()]
);
}
}
Here you can add the expiration time in minutes, seconds or hours.
I'm a begginer in Symfony 4 and I'm developing an API Rest. I want to create a PUT resource that can handle many update cases.
In my case, I have a user with many properties but I will take an example with 3 properties to keep things simple :
User {
username,
email,
password
}
My PUT resource can be called in order to update Username, update Email or update Password. For example, to update Username, the user of my API will send a PUT request with only username :
{
username: "New username"
}
Same for email and password, he will only send the property he wants to change.
My problem is in my Controller, I have to do things like this :
/**
* #Rest\Put("/user/{id}")
* #param Request $request
* #return View
*/
public function putUserRequest(Request $request)
{
$userId = $request->get('id');
$user = $this->doctrine->getRepository(User::class)->findOneBy('id' => $userId);
$userFromRequest = $this->serializer->deserialize($request->getContent(), User::class, 'json');
if ($userFromRequest->getUsername() != NULL) {
$user->setUsername($userFromRequest->getUsername())
}
if ($userFromRequest->getEmail() != NULL) {
$user->setEmail($userFromRequest->getEmail())
}
if ($userFromRequest->getPassword() != NULL) {
$user->setPassword($userFromRequest->getPassword())
}
// ...
}
In my example I have only 3 properties, but imagine when I have 30 properties.
With Symfony 3 I used forms to validate / save my datas :
$form->submit($request->request->all(), $clearMissing);
Where $clearMissing is false to keep datas not provided by the user of my API. I can't find a way to do it with serializer but I guess I'm doing things wrong.
Thanks.
If I understand correctly, You can use the validator Component like this :
/**
* #Rest\Put("/user/{id}")
* #param Request $request
* #return View
*/
public function putUserRequest(User $user, Request $request, ValidatorInterface $validator)
{
$data = $request->getContent();
$this->serializer->deserialize($data, User::class, 'json', ['object_to_populate' => $user]);
//At this moment, the data you sent is merged with your user entity
/** #var ConstraintViolationList $errors */
$errors = $validator->validate($user, null ,['groups' => 'user_update']);
if (count($errors) > 0) {
//return json reponse with formated errors;
}
//if ok $entityManager->flush() and Response Json with serialization group;
...
}
In your user class :
class User implements UserInterface
{
/**
* #Assert\Email(groups={"user_create", "user_update"})
*/
private $email;
/**
* #Assert\NotBlank(groups={"user_create", "user_update"})
* #Assert\Length(min=7, groups={"user_create", "user_update"})
*/
private $password;
/**
* #Assert\Length(min=2, groups={"user_create", "user_update"} )
*/
private $username;
}
Related Validator component documentation : https://symfony.com/doc/current/validation/groups.html
You can also check this project : https://github.com/attineos/relation-deserializer
I am quite new in Symfony 2. I have to build an application in Symfony 2 (I'm using 2.8 and also latest version of FOSUser Bundle). Majority of work is done, although I have to do some changes in default security settings. I was looking for them for two days and I have only really foggy concept how this can be fixed. The supposed changes are following:
REGISTRATION - I have enabled confirmation by e-mail and I don't know how to make to the confirmation link expire after one hour and/or after one usage (one click). There is setting in config.yaml settting ttl, but only for password resseting.
REGISTRATION - Before confirming users are prevented from logging in and there is Symfony 2 Exception - Disabled Account working, rendering short message about it. Actually I have to set redirection to another page (I suppose template) to render custom message that 'this account is blocked...' and link to send another link with confirmation token (Am I right? The link in email is confirmation token?).
RESETTING - As mentioned before ttl for link (token?) ressetting password is set for one hour, but I don't know how to make it expire after one usage (one click).
I know how to override some template of FOSUser, but I have no clear idea which of files should I override to change these things.
I have noticed that my FOSUser uses Symfony 2 Exceptions files and if I have changed content of message in my Exception file, it has changed also on my page, but I don't know how to make it well and override it, adding all necessary features.
I was trying to override AuthenticationListener (from FOSUser) with use of Compiler Pass (http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html), but I don't know if it worked, because any changes in overriden Listener were not visible. Actually I don't know if this is the file I should override.
I have check a few Stackoverflow questions, but I haven't found an answer.
FOSUser Bundle - Prevent Disabled users from logging in
This doesn't work for me, because users are prevented and I need only override message of exception and create redirection with another link sending confirmation one.
FOS user bundle authentication
I have tried to implement the solution pointed here, but it didn't work and I am not sure if I really need such a complicated solution.
Thanks for help in advance and I someone need to see my files, configuration just write and I will post here necessary ones.
I have finally figured all these things out. If someone has a similar problem i advise to read these topics in Symfony documentation:
Overriding FOSUser B controllers
Hooking into a controller
It turns out that for described features I need to override some files form FOSUser Bundle, sometimes Controller was enough, sometimes I needed to modify EventListener (actually I have even created my own event). There is more than one way.
The hardest part was one-click link for ressetting password. I have used a flag, which is set to false while sending an e-mail and set true while clicking on link to prevent from using link once more. The problem is, that Resetting Controller is 'executed' two times, so while clicking submit there was redirection, beacuse flag was true. I have added some counting in session in order to omit the part of code which checks the flag, when you hit the submit button (second usage of the Reset Method in Resetting Controller), but it prevented only from clicking submit second time, so actually you can not use the link two times, but you can see form two times, which is not an effect I wanted to reach, but is far better than nothing. If someone has an idea how to upgrade it I will be gratefull
<?php
namespace My\UserBundle\Controller;
use FOS\UserBundle\Controller\ResettingController as FOSResettingController;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Model\UserInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use My\UserBundle\Entity\User;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use My\UserBundle\UserEvents;
/**
* Controller managing the resetting of the password
*
* #author Thibault Duplessis <thibault.duplessis#gmail.com>
* #author Christophe Coevoet <stof#notk.org>
*/
class ResettingController extends FOSResettingController
{
/**
* Request reset user password: submit form and send email
*/
public function sendEmailAction(Request $request)
{
$username = $request->request->get('username');
/** #var $user UserInterface */
$user = $this->get('fos_user.user_manager')->findUserByUsernameOrEmail($username);
if (null === $user) {
return $this->render('FOSUserBundle:Resetting:request.html.twig', array(
'invalid_username' => $username
));
}
if ($user->isPasswordRequestNonExpired($this->container->getParameter('fos_user.resetting.token_ttl'))) {
return $this->render('FOSUserBundle:Resetting:passwordAlreadyRequested.html.twig');
}
if (null === $user->getConfirmationToken()) {
/** #var $tokenGenerator \FOS\UserBundle\Util\TokenGeneratorInterface */
$tokenGenerator = $this->get('fos_user.util.token_generator');
$user->setConfirmationToken($tokenGenerator->generateToken());
}
$this->get('fos_user.mailer')->sendResettingEmailMessage($user);
$user->setPasswordRequestedAt(new \DateTime());
$user->setPasswordRequestedClicked(false);
$this->get('fos_user.user_manager')->updateUser($user);
$_SESSION['views'] = 1;
return new RedirectResponse($this->generateUrl('fos_user_resetting_check_email',
array('email' => $this->getObfuscatedEmail($user))
));
}
/**
* Reset user password
*/
public function resetAction(Request $request, $token)
{
/** #var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
$formFactory = $this->get('fos_user.resetting.form.factory');
/** #var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
/** #var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
$dispatcher = $this->get('event_dispatcher');
$user = $userManager->findUserByConfirmationToken($token);
//Here there is a reaction for using expired token (column confirmation token === null) - redirection to page with possibility of sending another one.
if (null === $user) {
return $this->redirectToRoute('fos_user_invalid_token_click');
}
if ($_SESSION['views'] == 1){
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(UserEvents::RESETTING_RESET_CLICK_CHECK, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
} else {
$user->setPasswordRequestedClicked(true);
$userManager->updateUser($user);
$_SESSION['views']++;
$_SESSION['views']++;
}
} else {
$_SESSION['views']++;
}
if ($_SESSION['views'] == 5){
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(UserEvents::RESETTING_RESET_CLICK_CHECK, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
}
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $formFactory->createForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_SUCCESS, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_profile_show');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
$userManager->updateUser($user);
return $this->render('FOSUserBundle:Resetting:reset.html.twig', array(
'token' => $token,
'form' => $form->createView(),
));
}
public function InvalidTokenTtlMessageAction() {
return $this->render('UserBundle:Resetting:invalidTokenTtlRes.html.twig');
}
public function InvalidTokenClickMessageAction() {
return $this->render('UserBundle:Resetting:invalidTokenClickRes.html.twig');
}
}
My listener:
<?php
namespace My\UserBundle\EventListener;
use FOS\UserBundle\EventListener\ResettingListener as FOSResettingListener;
use FOS\UserBundle\FOSUserEvents;
use My\UserBundle\UserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use My\UserBundle\Entity\User;
class ResettingListener extends FOSResettingListener
{
private $router;
private $tokenTtl;
public function __construct(UrlGeneratorInterface $router, $tokenTtl)
{
$this->router = $router;
$this->tokenTtl = $tokenTtl;
}
public static function getSubscribedEvents()
{
return array(
UserEvents::RESETTING_RESET_CLICK_CHECK => 'onResettingClickCheck',
FOSUserEvents::RESETTING_RESET_INITIALIZE => 'onResettingResetInitialize',
FOSUserEvents::RESETTING_RESET_SUCCESS => 'onResettingResetSuccess',
);
}
public function onResettingClickCheck(GetResponseUserEvent $event){
//checking if link hasn't expired due to its usage
if ($event->getUser()->isPasswordRequestedClicked() === true){
$event->setResponse(new RedirectResponse($this->router->generate('fos_user_invalid_token_click')));
}
}
public function onResettingResetInitialize(GetResponseUserEvent $event)
{
//checking if link hasn't expired due to exceeding token Ttl
if (!$event->getUser()->isPasswordRequestNonExpired($this->tokenTtl)) {
$event->setResponse(new RedirectResponse($this->router->generate('fos_user_invalid_token_ttl')));
}
}
public function onResettingResetSuccess(FormEvent $event)
{
/** #var $user \FOS\UserBundle\Model\UserInterface */
$user = $event->getForm()->getData();
$user->setConfirmationToken(null);
$user->setPasswordRequestedAt(null);
$user->setEnabled(true);
}
}
and my User entity:
<?php
namespace My\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use My\BackendBundle\Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="My\UserBundle\Repository\UserRepository")
*/
class User extends BaseUser
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable = false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Gedmo\Slug(fields={"username"})
* #ORM\Column(length=128, unique=true)
*/
private $slug;
/**
*
* #ORM\ManyToMany(targetEntity="\My\BackendBundle\Entity\Event", mappedBy="users")
* #ORM\JoinColumn(name="id", referencedColumnName="id", nullable=false)
* #ORM\OrderBy({"date"="ASC"})
*
*/
protected $events;
/**
* #var \Doctrine\Common\Collections\ArrayCollection $event_org
* #ORM\OneToMany(targetEntity="\My\BackendBundle\Entity\Event", mappedBy="user_org", cascade={"all"})
*/
protected $event_org;
/**
* #var \DateTime
* #ORM\Column(name="confirmation_token_requested_at", type="datetime")
*/
protected $confirmationTokenRequestedAt;
/**
* #var boolean
* #ORM\Column(name="password_requested_clicked", type="boolean", nullable=true)
*/
protected $passwordRequestedClicked;
public function __toString()
{
return $this->getUsername();
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
public function __construct()
{
parent::__construct();
$this->event_org = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add event
*
* #param \My\BackendBundle\Entity\Event $event
*
* #return User
*/
public function addEvent(\My\BackendBundle\Entity\Event $event)
{
$this->events[] = $event;
$event->addUser($this);
return $this;
}
/**
* Remove event
*
* #param \My\BackendBundle\Entity\Event $event
*/
public function removeEvent(\My\BackendBundle\Entity\Event $event)
{
$this->events->removeElement($event);
}
/**
* Get events
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getEvents()
{
return $this->events;
}
/**
* Set slug
*
* #param string $slug
*
* #return User
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* Add eventOrg
*
* #param \My\BackendBundle\Entity\Event $eventOrg
*
* #return User
*/
public function addEventOrg(\My\BackendBundle\Entity\Event $eventOrg)
{
$this->event_org[] = $eventOrg;
return $this;
}
/**
* Remove eventOrg
*
* #param \My\BackendBundle\Entity\Event $eventOrg
*/
public function removeEventOrg(\My\BackendBundle\Entity\Event $eventOrg)
{
$this->event_org->removeElement($eventOrg);
}
/**
* Get eventOrg
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getEventOrg()
{
return $this->event_org;
}
/**
* Set confirmationTokenRequestedAt
*
* #param \DateTime $confirmationTokenRequestedAt
*
* #return User
*/
public function setConfirmationTokenRequestedAt(\DateTime $date = null)
{
$this->confirmationTokenRequestedAt = $date;
return $this;
}
/**
* Gets the timestamp that the user requested a confirmation_token.
*
* #return null|\DateTime
*/
public function getConfirmationTokenRequestedAt()
{
return $this->confirmationTokenRequestedAt;
}
public function isConfirmationTokenNonExpired($ttl)
{
return $this->getConfirmationTokenRequestedAt() instanceof \DateTime &&
$this->getConfirmationTokenRequestedAt()->getTimestamp() + $ttl > time();
}
/**
* Set passwordRequestedClicked
*
* #param boolean $passwordRequestedClicked
*
* #return User
*/
public function setPasswordRequestedClicked($boolean)
{
$this->passwordRequestedClicked = (Boolean) $boolean;
return $this;
}
/**
* Get passwordRequestedClicked
*
* #return boolean
*/
public function getPasswordRequestedClicked()
{
return $this->passwordRequestedClicked;
}
/**
* Checks whether the user has used password request.
*
*
* #return Boolean true if the user is enabled, false otherwise
*/
public function isPasswordRequestedClicked() {
return $this->passwordRequestedClicked;
}
}
If someone would like to get code for remaining problems, please write me a message and I will provide it here :).
Resetting controller:
<?php
namespace My\UserBundle\Controller;
use FOS\UserBundle\Controller\ResettingController as FOSResettingController;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Model\UserInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use My\UserBundle\Entity\User;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use My\UserBundle\UserEvents;
class ResettingController extends FOSResettingController
{
public function sendEmailAction(Request $request)
{
$username = $request->request->get('username');
$user = $this->get('fos_user.user_manager')->findUserByUsernameOrEmail($username);
if (null === $user) {
return $this->render('FOSUserBundle:Resetting:request.html.twig', array(
'invalid_username' => $username
));
}
if ($user->isPasswordRequestNonExpired($this->container->getParameter('fos_user.resetting.token_ttl'))) {
return $this->render('FOSUserBundle:Resetting:passwordAlreadyRequested.html.twig');
}
if (null === $user->getConfirmationToken()) {
$tokenGenerator = $this->get('fos_user.util.token_generator');
$user->setConfirmationToken($tokenGenerator->generateToken());
}
$this->get('fos_user.mailer')->sendResettingEmailMessage($user);
$user->setPasswordRequestedAt(new \DateTime());
$user->setPasswordRequestedClicked(false);
$this->get('fos_user.user_manager')->updateUser($user);
$_SESSION['views'] = 1;
return new RedirectResponse($this->generateUrl('fos_user_resetting_check_email',
array('email' => $this->getObfuscatedEmail($user))
));
}
public function resetAction(Request $request, $token)
{
$formFactory = $this->get('fos_user.resetting.form.factory');
$userManager = $this->get('fos_user.user_manager');
$dispatcher = $this->get('event_dispatcher');
$user = $userManager->findUserByConfirmationToken($token);
//Here there is a reaction for using expired token (column confirmation token === null) - redirection to page with possibility of sending another one.
if (null === $user) {
return $this->redirectToRoute('fos_user_invalid_token_click');
}
if ($_SESSION['views'] == 1){
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(UserEvents::RESETTING_RESET_CLICK_CHECK, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
} else {
$user->setPasswordRequestedClicked(true);
$userManager->updateUser($user);
$_SESSION['views']++;
$_SESSION['views']++;
}
} else {
$_SESSION['views']++;
}
if ($_SESSION['views'] == 5){
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(UserEvents::RESETTING_RESET_CLICK_CHECK, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
}
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $formFactory->createForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_SUCCESS, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_profile_show');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
$userManager->updateUser($user);
return $this->render('FOSUserBundle:Resetting:reset.html.twig', array(
'token' => $token,
'form' => $form->createView(),
));
}
public function InvalidTokenTtlMessageAction() {
return $this->render('UserBundle:Resetting:invalidTokenTtlRes.html.twig');
}
public function InvalidTokenClickMessageAction() {
return $this->render('UserBundle:Resetting:invalidTokenClickRes.html.twig');
}
}
I am trying to use Laravel's built in authentication, but it is not working. If I hash a password at the registration process, it does not match the hash in the login process, because Laravel's auth generates a totally different hash than Hash:make().
I made a test route and function, to make everything clear
(I tried to use the Auth::attempt() function with Hash::make() and without Hash::make() too, If I pass the Hashed password, it generates a totally different one, If I pass the raw password the Auth doesn't even bother to hash it):
Route::get('/test', function() {
$email = rand(1, 1000) . "test#mail.com";
$password = $email;
$now = new DateTime();
Felhasznalo::create(array(
'teljesnev' => 'valami',
'email' => $email,
'jelszo' => Hash::make($password),
'FelFelhasznaloiSzint_id' => 2,
'created_at' => $now->getTimestamp(),
'aktiv' => 1
));
if (Auth::attempt(array(
'email' => $email,
'jelszo' => Hash:make($password)
))) {
echo 'Working';
} else {
echo 'Not working';
}
});
The first part generates this row to my mysql server:
39test#mail.com, $2y$10$gkzQ2BEuDWN05RQ/OyBH8u4aKRqdL5zSIthUO4BUyEKcscgzRwZzG, valami ....etc
I intentionally mistyped the password field's name to jelszo1 (means password1 in english), when attempting login, to get an sql error.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'jelszo1' in 'where clause' (SQL: select * from `Felhasznalo` where `email` = 39test#mail.com and `jelszo1` = y$XAnnnGNKrOQOxBiX2BnEPOq86Y9mh5h./xwUlfCTPpzW.jzzt3YiO limit 1)
First part (in mysql):
$2y$10$gkzQ2BEuDWN05RQ/OyBH8u4aKRqdL5zSIthUO4BUyEKcscgzRwZzG
Second part (when attempting login):
y$XAnnnGNKrOQOxBiX2BnEPOq86Y9mh5h./xwUlfCTPpzW.jzzt3YiO
and the User model (named as Felhasznalo)
<?php
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class Felhasznalo extends \Eloquent implements UserInterface, RemindableInterface {
use UserTrait,
RemindableTrait;
protected $fillable = [
'id', 'email', 'jelszo', 'teljesnev', 'jelszoreset',
'hash', 'aktiv', 'ban', 'FelFelhasznaloiSzint_id',
'remember_token'
];
protected $guarded = [
];
protected $hidden = [
'jelszo', 'jelszoreset', 'hash'
];
protected $table = 'Felhasznalo';
public $timestamps = true;
protected $softDelete = true;
//----------------------------
//----------------------------
// RELATIONSHIP FUNCTIONS
//----------------------------
//----------------------------
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier() {
return $this->getKey();
}
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword() {
return $this->jelszo;
}
/**
* Get the e-mail address where password reminders are sent.
*
* #return string
*/
public function getReminderEmail() {
return $this->email;
}
public function getRememberToken() {
return $this->remember_token;
}
public function setRememberToken($value) {
$this->remember_token = $value;
}
public function getRememberTokenName() {
return 'remember_token';
}
}
The auth config.:
'model' => 'Felhasznalo',
'table' => 'Felhasznalo',
SQL Error error when using raw password in attempt():
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'jelszo1' in 'where clause' (SQL: select * from `Felhasznalo` where `email` = 832test#mail.com and `jelszo1` = 832test#mail.com limit 1)
The answer to Your question from the post's title (Which Hash function laravel's Auth is using?) can be found on mnshankar.wordpress.com - Laravel Hash::make() explained.
Here is the first sentence from the "How?" section of the linked blog post:
Internally, Hash::make() encrypts using the bcrypt function and Blowfish algorithm.
Also, You can see on the Laravel 5.4 docs - Hashing page that they say:
The Laravel Hash facade provides secure Bcrypt hashing for storing user passwords.
I just checked the Auth code, your password column MUST be called password. You cannot use jelszo
Also - yourr login code is incorrect. You just do this:
if (Auth::attempt(array(
'email' => $email,
'password' => $password
))) {
echo 'Working';
} else {
echo 'Not working';
}
Auth::attempt() will do the hashing for you.