CakePHP Changing Auth Fields isn't working - php

I'm currently trying to change my cakephp login from using the username field to using the email field.
When using the username field, the login works fine, here's the code for the login with username:
login.ctp
<?php
echo $this->Form->create('User');
echo $this->Form->input('username');
echo $this->Form->input('password');
echo $this->Form->end(__('Login'));
?>
UsersController.php
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('add', 'login'); // Letting users register themselves
$this->Auth->fields = array('username' => 'username', 'password' => 'password');
}
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->Session->setFlash(__('worked'));
} else {
debug($this->data);
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
}
AppController
public $components = array('Session', 'Auth');
So this all works fine, I can login with test details.
So to change this to using an email, all I have done is:
Change the input in login.ctp from username to email
echo $this->Form->input('email');
Change the fields array in userscontroller from username to email
$this->Auth->fields = array('username' => 'email', 'password' => 'password');
Change the database field from username to email
I then try to login using the same test details and it tells me they are incorrect.
Does anyone have any idea why this wouldn't work?

In Cake 2.x it's a little different
$this->Auth->authenticate = array(
'Form' => array(
'fields' => array('username' => 'email', 'password' => 'password'),
),
);

Related

Allow login using username or email in Laravel 5.4

Now I've followed the Laravel documentation on how to allow usernames during authentication, but it takes away the ability to use the email. I want to allow users to use their username or email to login. How do I go about this?
I've added this code to the LoginController as per Laravel's Documentation and it only allows username for login. I want it to accept username or email for login.
public function username () {
return 'username';
}
I think a simpler way is to just override the username method in LoginController:
public function username()
{
$login = request()->input('login');
$field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
request()->merge([$field => $login]);
return $field;
}
Follow instructions from this link: https://laravel.com/docs/5.4/authentication#authenticating-users
Then you can check for the user input like this
$username = $request->username; //the input field has name='username' in form
if(filter_var($username, FILTER_VALIDATE_EMAIL)) {
//user sent their email
Auth::attempt(['email' => $username, 'password' => $password]);
} else {
//they sent their username instead
Auth::attempt(['username' => $username, 'password' => $password]);
}
//was any of those correct ?
if ( Auth::check() ) {
//send them where they are going
return redirect()->intended('dashboard');
}
//Nope, something wrong during authentication
return redirect()->back()->withErrors([
'credentials' => 'Please, check your credentials'
]);
This is just a sample. THere are countless various approaches you can take to accomplish the same.
Open your LoginController.php file.
Add this reference
use Illuminate\Http\Request;
And override the credentials method
protected function credentials(Request $request)
{
$field = filter_var($request->get($this->username()), FILTER_VALIDATE_EMAIL)
? 'email'
: 'username';
return [
$field => $request->get($this->username()),
'password' => $request->password,
];
}
Successfully tested in Laravel 5.7.11
You need to override protected function attemptLogin(Request $request) method from \Illuminate\Foundation\Auth\AuthenticatesUsers Trait in your LoginController
i.e. in my LoginController class
protected function attemptLogin(Request $request) {
$identity = $request->get("usernameOrEmail");
$password = $request->get("password");
return \Auth::attempt([
filter_var($identity, FILTER_VALIDATE_EMAIL) ? 'email' : 'username' => $identity,
'password' => $password
]);
}
Your LoginController class should use Trait \Illuminate\Foundation\Auth\AuthenticatesUsers in order to override attemptLogin method i.e.
class LoginController extends Controller {
use \Illuminate\Foundation\Auth\AuthenticatesUsers;
.......
.......
}
I think its even more simple, just override the method from AuthenticatesUsers traits, credentials method in your LoginController. Here I have implemented to login with either email or phone. You can change it to fit your needs.
LoginController.php
protected function credentials(Request $request)
{
if(is_numeric($request->get('email'))){
return ['phone'=>$request->get('email'),'password'=>$request->get('password')];
}
return $request->only($this->username(), 'password');
}
This is the way I do it:
// get value of input from form (email or username in the same input)
$email_or_username = $request->input('email_or_username');
// check if $email_or_username is an email
if(filter_var($email_or_username, FILTER_VALIDATE_EMAIL)) { // user sent his email
// check if user email exists in database
$user_email = User::where('email', '=', $request->input('email_or_username'))->first();
if ($user_email) { // email exists in database
if (Auth::attempt(['email' => $email_or_username, 'password' => $request->input('password')])) {
// success
} else {
// error password
}
} else {
// error: user not found
}
} else { // user sent his username
// check if username exists in database
$username = User::where('name', '=', $request->input('email_or_username'))->first();
if ($username) { // username exists in database
if (Auth::attempt(['name' => $email_or_username, 'password' => $request->input('password')])) {
// success
} else {
// error password
}
} else {
// error: user not found
}
}
I believe there is a shorter way to do that, but for me this works and is easy to understand.
public function username()
{
//return ‘identity’;
$login = request()->input('identity');
$field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'phone';
request()->merge([$field => $login]);
return $field;
}
protected function validateLogin(Request $request)
{
$messages = [
'identity.required' => 'Email or username cannot be empty',
'email.exists' => 'Email or username already registered',
'phone.exists' => 'Phone No is already registered',
'password.required' => 'Password cannot be empty',
];
$request->validate([
'identity' => 'required|string',
'password' => 'required|string',
'email' => 'string|exists:users',
'phone' => 'numeric|exists:users',
], $messages);
}
https://dev.to/pramanadiputra/laravel-how-to-let-user-login-with-email-or-username-j2h
This solution of "Rabah G" works for me in Laravel 5.2. I modified a litle but is the same
$loginType = request()->input('useroremail');
$this->username = filter_var($loginType, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
request()->merge([$this->username => $loginType]);
return property_exists($this, 'username') ? $this->username : 'email';
Thanks, this is the solution I got thanks to yours.
protected function credentials(Request $request) {
$login = request()->input('email');
// Check whether username or email is being used
$field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'user_name';
return [
$field => $request->get('email'),
'password' => $request->password,
'verified' => 1
];
}

CakePHP 2.x first login with hash password no users in DB

I have already check and when I create users and passwords and then I try to login and is successful, however if for example I install on other device my project and set up my DB I enter to my system how can I access for first time if I dont have users created?
1) I tried to create user and password on my database but it cant recognize the password due to hashing methods.
How can i access for the first time and then create users as normal?
My login access controller:
public function login() {
//if already logged-in, redirect
if($this->Session->check('Auth.User')){
$this->redirect(array('action' => 'index'));
}
// if we get the post information, try to authenticate
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->Session->setFlash(__('Bienvenido, '. $this->Auth->user('username')));
$this->redirect($this->Auth->redirectUrl());
} else {
$this->Session->setFlash(__('Usuario o password invalidos'));
}
}
$this->layout = 'login';
}
appcontroller:
class AppController extends Controller {
//public $components = array('DebugKit.Toolbar');
public $components = array(
//'DebugKit.Toolbar',
'Session',
'Auth' => array(
'authorize' => 'Controller',
'actionPath' => 'controllers/',
'loginRedirect' => array('controller' => 'users', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'users', 'action' => 'login'),
'authError' => 'You must be logged in to view this page.',
'loginError' => 'Invalid Username or Password entered, please try again.'
),
);
// only allow the login controllers only
public function beforeFilter() {
$this->Auth->allow('login','view','index','logout','getData');
}
public function isAuthorized($user) {
// Here is where we should verify the role and give access based on role
if (isset($user['role']) && $user['role'] === 'adm') {
return true;
}
if (in_array($this->action, array('add','getData','getDataArticulos','addDetFac','descargar','getNit'))) {
if (isset($user['role']) && $user['role'] === 'vend')
return true;
else
return $this->Session->setFlash(__('Acceso denegado.'), 'error');
}
return $this->Session->setFlash(__('Acceso denegado.'), 'error');
}
}
At first allow add method.
public function beforeFilter() {
$this->Auth->allow('login','view','index','logout','getData','add');
}
Then create a user, write in your browser URL your_project_path/users/add
After add 1st user remove add from Auth allow.

