Check this article http://www.codeheaps.com/php-programming/laravel-5-new-auth-generators-user-authentication/
@pzotov I've seen that article before, I'm not sure if I'm missing something but what I want to do is create a custom UserProvider, as default we have EloquentUserProvider and DatabaseUserProvider and I already know how to create my custom UserProvider my I dont know how I set this provider for use just like:
Auth::extend('dummy', function($app)
{
return new MyApp\Extensions\DummyAuthProvider;
});
Hi, Let us do it step by step :)
driver
key inside config/auth.php
like this: 'driver' => 'custom',
Auth
directory inside the app
root (or in a place of your preference) and create the User Provider Interface implementation. I will name the file as CustomUserProvider
.php:<?php namespace App\Auth;
use Illuminate\Contracts\Auth\User as UserContract;
use Illuminate\Auth\UserProviderInterface;
class CustomUserProvider implements UserProviderInterface {
protected $model;
public function __construct(UserContract $model)
{
$this->model = $model;
}
public function retrieveById($identifier)
{
}
public function retrieveByToken($identifier, $token)
{
}
public function updateRememberToken(UserContract $user, $token)
{
}
public function retrieveByCredentials(array $credentials)
{
}
public function validateCredentials(UserContract $user, array $credentials)
{
}
}
Now implement the UserProviderInterface methods however you want.
app/Providers
directory and name it according to the convention you are using. I will call it `CustomAuthProvider'.php. Now, in this file we will register the new auth drivers that we have specified inside the config file:<?php namespace App\Providers;
use App\User;
use App\Auth\CustomUserProvider;
use Illuminate\Support\ServiceProvider;
class CustomAuthProvider extends ServiceProvider {
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
$this->app['auth']->extend('custom',function()
{
return new CustomUserProvider(new User);
});
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
//
}
}
Now in the last step add the name of the provider into the providers array of the config/app.php file.
'providers' => [
/*
* Application Service Providers...
*/
'App\Providers\EventServiceProvider',
'App\Providers\RouteServiceProvider',
'App\Providers\CustomAuthProvider',
......
I hope you will get it right this time. Regards!
Thank you @usm4n, that's actually pretty simple, I'll try it tomorrow and I'll leave a comment here.
Thank you so much usm4n! I was almost there but stuck on how to register my custom UserProvider!
hey usm4n. this is a big help with what i need as well. thank you very much for this. :)
Hi @usm4n - Thanks for the help.
I've followed your guidance, and as you can see below, my code matches yours, however, when I try to load the site, it gives me this error:
[InvalidArgumentException]
Driver [custom] not supported.
From the stack trace it looks like the error is in AuthManager.php line 15, where it calls the createDriver() method. It appears its looking for a createCustomDriver() method (which obviously doesn't exist in authManager).
https://gist.github.com/josh7weaver/9de6162b442bdc3803b0
Did I miss something? Any input would be helpful... thanks!
@josh7weaver, sorry for being late to the party :).
The problem seems to be inside your boot
method, the name of the driver is not the same i.e. you have specified the name as 'driver ' => 'custom'
and then you are extending a different driver i.e. token
. Either change the driver name inside your config file as token
or use the name custom
inside the boot
method:
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
$this->app['auth']->extend('custom', function ($app)
{
$model = $app['config']['auth.model'];
return new CustomUserProvider($app['hash'], new $model);
});
}
Please note the new
operator, I have passed an instance of the Model
which in my case is App\User
. You will also need to change the constructor of your CustomUserProvider
:
class CustomUserProvider implements UserProvider {
/**
* The hasher implementation.
*
* @var \Illuminate\Contracts\Hashing\Hasher
*/
protected $hasher;
/**
* The Eloquent user model.
*
* @var string
*/
protected $model;
/**
* Create a new database user provider.
*
* @param \Illuminate\Contracts\Hashing\Hasher $hasher
* @param string $model
* @return void
*/
public function __construct(HasherContract $hasher, $model)
{
$this->model = $model; // the model instance passed from `boot` method.
$this->hasher = $hasher; // hasher of course.
}
///rest of the code....
Hope this will solve your issue.
Usman
Hi @usm4n
I've followed too your guidance and i don't understand my problem's, can you help me
You have the details of my problem in my gists, i resume :
In my CustomUserProvider.php i get my Fake user after attempt, but i loose the user after redirection in Authenticate.php i think a don't understand or i forget a step...
Do you have Idea ?
Thanks
Thanks Usman! with your help I figured out what the problems were. In addition to what you pointed out, it kept erroring because I had the following inside AppServiceProvider.php, which was getting called before the CustomAuthProvider.php:
public function boot()
{
view()->composer('layouts.default', function($view){
$view->with('currentUser', $this->app['auth']->user());
});
}
Once I moved the CustomAuthProvider to be loaded BEFORE I tried to send the ->user() message, it worked just fine!
Thanks alot for the walkthrough. One thing i'm not sure on is how to extend (or overwrite) the Guard class. For instance if I wanted to extend the user() function to return a different model depending on the type of user or return a Guest model when using Auth::user() rather than null. How would I go about that?
Sweeeeeet. And I thought I was gonna have to write a migration just to make my DB work with Laravel. :)
Thanks for sharing the solution.
I did everything. It seems works, no any error from Laravel 5. But I can not login. it gives me an error message: Login or password is wrong.
So, should I write sql query by myself? If yes, how?
thanks for the tutorial. Just one thing I had to change to make it work (maybe specific to Laravel 5.2 ?) : in my AuthServiceProvider I had to call
$this->app['auth']->provider(...
instead of $this->app['auth']->extend(...
Same here, I also had to call provider
instead of extend
in Laravel 5.2. Huge help when I could never find this noted anyplace else.
hi guys thanks for this discussion I had a same problem and this helped but now I try to log in but laravel still references the laravel attributes instead of my built in ones on the user model how can I solve that I am using the example provided here just changed the attributes to meet mine and also working in laravel 5.2 the error
ErrorException in CustomUserProvider.php line 96:
Undefined index: Username
in CustomUserProvider.php line 96
at HandleExceptions->handleError('8', 'Undefined index: Username', 'CustomUserProvider.php', '96', array('credentials' => array('email' => 'email', 'password' => 'pass'))) in CustomUserProvider.php line 96
at CustomUserProvider->retrieveByCredentials(array('email' => 'email', 'password' => 'pass')) in SessionGuard.php line 353
at SessionGuard->attempt(array('email' => 'email', 'password' => 'pass'), false) in AuthenticatesUsers.php line 74
at AuthController->login(object(Request))
at call_user_func_array(array(object(AuthController), 'login'), array(object(Request))) in Controller.php line 80
at Controller->callAction('login', array(object(Request))) in ControllerDispatcher.php line 146
at ControllerDispatcher->call(object(AuthController), object(Route), 'login') in ControllerDispatcher.php line 94
After sacfolding auth with:
php artisan make:auth
Than I am getting followinf error:
ErrorException in AuthManager.php line 294: Call to undefined method App\Extensions\CustomUserProvider::check() (View: ...my-api-project\resources\views\welcome.blade.php)
So, is it possible to use custom Auth with scafolded views?
After adding
public static function check()
{
return true;
}
to CustomUserProvider I am getting follwoing error:
FatalThrowableError in AuthManager.php line 294: Call to undefined method App\Extensions\CustomUserProvider::authenticate()
Here is my CustomUserProvider:
<?php
namespace App\Extensions;
use Illuminate\Contracts\Auth\User as UserContract;
use Illuminate\Contracts\Auth\UserProvider as UserProviderInterface;
use \Illuminate\Contracts\Auth\Authenticatable;
class CustomUserProvider implements UserProviderInterface
{
public function retrieveById($identifier)
{
// TODO: Implement retrieveById() method.
}
public function retrieveByToken($identifier, $token)
{
// TODO: Implement retrieveByToken() method.
}
public function updateRememberToken(Authenticatable $user, $token)
{
// TODO: Implement updateRememberToken() method.
}
public function retrieveByCredentials(array $credentials)
{
// TODO: Implement retrieveByCredentials() method.
}
public function validateCredentials(Authenticatable $user, array $credentials)
{
// TODO: Implement validateCredentials() method.
}
public static function check()
{
return true;
}
}
and here CustomAuthProvider:
<?php
namespace App\Extensions;
use App\User;
use App\Extensions\CustomUserProvider;
use Illuminate\Support\ServiceProvider;
class CustomAuthProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
$this->app['auth']->extend('custom',function()
{
return new CustomUserProvider(new User);
});
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
//
}
}
I changed my AUTH_DRIVER=custom. I wrote the custom files like CustomUserProvider and CustomAuthProvider.
MY problem is that the user is not logged in after a true returns from the validateCredentials method.
WHY?
gaalgergely said:
I changed my AUTH_DRIVER=custom. I wrote the custom files like CustomUserProvider and CustomAuthProvider.
MY problem is that the user is not logged in after a true returns from the validateCredentials method.
WHY?
Did you find a solution to your problem ? I am having the exact same issue.
gandra404 said:
After sacfolding auth with:
php artisan make:auth
Than I am getting followinf error:
ErrorException in AuthManager.php line 294: Call to undefined method App\Extensions\CustomUserProvider::check() (View: ...my-api-project\resources\views\welcome.blade.php)
So, is it possible to use custom Auth with scafolded views?
After adding
public static function check() { return true; }
to CustomUserProvider I am getting follwoing error:
FatalThrowableError in AuthManager.php line 294: Call to undefined method App\Extensions\CustomUserProvider::authenticate()
Here is my CustomUserProvider:
<?php namespace App\Extensions; use Illuminate\Contracts\Auth\User as UserContract; use Illuminate\Contracts\Auth\UserProvider as UserProviderInterface; use \Illuminate\Contracts\Auth\Authenticatable; class CustomUserProvider implements UserProviderInterface { public function retrieveById($identifier) { // TODO: Implement retrieveById() method. } public function retrieveByToken($identifier, $token) { // TODO: Implement retrieveByToken() method. } public function updateRememberToken(Authenticatable $user, $token) { // TODO: Implement updateRememberToken() method. } public function retrieveByCredentials(array $credentials) { // TODO: Implement retrieveByCredentials() method. } public function validateCredentials(Authenticatable $user, array $credentials) { // TODO: Implement validateCredentials() method. } public static function check() { return true; } }
and here CustomAuthProvider:
<?php namespace App\Extensions; use App\User; use App\Extensions\CustomUserProvider; use Illuminate\Support\ServiceProvider; class CustomAuthProvider extends ServiceProvider { /** * Bootstrap the application services. * * @return void */ public function boot() { $this->app['auth']->extend('custom',function() { return new CustomUserProvider(new User); }); } /** * Register the application services. * * @return void */ public function register() { // } }
Hey man, did you found the solution? I got the same trouble and can't fix it. Help me pls
It is necessary to use Laravel authentication controller when we use custom authentication driver...About the solution, already @usm4n gave a great solution for the custom authentication. For any query regarding Laravel development, just visit; hirelaraveldeveloperindia.com
In my case, the key was to understand retrieveById() and retrieveByCredentials. I believe it is mandatory that they return the proper info for this to work. I figured it out by doing var_dump(Auth::user()) on a default install and comparing it to what my custom auth provider install was doing. Also found a brief comment in Laravel docs that I had missed before.
https://laravel.com/docs/5.5/authentication#adding-custom-user-providers
The retrieveById function typically receives a key representing the user, such as an auto-incrementing ID from a MySQL database. The Authenticatable implementation matching the ID should be retrieved and returned by the method.
So retrieveById and retreiveByCredentials should both return the same object. The same as the default auth scaffold returns from User Model. I am pretty sure this is mandatory for Auth to work. Only in this case it will return your Custom Model such as Admin.php or whatever.
I don't think any other Methods in CustomUserProvider need to return anything except ValidateCredentials() which can just be set to return true;
for testing
Since Laravel 5.5 is out now, I will explain the process for this version. To add custom authentication in Laravel 5.5, you have to add auth to your main controller file.
<?php
namespaceAppHttpControllers;
useRedirect;
useAuth;
useInput;
useIlluminateSupportFacadesValidator;
useIlluminateFoundationBusDispatchesJobs;
useIlluminateRoutingController as BaseController;
useIlluminateFoundationValidationValidatesRequests;
useIlluminateFoundationAuthAccessAuthorizesRequests;
useIlluminateFoundationAuthAccessAuthorizesResources;
useIlluminateHtmlHtmlServiceProvider;
class MainController extends BaseController
{
public
function showLogin()
{
// Form View
return view('login');
}
public
function doLogout()
{
Auth::logout(); // logging out user
return Redirect::to('login'); // redirection to login screen
}
public
function doLogin()
{
// Creating Rules for Email and Password
$rules = array(
'email' => 'required|email', // make sure the email is an actual email
'password' => 'required|alphaNum|min:8'
// password has to be greater than 3 characters and can only be alphanumeric and);
// checking all field
$validator = Validator::make(Input::all() , $rules);
// if the validator fails, redirect back to the form
if ($validator->fails())
{
return Redirect::to('login')->withErrors($validator) // send back all errors to the login form
->withInput(Input::except('password')); // send back the input (not the password) so that we can repopulate the form
}
else
{
// create our user data for the authentication
$userdata = array(
'email' => Input::get('email') ,
'password' => Input::get('password')
);
// attempt to do the login
if (Auth::attempt($userdata))
{
// validation successful
// do whatever you want on success
}
else
{
// validation not successful, send back to form
return Redirect::to('checklogin');
}
}
}
}
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community