Cakephp Identify user using REST API - php

I'm developing an API for an application that I'm creating. This application will get all the information from this API (first will auth the user, then get information)
Right now, I'm trying to make the user send a username and password to the API, it validates the information and returns if it's "ok" or "not", very simple to start only. I know all the security involved in this, just need to get this working.
Already managed to send the username and passsword on the API Side (and i'm 100% sure that the data is correctly saved). Though, when I call
$this->Auth->identify($this->request->data);
It always returns false to me (already tried with parameters and without, result is the same).
I'm using the HttpRequester, firefox plugin, to send information.
I've did a debug of $this->request->data to see if the information is correct, and it is. Can't do a find on database since the password is being hashed.
The database password field is a varchar with 300 length (already tried with 255, also no work)
Thanks for the help
EDIT:
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email',
'password' => 'password'
]
],
]
]);
if($this->request->is('POST')){
//debug($this->request->data);
$user = $this->Auth->identify($this->request->data);
}
Users Table:
protected $_accessible = [
'*' => true,
];
/**
* Hash password
*
*/
protected function _setPassword($password)
{
return (new DefaultPasswordHasher)->hash($password);
}
protected function _getFullName()
{
if(isset($this->_properties['full_name'])){
return ucwords(mb_strtolower($this->_properties['full_name']));
}
}
ps: Also tried doing the following (replacing the variables form post, but also no luck)
$this->request->data['username'] = "xxxx";
$this->request->data['password'] = "zzzz";

Problem is here
'Form' => [
'fields' => [
'username' => 'email', //email is your database field
'password' => 'password' // password is your database field name
]
],
Your code should be
'Form' => [
'fields' => [
'username' => 'username',
'password' => 'password'
]
],
Details check Configuring Authentication Handlers

Related

Laravel Passport Grant Token — Set custom username and password fields

I am working on project which has separate model for users — App\Models\Customer. And also it has own authorisation fields — Email and cust_password. And also password is hashed by password_hash function.
In my config/auth.php in providers section I set up my custom model:
'providers' => [
'customers' => [
'driver' => 'eloquent',
'model' => App\Models\Customer::class,
],
],
So I am trying to implement Laravel Grand Tokens. I need to make request to /oauth/token/ with client (which was previously created with custom provider field) and customer credentials as like this:
/** #var \Laravel\Passport\Client $client */
$response = Http::asForm
->post('https://localhost/oauth/token/', [
'grant_type' => 'password',
'client_id' => $client->id,
'client_secret' => $client->secret,
'username' => 'example#example.com',
'password' => password_hash('my-password'),
]);
But I am receiving error: invalid_grant — The user credentials were incorrect.
I assume that Passport doesn't know where to find my Email and cust_password fields. Is there any way to set custom login and password fiends?
Thanks you any advice!
Well, I wasn't attentive enough, there is special topics for this situations:
Customizing The Username Field https://laravel.com/docs/9.x/passport#customizing-the-username-field
Customizing The Password Validation https://laravel.com/docs/9.x/passport#customizing-the-password-validation

CakePHP DC Users 8.5.1 customising to use email

