Last active
January 23, 2024 15:11
-
-
Save GuillermoFarias/58b9d27aa06de76de974089708203192 to your computer and use it in GitHub Desktop.
Laravel 8 Custom Guard, login de usuario con API externa
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Illuminate\Http\Request; | |
use Illuminate\Support\Facades\Route; | |
/* | |
|-------------------------------------------------------------------------- | |
| API Routes | |
|-------------------------------------------------------------------------- | |
| | |
| Here is where you can register API routes for your application. These | |
| routes are loaded by the RouteServiceProvider within a group which | |
| is assigned the "api" middleware group. Enjoy building your API! | |
| | |
*/ | |
Route::middleware('auth:sso')->group(function () { | |
Route::get('/me', function (Request $request) { | |
return $request->user(); | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
'guards' => [ | |
'sso' => [ | |
'driver' => 'sso' | |
] | |
], |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Providers; | |
use App\Providers\Sso\TokenGuard; | |
use App\Providers\Sso\TokenUserProvider; | |
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; | |
use Illuminate\Support\Facades\Auth; | |
class AuthServiceProvider extends ServiceProvider | |
{ | |
/** | |
* The policy mappings for the application. | |
* | |
* @var array | |
*/ | |
protected $policies = [ | |
// 'App\Models\Model' => 'App\Policies\ModelPolicy', | |
]; | |
/** | |
* Register any authentication / authorization services. | |
* | |
* @return void | |
*/ | |
public function boot() | |
{ | |
$this->registerPolicies(); | |
Auth::extend('sso', function ($app) { | |
$request = $app->make('request'); | |
$userProvider = new TokenUserProvider($request->header('email'), $request->header('token')); | |
return new TokenGuard($userProvider, $request); | |
}); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Providers\Sso; | |
use Illuminate\Auth\GuardHelpers; | |
use Illuminate\Contracts\Auth\Authenticatable; | |
use Illuminate\Contracts\Auth\Guard; | |
use Illuminate\Contracts\Auth\UserProvider; | |
use Illuminate\Http\Request; | |
class TokenGuard implements Guard | |
{ | |
use GuardHelpers; | |
/** | |
* @var string | |
*/ | |
private const EMAIL = 'email'; | |
/** | |
* @var string | |
*/ | |
private const TOKEN = 'token'; | |
/** | |
* The request instance. | |
* | |
* @var \Illuminate\Http\Request | |
*/ | |
protected $request; | |
/** | |
* Create a new authentication guard. | |
* | |
* @param \Illuminate\Contracts\Auth\UserProvider $provider | |
* @param \Illuminate\Http\Request $request | |
* @return void | |
*/ | |
public function __construct( | |
UserProvider $provider, | |
Request $request | |
) { | |
$this->request = $request; | |
$this->provider = $provider; | |
} | |
/** | |
* Get the currently authenticated user. | |
* | |
* @return \Illuminate\Contracts\Auth\Authenticatable|null | |
*/ | |
public function user(): ?Authenticatable | |
{ | |
if (!is_null($this->user)) { | |
return $this->user; | |
} | |
$user = null; | |
if (!empty($this->request->header(self::TOKEN))) { | |
$credentials = [ | |
self::EMAIL => $this->request->header(self::EMAIL), | |
self::TOKEN => $this->request->header(self::TOKEN), | |
]; | |
$user = $this->provider->retrieveByCredentials($credentials); | |
} | |
return $this->user = $user; | |
} | |
/** | |
* Validate a user's credentials. | |
* | |
* @param array $credentials | |
* @return bool | |
*/ | |
public function validate(array $credentials = []): bool | |
{ | |
if (empty($credentials[self::TOKEN])) { | |
return false; | |
} | |
$credentials = [ | |
self::EMAIL => $credentials[self::EMAIL], | |
self::TOKEN => $credentials[self::TOKEN], | |
]; | |
if ($this->provider->retrieveByCredentials($credentials)) { | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Set the current request instance. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @return $this | |
*/ | |
public function setRequest(Request $request) | |
{ | |
$this->request = $request; | |
return $this; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Providers\Sso; | |
use App\Models\User; | |
use Illuminate\Contracts\Auth\Authenticatable as UserContract; | |
use Illuminate\Contracts\Auth\Authenticatable; | |
use Illuminate\Contracts\Auth\UserProvider; | |
use Illuminate\Support\Facades\Http; | |
class TokenUserProvider implements UserProvider | |
{ | |
/** | |
* @var string | |
*/ | |
private $host; | |
/** | |
* @var string | |
*/ | |
private const EMAIL = 'email'; | |
/** | |
* @var string | |
*/ | |
private const TOKEN = 'token'; | |
/** | |
* Create a new token sso user provider. | |
* | |
* @param string $email | |
* @param string $token | |
* @return void | |
*/ | |
public function __construct() | |
{ | |
$this->host = env('SSO_HOST'); | |
} | |
/** | |
* Retrieve a user by their unique identifier. | |
* | |
* @param mixed $identifier | |
* @return \Illuminate\Contracts\Auth\Authenticatable|null | |
*/ | |
public function retrieveById($identifier): ?Authenticatable | |
{ | |
return null; | |
} | |
/** | |
* Retrieve a user by their unique identifier and "remember me" token. | |
* | |
* @param mixed $identifier | |
* @param string $token | |
* @return \Illuminate\Contracts\Auth\Authenticatable|null | |
*/ | |
public function retrieveByToken($email, $token): ?Authenticatable | |
{ | |
return $this->getUser($email, $token); | |
} | |
/** | |
* Update the "remember me" token for the given user in storage. | |
* | |
* @param \Illuminate\Contracts\Auth\Authenticatable $user | |
* @param string $token | |
* @return void | |
*/ | |
public function updateRememberToken(UserContract $user, $token) | |
{ | |
} | |
/** | |
* Retrieve a user by the given credentials. | |
* | |
* @param array $credentials | |
* @return \Illuminate\Contracts\Auth\Authenticatable|null | |
*/ | |
public function retrieveByCredentials(array $credentials = []): ?Authenticatable | |
{ | |
if (!array_key_exists(self::EMAIL, $credentials) && !array_key_exists(self::TOKEN, $credentials)) { | |
return null; | |
} | |
if (!$this->validate($credentials[self::EMAIL], $credentials[self::TOKEN])) { | |
return null; | |
} | |
return $this->getUser($credentials[self::EMAIL], $credentials[self::TOKEN]); | |
} | |
/** | |
* 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 = []): bool | |
{ | |
return $this->validate($credentials[self::EMAIL], $credentials[self::TOKEN]); | |
} | |
/** | |
* instance user from sso data user | |
* | |
* @param string $email | |
* @param string $token | |
* @return \Illuminate\Contracts\Auth\Authenticatable|null | |
*/ | |
private function getUser(?string $email, ?string $token): ?Authenticatable | |
{ | |
$response = Http::withHeaders([ | |
self::EMAIL => $email, | |
self::TOKEN => $token, | |
])->get($this->host . '/api/whois'); | |
if ($response->status() !== 200) { | |
return null; | |
} | |
$ssoUserInfo = json_decode($response->body()); | |
if (!$ssoUserInfo) { | |
return null; | |
} | |
return new User((array) $ssoUserInfo); | |
} | |
/** | |
* validate if email and token are valid | |
* | |
* @param string $email | |
* @param string $token | |
* @return bool | |
*/ | |
private function validate(?string $email, ?string $token): bool | |
{ | |
$response = Http::withHeaders([ | |
self::EMAIL => $email, | |
self::TOKEN => $token, | |
])->get($this->host . '/api/validate'); | |
return $response->status() == 200; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment