EnricoScariot's avatar

Custom Authentication changing only the default Auth Provider

Hi, i'm trying to make a custom authentication for my Laraver web application because i want to authenticate the user not via database query but using a web API from an external website. That's how i decided to proceed:

I want to create an authentication changing the less possible amount of code, trying to mantain all the default auth characteristics So i'm using the web guard (the default guard) changing only the provider driver (users)

 /**
     * Retrieve a user by the given credentials.
     *
     * @param    array  $credentials
     * @return  \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveByCredentials(array $credentials)
    {
        $user_info=[];

        $user_info+=['name' => 'Jon'];
        $user_info+=['surname' => 'Doe'];
        $user_info+=['taxcode' => 'JND89F48W345Q'];
        $user_info+=['birthdate' => '1456-03-22'];
        $user_info+=['health_service_description' => 'Ecografia osteo articolare'];
        $user_info+=['reservation_day' => '2017-03-22'];
        $user_info+=['first_zip_download_date' => '2019-04-02'];
        $user_info+=['accession_number' => '34243234'];
        $user_info+=['order_id' => '52'];
        $user_info+=['active' => '1'];

        Log::info($user_info);
     
        $user=new User($user_info);
       
        return $user;

    }

    /**
     * Validate a user against the given credentials.
     *
     * @param    \Illuminate\Contracts\Auth\Authenticatable  $user
     * @param    array  $credentials
     * @return  bool
     */
    public function validateCredentials(UserContract $user, array $credentials)
    {
        

        return true;
    }

I've only implemented these two methods, the second is returning true only to allow me to authenticate my user in anyway. Than i've added my new provider like this, in Providers->AuthServiceProvider.php

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

  
        Auth::provider('custom_provider', function($app, array $config) {
            switch(config('custom.auth_type')) { 
                case "CUSTOM":
                return new CustomAuthenticationProvider();
                    break;
            }
        });
       
   }

And in the config->auth.php i've changed the driver of my provider like this, using the default provider:

 'providers' => [
        'users' => [
            'driver' => 'custom_provider',
         //   'model' => App\Models\PortalUser::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

The problem is the following: my user is apparently authenticated and i can use all the user methods (like for example user(), check(), ecc) provided by the Auth facade but only in the LoginContoller, for example i have overriden the authenticated method that is called after the user is authenticated and it return correctly true if i log Auth::check() and the username if i log Auth::user()->name

    /**
     * The user has been authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  mixed  $user
     * @return mixed
     */
    protected function authenticated(Request $request, $user)
    {
     Log::info("the user is authenticated Auth::check is ".Auth::check()."and the user name is ".Auth::user()->name);
    }

But if i try, after the authentication, to redirect into a route of the auth middleware it'doesn't work, if i put the route outside the auth middleware and open that url/route, Auth::check() returns false.... basically it seems like i can't extend my authentication outside the login controller....

0 likes
4 replies
TECreasey's avatar

I too want to Authenticate a user using an external API.

I have read the documentation on Passport, and unless I am missing something, it only appears to talk about using Laravel as an API for other external services and not the other way round.

I feel a custom provider created for Socialite would be more suitable.

Snapey's avatar

@tecreasey

Passport is only for Laravel authenticating client applications. Not for authenticating users.

I would approach it differently. I would overwrite the login method of the AuthenticatesUsers trait within the LoginController. Get the credentials from the user, find them in the database then test supplied credentials against the third party service then manually authenticate the user.

https://laravel.com/docs/5.8/authentication#authenticating-users

Look under Authenticate A User By ID

Note with this approach, your user MUST have a record in the User model

Please or to participate in this conversation.