I have a CakePHP application running on Cake PHP 3.8.13 and CakeDC Users 8.5.1.
I am currently able to log on using the username field, but I would like to use the email field for authentication. I have followed the instructions on https://github.com/CakeDC/users/blob/master/Docs/Documentation/Configuration.md#using-the-users-email-to-login but the system is still trying to use the username field. If I change email to username in the src/Template/Plugin/CakeDC/Users/Users/login.ctp I can log in using the username.
How can I get it to use the email field instead?
src/Application.php
<?php
namespace App;
use Cake\Core\Configure;
use Cake\Core\Exception\MissingPluginException;
use Cake\Error\Middleware\ErrorHandlerMiddleware;
use Cake\Http\BaseApplication;
use Cake\Http\Middleware\SecurityHeadersMiddleware;
use Cake\Routing\Middleware\AssetMiddleware;
use Cake\Routing\Middleware\RoutingMiddleware;
use Cake\Http\Middleware\EncryptedCookieMiddleware;
class Application extends BaseApplication
{
/**
* {#inheritDoc}
*/
public function bootstrap()
{
// Call parent to load bootstrap from files.
parent::bootstrap();
$this->addPlugin('AuditStash');
if (PHP_SAPI === 'cli') {
try {
$this->addPlugin('Bake');
} catch (MissingPluginException $e) {
// Do not halt if the plugin is missing
}
$this->addPlugin('Migrations');
}
/*
* Only try to load DebugKit in development mode
* Debug Kit should not be installed on a production system
*/
if (Configure::read('debug')) {
$this->addPlugin(\DebugKit\Plugin::class);
}
$this->addPlugin(\CakeDC\Users\Plugin::class);
Configure::write('Users.config', ['users']);
$identifiers = Configure::read('Auth.Identifiers');
$identifiers['Authentication.Password']['fields']['username'] = 'email';
Configure::write('Auth.Identifiers', $identifiers);
}
/**
* Setup the middleware queue your application will use.
*
* #param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to setup.
* #return \Cake\Http\MiddlewareQueue The updated middleware queue.
*/
public function middleware($middlewareQueue)
{
$securityHeaders = new SecurityHeadersMiddleware();
$securityHeaders
->setCrossDomainPolicy()
->setReferrerPolicy()
->setXFrameOptions()
->setXssProtection()
->noOpen()
->noSniff();
$middlewareQueue
// Add security headers
->add($securityHeaders)
// Catch any exceptions in the lower layers,
// and make an error page/response
->add(ErrorHandlerMiddleware::class)
// Handle plugin/theme assets like CakePHP normally does.
->add(new AssetMiddleware([
'cacheTime' => Configure::read('Asset.cacheTime')
]))
// Add routing middleware.
// Routes collection cache enabled by default, to disable route caching
// pass null as cacheConfig, example: `new RoutingMiddleware($this)`
// you might want to disable this cache in case your routing is extremely simple
->add(new RoutingMiddleware($this, '_cake_routes_'));
$cookies = new EncryptedCookieMiddleware(
// Names of cookies to protect
['remember_me', 'csrfToken'],
Configure::read('Security.cookieKey')
);
$middlewareQueue->add($cookies);
return $middlewareQueue;
}
}
src/config/users.php
<?php
return [
// Table used to manage users
'table' => 'Users',
// Controller used to manage users plugin features & actions
'controller' => 'Users',
// configure Auth component
'auth' => true,
// Password Hasher
'passwordHasher' => '\Cake\Auth\DefaultPasswordHasher',
// token expiration, 1 hour
'Token' => ['expiration' => 3600],
'Email' => [
// determines if the user should include email
'required' => true,
// determines if registration workflow includes email validation
'validate' => true,
],
'Registration' => [
// determines if the register is enabled
'active' => false,
// determines if the reCaptcha is enabled for registration
'reCaptcha' => true,
// allow a logged in user to access the registration form
'allowLoggedIn' => false,
//ensure user is active (confirmed email) to reset his password
'ensureActive' => false,
// default role name used in registration
'defaultRole' => 'user',
],
'reCaptcha' => [
// reCaptcha key goes here
'key' => null,
// reCaptcha secret
'secret' => null,
// use reCaptcha in registration
'registration' => false,
// use reCaptcha in login, valid values are false, true
'login' => false,
],
'Tos' => [
// determines if the user should include tos accepted
'required' => true,
],
'Social' => [
// enable social login
'login' => false,
// enable social login
'authenticator' => 'CakeDC/Users.Social',
],
'GoogleAuthenticator' => [
// enable Google Authenticator
'login' => false,
'issuer' => null,
// The number of digits the resulting codes will be
'digits' => 6,
// The number of seconds a code will be valid
'period' => 30,
// The algorithm used
'algorithm' => 'sha1',
// QR-code provider (more on this later)
'qrcodeprovider' => null,
// Random Number Generator provider (more on this later)
'rngprovider' => null
],
'Profile' => [
// Allow view other users profiles
'viewOthers' => false,
'route' => ['plugin' => 'CakeDC/Users', 'controller' => '\Users', 'action' => 'profile'],
],
'Key' => [
'Session' => [
// session key to store the social auth data
'social' => 'Users.social',
// userId key used in reset password workflow
'resetPasswordUserId' => 'Users.resetPasswordUserId',
],
// form key to store the social auth data
'Form' => [
'social' => 'social'
],
'Data' => [
// data key to store the users email
'email' => 'email',
// data key to store email coming from social networks
'socialEmail' => 'info.email',
// data key to check if the remember me option is enabled
'rememberMe' => 'remember_me',
],
],
// Avatar placeholder
'Avatar' => ['placeholder' => 'CakeDC/Users.avatar_placeholder.png'],
'RememberMe' => [
// configure Remember Me component
'active' => false,
'checked' => true,
'Cookie' => [
'name' => 'remember_me',
'Config' => [
'expires' => '1 month',
'httpOnly' => true,
]
]
],
];
src/Template/Plugin/CakeDC/Users/Users/login.ctp
<?php
use Cake\Core\Configure;
?>
<div class="users form">
<?= $this->Flash->render('auth') ?>
<?= $this->Form->create() ?>
<fieldset>
<legend><?= __d('CakeDC/Users', 'Please enter your username and password') ?></legend>
<?= $this->Form->control('email', ['required' => true]) ?>
<?= $this->Form->control('password', ['required' => true]) ?>
</fieldset>
<?= $this->Form->button(__d('CakeDC/Users', 'Login')); ?>
<?= $this->Form->end() ?>
</div>
Add this code
$identifiers = Configure::read('Auth.Identifiers');
$identifiers['Authentication.Password']['fields']['username'] = 'email';
Configure::write('Auth.Identifiers', $identifiers);
to your pluginBootstrap() function in Application, or ensure the identifier configuration is correctly updated in the config/users.php file, so the plugin will be able to read it and configure Authentication internally.