CakePHP login without use of password, ONLY username

After reading the post: logging without password
I made a personal attempt:
AppController:
function beforeFilter(){
$this->Auth->loginError = "This message shows up when the wrong credentials are
used";
//$this->Auth->authError = "This error shows up with the user tries to access a part
of the website that is protected.";
//$this->Auth->authError = "";
$this->Auth->fields = array(
'username' => 'username',
'password' => null
);
UsersController, inside add():
// Save new user
if ($this->User->save(array('username' => $this->request->data['User']['username'],
'password' => $this->Auth->password(null),
'name' => $this->request->data['User']['name'],
'surname' => $this->request->data['User']['surname'],
'chosenLayout' => $this->request->data['User']['chosenLayout'],
'dateCreated' => $this->request->data['User']['dateCreated'],
'dateModified' => $this->request->data['User']['dateModified'],
'role_id' =>$this->request->data['User']['role_id']
))) {
$this->Session->setFlash(__('message_success_user_added',
array($this->request->data['User']['username'])), 'default', array(), 'success');
$this->redirect(array('action' => 'index'));
}
else {
// Validation error
$this->Session->setFlash(__('message_fail_validation'), 'default', array(), 'fail');
}
Then entered as admin and created some dummy users with null or random password.
Checking the database encrypted passwords were all the same ( a hashed null string) which means the modification in add() function worked...
Inside UsersController login():
// Login User
public function login() {
// Check if the user is already logged in
if ($this->Session->check('Auth.User.id')){
// Redirect to login page
$this->redirect($this->Auth->loginRedirect);
}
else{
// If the user is not logged in
session_set_cookie_params(0);
// If the request is a POST request
if ($this->request->is('post')) {
//get credentials
$this->username = $this->request->data['User']['username'];
$this->password = $this->request->data['User']['password'];
$this->domain = $this->request->data['User']['domain'];
//debug($this->username);
debug($this->domain) ;
//Check if username exists in local DB
//debug($this->User->findByUsername( $this->username ));
if ($this->Auth->login(
array(
'username'=> $this->username,
'password'=> null)
)){
// debug($this->Auth->login(array(
// 'username'=> $this->username,
// 'password'=> null
// )));
// Successful login
// Get all the user information and store in Session
//debug($this->Auth);
$this->User->id = $this->Auth->user('id');
debug($this->User->id);
debug($this->User);
$this->User->contain(array('User', 'Role' => array('Ui', 'Action.name')));
$this->Session->write('User', $this->User->read());
$actions = array();
foreach ($this->Session->read('User.Role.Action') as $key => $value){
array_push($actions, $value['name']);
}
$this->Session->write('User.Role.Action', $actions);
debug($actions);
// Render different layout depending on user type
if($this->Session->read('User.Role.Ui.name') == Configure::read('usertype.msp')){
$this->Session->write('SessionValues.ui', Configure::read('usertype.msp'));
$this->Auth->loginRedirect = array('controller' => 'PortStats', 'action' =>
'index');
}
else if($this->Session->read('User.Role.Ui.name') ==
Configure::read('usertype.tsc')){
$this->Session->write('SessionValues.ui', Configure::read('usertype.tsc'));
$this->Auth->loginRedirect = array('controller' => 'PortStats', 'action' =>
'index');
}
else if($this->Session->read('User.Role.Ui.name') ==
Configure::read('usertype.superAdminUserType')){
$this->Auth->loginRedirect = array('controller' => 'Uis', 'action' => 'index');
}
// Redirect to main login page
$this->redirect($this->Auth->loginRedirect);
}
else {
// Failed login user
session_destroy();
$this->Session->setFlash(__('Login failed:
access not granted'), 'default', array(), 'fail');
}
}
}
}
Then I try to login with my new users.I get the failed login message.
Which means $this->Auth->login returns false.
It must be as easy as that but something is going wrong.
In the meantime my debug trace:
Warning (2): Invalid argument supplied for foreach()
[APP\Controller\UsersController.php, line 85]
Simplify it. It is not a login, but a registration process, so don't confuse those two totally different things.
You just
create the user including proper validation
on success use Auth->login($user['User']) to set the auth session manually
only then redirect manually to where you want the user to go after a registration here
For a live example see https://github.com/dereuromark/cakefest/blob/master/Controller/AccountController.php#L166

cookie is not saving Cakephp

Cake is not saving the cookie, at least not that I can see, and when I revisit the page I am not auto logged in.i actually want to implement the 'remember me functionality '.i am using this component
https://github.com/ceeram/Authenticate/wiki/Set-Cookie
here is my code
login.ctp
echo $this->form->create();
echo $this->form->input('email');
echo $this->form->input('password');
<?php echo $this->Form->checkbox('remember_me', array('hiddenField' => false,'name' => 'remember_me'));?>
echo $this->form->end('submit');
?>
UserController
<?php
class UsersController extends AppController {
public $components = array('Cookie');
public function beforeFilter() {
parent::beforeFilter();
$this->Cookie->type('rijndael');
$this->Security->requireSecure('login');// for security
$this->Auth->authenticate = array(
'Authenticate.MultiColumn' => array(
'fields' => array(
'username' => 'email',
'password' => 'password'
),
'columns' => array('email', 'mobileNo'),
'userModel' => 'User',
)
);
}
public function index(){
}
public function login() {
$this->layout='userdefault';
if ($this->request->is('post')) {
//$this->Auth->logout();
$cookie = $this->Cookie->read('Auth.User');
debug($cookie);
if ($this->Auth->login()) {
$this->_setCookie($this->Auth->user('id'));
$this->redirect('/users/controlpanel');
} else {
$this->Session->setFlash('Incorrect Email/Password Combination');
}
}
}
protected function _setCookie($id) {
if (!$this->request->data('User.remember_me')) {
return false;
}
$data = array(
'username' => $this->request->data('User.email'),
'password' => $this->request->data('User.password')
);
$this->Cookie->write('User', $data, true, '+1 week');
return true;
}
public function logout() {
$this->redirect($this->Auth->logout());
}
public function controlpanel(){
$this->layout='controlpaneldefault';
}
}
?>
and also tell me how can i check or debug the cookie to check that whether my cookie saving or not or if debugging is not possible then tell me how can i set the name of the cookie so i go in the browser cookies and search the cookie with name
insert exit(); after debug($cookie); for check cookie data.

CakePHP 2.1 Adding fields to login page

I have made a a basic login form with three fields, they're "company", "employee", and "password" I tried using the default Auth component:
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
}
but as this parses the default "username", and "password" fields I can't log in. How can I change the Auth function to validate my three fields and log me in?
Sorry if this is a noob question, I had a read through http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html but nothing on there helped.
Try the following:
public function beforeFilter() {
$this->Auth->authenticate = array(
'Form' => array(
'fields' => array(
'username' => 'employee',
),
),
);
}
public function login() {
if ($this->request->is('post')) {
$this->Auth->authenticate['Form']['scope'] = array(
'User.company_id' => $this->request->data['User']['company_id'],
// or however this condition needs to be setup as
);
if ($this->Auth->login()) {
// login success
} else {
// login fail
}
}
}
Basically, add the third condition as a scope.

Categories