User authentication user base in response to an API call

Description:

I am using Laravel for a heap of a project. Implementing user authentication is easy in Laravel. Now the structure I'm dealing with is a little different - I don't have a database table or users locally. I have to make an API call to request what I need.


I tried

 public function postSignIn(){ $username = strtolower(Input::get('username')); $password_api = VSE::user('password',$username); // abc <----- $password = Input::get('password'); // abc <----- if ( $password == $password_api ) { //Log user in $auth = Auth::attempt(); // Stuck here <---- } if ($auth) { return Redirect::to('/dashboard')->with('success', 'Hi '. $username .' ! You have been successfully logged in.'); } else { return Redirect::to('/')->with('error', 'Username/Password Wrong')->withInput(Request::except('password'))->with('username', $username); } } 

Update

I connect to the API using a simple shell_exec in the VSE class

 public static function user($attr, $username) { $data = shell_exec('curl '.env('API_HOST').'vse/accounts'); $raw = json_decode($data,true); $array = $raw['data']; return $array[$attr]; } 

It is a pity that I can not show it to you here, but it is located on a virtual machine in my local machine, so please stay with me here. In principle, It

Run

curl http://172.16.67.137:1234/vse/accounts <--- updated

Answer

 Object data:Array[2] 0:Object DBA:"" account_id:111 account_type:"admin" address1:"111 Park Ave" address2:"Floor 4" address3:"Suite 4011" city:"New York" customer_type:2 display_name:"BobJ" email_address:" bob@xyzcorp.com " first_name:"Bob" last_name:"Jones" last_updated_utc_in_secs:200200300 middle_names:"X." name_prefix:"Mr" name_suffix:"Jr." nation_code:"USA" non_person_name:false password:"abc" phone1:"212-555-1212" phone2:"" phone3:"" postal_code:"10022" state:"NY" time_zone_offset_from_utc:-5 1:Object DBA:"" account_id:112 account_type:"mbn" address1:"112 Park Ave" address2:"Floor 3" address3:"Suite 3011" city:"New York" customer_type:2 display_name:"TomS" email_address:" tom@xyzcorp.com " first_name:"Tom" last_name:"Smith" last_updated_utc_in_secs:200200300 middle_names:"Z." name_prefix:"Mr" name_suffix:"Sr." nation_code:"USA" non_person_name:false password:"abd" phone1:"212-555-2323" phone2:"" phone3:"" postal_code:"10022" state:"NY" time_zone_offset_from_utc:-5 message:"Success" status:200 

As you can see, the password for Bob is abc , and for Tom is abd

+6
source share
1 answer

Following the instructions below, you can configure your own authentication driver, which handles fetching and validating user credentials using an API call:

1. Create your own custom provider in app/Auth/ApiUserProvider.php with the following contents:

 namespace App\Auth; use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Contracts\Auth\Authenticatable as UserContract; class ApiUserProvider implements UserProvider { /** * Retrieve a user by the given credentials. * * @param array $credentials * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveByCredentials(array $credentials) { $user = $this->getUserByUsername($credentials['username']); return $this->getApiUser($user); } /** * Retrieve a user by their unique identifier. * * @param mixed $identifier * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveById($identifier) { $user = $this->getUserById($identifier); return $this->getApiUser($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 $user->getAuthPassword() == $credentials['password']; } /** * Get the api user. * * @param mixed $user * @return \App\Auth\ApiUser|null */ protected function getApiUser($user) { if ($user !== null) { return new ApiUser($user); } } /** * Get the use details from your API. * * @param string $username * @return array|null */ protected function getUsers() { $ch = curl_init(); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_URL, env('API_HOST') . 'vse/accounts'); $response = curl_exec($ch); $response = json_decode($response, true); curl_close($ch); return $response['data']; } protected function getUserById($id) { $user = []; foreach ($this->getUsers() as $item) { if ($item['account_id'] == $id) { $user = $item; break; } } return $user ?: null; } protected function getUserByUsername($username) { $user = []; foreach ($this->getUsers() as $item) { if ($item['email_address'] == $username) { $user = $item; break; } } return $user ?: null; } // The methods below need to be defined because of the Authenticatable contract // but need no implementation for 'Auth::attempt' to work and can be implemented // if you need their functionality public function retrieveByToken($identifier, $token) { } public function updateRememberToken(UserContract $user, $token) { } } 

2. Also create a user class that extends the default GenericUser offered by the authentication system in app/Auth/ApiUser.php , with the following contents:

 namespace App\Auth; use Illuminate\Auth\GenericUser; use Illuminate\Contracts\Auth\Authenticatable as UserContract; class ApiUser extends GenericUser implements UserContract { public function getAuthIdentifier() { return $this->attributes['account_id']; } } 

3. In your app/Providers/AuthServiceProvider.php file upload method, register a new driver provider:

 public function boot(GateContract $gate) { $this->registerPolicies($gate); // The code below sets up the 'api' driver $this->app['auth']->extend('api', function() { return new \App\Auth\ApiUserProvider(); }); } 

4. Finally, in your config/auth.php install the driver in your own:

  'driver' => 'api', 

Now you can do the following in your controller action:

 public function postSignIn() { $username = strtolower(Input::get('username')); $password = Input::get('password'); if (Auth::attempt(['username' => $username, 'password' => $password])) { return Redirect::to('/dashboard')->with('success', 'Hi '. $username .'! You have been successfully logged in.'); } else { return Redirect::to('/')->with('error', 'Username/Password Wrong')->withInput(Request::except('password'))->with('username', $username); } } 

Calling Auth::user() to get information about the user after a successful login will return an ApiUser instance containing the attributes extracted from the remote API and will look something like this:

 ApiUser {#143 β–Ό #attributes: array:10 [β–Ό "DBA" => "" "account_id" => 111 "account_type" => "admin" "display_name" => "BobJ" "email_address" => " bob@xyzcorp.com " "first_name" => "Bob" "last_name" => "Jones" "password" => "abc" "message" => "Success" "status" => 200 ] } 

Since you did not post a sample response that you receive when there is no match in the user email API, I configure the condition in the getUserDetails method to determine if there is a match and return null if the response does not contain the data property or if the data property is empty. You can change this condition to suit your needs.


The above code has been tested with a pushable response that returns the data structure posted in your question and works very well.

As a final note: you should seriously consider modifying the API to handle user authentication sooner rather than later (possibly using an Oauth implementation), because with a password sent (and even more disturbing) like plain text) it’s not what you want to put aside.

+7
source

All Articles