Trying to store login history inside laravels basic exampel for "manually authenticating users"

I used Laravel's guide to authenticating users manually at this link:
https://laravel.com/docs/7.x/authentication#remembering-users
and now I want to log every login's browser, version, platform, and ip.
My function on login:
public function store(Request $request)
{
$this->validate($request, [
'username' => 'required',
'password' => 'required'
]);
if (Auth::guard('admin')->attempt(['username' => $request->username, 'password' => $request->password, 'status' => 1], $request->remember)) {
$browserDetails = get_browser($request->header('User-Agent'), true);
LoginHistory::create([
'user_id' => auth()->guard('admin')->user()->id,
'user_type' => '2', // Admin = 2
'browser' => $browserDetails['browser'],
'browser_version' => $browserDetails['version'],
'platform' => $browserDetails['platform'],
'ip_address' => $request->ip()
]);
return redirect()->route('admin.dashboard');
}
return redirect()->back()->withErrors('Username or password incorrect.');
}
but I am getting:
ErrorException
Trying to get property 'id' of non-object
on this line:
'user_id' => auth()->guard('admin')->user()->id,
What should I do? The authentication works if I try to access login it will redirect me to dashboard so the session is created, but why can I not access the user id inside this function? It works on the edit admins page showing user id and all information.
use auth()->user()->id. when attempt () is executed and this is successful it performs the authentication

Show error of two strings are equal in unit testing

I have created a small Laravel project and I am applying unit testing on my project. When I fill wrong credentials in function, it doesn't redirect to the login page and shows error on terminal saying Failed asserting that two strings are equal. Here is my code...
$credentials = [
'email' => 'test#gmail.com',
'password' => 'wrongcode'
];
$this->post('/login', $credentials)->assertRedirect('/login');
But when i change assertRedirect('/login') to assertRedirect('/') , it works fine
$credentials = [
'email' => 'test1234#gmail.com',
'password' => '98756412'
];
$this->post('/login', $credentials)->assertRedirect('/');
assertRedirect checks two string, one of them is an argument of method, 2nd is redirect path. Looks like everything works fine. You write a test, test failed, you have feedback to improve application. In that case, the redirect path is different than expected by you.
There should be 2 different methods for an individual scenario like below.
public function testCorrectCredential() {
$credentials = [
'email' => 'test1234#gmail.com',
'password' => '98756412'
];
$this->post('/login', $credentials)->assertRedirect('/');
}
public function testInCorrectCredential() {
$credentials = [
'email' => 'incorrect#gmail.com',
'password' => '98756412'
];
$this->post('/login', $credentials)->assertRedirect('/incorrect-url');
}

How to use Auth in cakephp using mongodb

I have a mongo db structure for users with "username" and "password". I am trying to use the Auth in cakephp login but it seems like its not working for me. I tried removing the $this->data but still it did not work.
My password is hashed using Security::hash($this->data['User']['password'])
if(!empty($this->data))
{
if($this->Auth->login($this->data))
{
echo "yes";
}
else{
echo "no";
}
}
In my app controller I have this:
public $components = array('DebugKit.Toolbar', 'Session', 'Auth' => array(
'loginAction' => array(
'controller' => 'pages',
'action' => 'home'
),
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'username', 'password' => 'password')
)
)
));
Here is the result when I debug the login method:
array(
'User' => array(
'password' => '*****',
'username' => 'test#test.com',
'remember' => '0',
'auto_login' => '0'
)
)
I don't know why I cannot use Auth with mongodb. Thanks for the help in advance.
EDIT:
When i tried and take away the layout, it shows me a query at the bottom of the page saying:
db.users.find( {"username":"test#test.com","password":"2fdf49ffc396453960802df8fc2417655d1e8fca"}, [] ).sort( [] ).limit( 1 ).skip( 0 )
The hashed value of the password that I inputted from the form is different from the hash value that is being queried. The hashed value should be "a2374c309ab7823dcd9b4e21dae7511f7a9c7ec5". Why is it that cakephp is converting the password into another hash value?
There are two ways of using $this->Auth->login(). The CakePHP API documentation explains it:
If a $user is provided that data will be stored as the logged in user. If $user is empty or not specified, the request will be used to identify a user.
The manual also mentions:
In 2.0 $this->Auth->login($this->request->data) will log the user in with whatever data is posted ...
So for the login method of the users controller you shouldn't pass anything:
if($this->Auth->login()) {
// user is now logged in
}
Should you need to manually login a user you can pass the user data as an array:
if($this->Auth->login($this->request->data['User'])) {
// user is now logged in
}
Where $this->request->data['User'] is something like:
array(
'id' => 1,
'username' => 'admin',
'password' => '1234',
);
Note: In both cases you don't need to hash the password as it is done automatically.
I was able to find out the answer. Its because cakephp is automatically hashing the password when searching in the database.
The problem that I had was when I was saving the users' password, I am was using
Security::hash($this->data['User']['password'])
I should have used this one instead:
AuthComponent::password($this->data['User']['password'])
Thank you for all the help especially to #xgalvin

Categories