2

Been trying to incorporate an external authentication with Laravel's authentication and I don't seem to make it work

Read and tried this article I've found here in stackoverflow, Custom user authentication base on the response of an API call, based on this article I've successfully put the externally authenticated user info to Laravel's Auth System.

My problem is when I do login and use that credential to login to the external API(assuming we fetch successfully the user info from the API) and redirect to another page, Auth::user() don't seem to work and always return null value, it looks like the session is not persisting...

I have also tried creating custom session to put the return data from the API inside the ApiUserProvider to access it later in other routes, but the session becomes missing....

I hope some could help me, Thank you

PS: I'm using Laravel 5.4

config/auth.php

'providers' => [
        'users' => [
            'driver' => 'api',
        ],
    ],

app/Providers/AuthServiceProvider

namespace App\Providers;

use Illuminate\Support\Facades\Auth;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
    ];

    public function boot()
    {
        $this->registerPolicies();

        Auth::provider('api', function ($app, array $config) {
            return new \App\Providers\ApiUserProvider($this->app['hash']);
        });
    }
}

app/Providers/ApiUserProvider.php

namespace App\Providers;

use Illuminate\Support\Facades\Auth;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;

class ApiUserProvider implements UserProvider
{
    protected $hasher;

    public function __construct(HasherContract $hasher)
    {
        $this->hasher = $hasher;
    }

    public function retrieveByCredentials(array $credentials)
    {

        $user = [];

        $post = [
            'username' => $credentials['username'],
            'password' => $credentials['password']
        ];

        $ch = curl_init();

        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, 'https://sample.com/dev/admin/login'); 
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post));
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));

        $response = curl_exec($ch);
        $response = json_decode($response, true);

        curl_close($ch);

        if(isset($response['successful']) && $response['successful']) {
            $response['claims'] =  json_decode(base64_decode(explode('.', $response['token'])[1]));
            $response['password'] =  bcrypt($credentials['password']);
            $response['username'] =  $credentials['username'];
            $response['id'] =  $response['claims']->client_id;
            $response['remember_token'] =  null;

            $user = $response;
            session()->put($response['claims']->client_id, $response); //<--- I attempt to put it in session
        }

        $user = $user ? : null;

        return $this->getApiUser($user);
    }

    public function retrieveById($identifier)
    {
        //$user = $this->getUserById($identifier);
        $user = session()->get($identifier);  //<---- attempted to retrieve the user, but session don't exists if I go in other route 
        return $this->getApiUser($user);
    }

    public function validateCredentials(UserContract $user, array $credentials)
    {
         return $this->hasher->check(
            $credentials['password'], $user->getAuthPassword()
        );
    }

    protected function getApiUser($user)
    {
        if ($user !== null) {
            return new \App\ApiUser((array) $user);
        }
    }

    protected function getUserById($id)
    {
        $user = session()->get($id);
        return $user ?: null;
    }

    public function retrieveByToken($identifier, $token) { }
    public function updateRememberToken(UserContract $user, $token) { }
}

UserController.php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Illuminate\Contracts\Auth\SessionGuard;

class UserController extends Controller
{ 
     protected function attemptLogin(Request $request)
    {
        return $this->guard()->attempt($this->credentials($request));
    }

    protected function guard()
    {
        return Auth::guard();
    }

    protected function credentials(Request $request)
    {
        return $request->only('username', 'password');
    }

    public function login(Request $request)
    {
         if ($this->attemptLogin($request)) {
             dd(auth());
             return "T";
         }

         return "F";
    }

    public function getCurrentUserInfo(Request $request)
    {
        dd(auth()); //<------------- user info no longer exist here
    }
}
Enriqho Juan
  • 31
  • 1
  • 6
  • How are you logging in the user? – Marwelln May 26 '18 at 19:50
  • Hi Maxwelln, Im still using the `Auth::attempt` to login and passed it to the custom service provider(that extends the UserProvider Class) and inside `retrieveByCredentials` method, I perform cURL passing the username and password, if the result of the cURL is successful, It will be authenticated You can refer to the link I've mentioned above.... I did very similar with that one. I am just having trouble regarding persistence of the retrieved data from API Thanks – Enriqho Juan May 27 '18 at 15:02
  • @EnriqhoJuan Any update on this? I think you have to store the data into some storage(database, cache etc) and retrieve from there for subsequent requests. – im_tsm Jan 23 '19 at 13:33

1 Answers1

0

I think this is because I am using the api route when login that is why it is not storing in the info in its session in auth,

I have tried adding startsession middleware in api route and it work but I think it is not right because api route must be stateless.

Enriqho Juan
  • 31
  • 1
  • 6