|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
namespace authkit2\Observers;
|
|
|
|
|
|
|
|
use authkit2\Authkit2;
|
|
|
|
use authkit2\Models\Token;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Watch for user models being loaded or saved and handle installing an
|
|
|
|
* `authkit` object on them to allow the main application to easily interact
|
|
|
|
* with other services as the user or fetch data from the OIDC provider.
|
|
|
|
*/
|
|
|
|
class UserObserver
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* When a user model is saved we have to remove the authkit property from it
|
|
|
|
* to avoid Eloquent or another ORM from trying to save it. When we do so,
|
|
|
|
* we cache it here so we can restore it when the save is complete.
|
|
|
|
*
|
|
|
|
* @var array<mixed,string>
|
|
|
|
*/
|
|
|
|
protected static $token_cache = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Run in response to a user model being loaded, locating their token and
|
|
|
|
* creating a client to place on the model.
|
|
|
|
*
|
|
|
|
* @param mixed $user
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function retrieved($user): void
|
|
|
|
{
|
|
|
|
// Find the token + refresh token for the user
|
|
|
|
$token = Token::where('user_id', $user->{$user->getAuthIdentifierName()})->first();
|
|
|
|
|
|
|
|
// Create a token object
|
|
|
|
$user->authkit = Authkit2::get_token($token->access_token, $token->refresh_token);
|
|
|
|
|
|
|
|
// Set a refresh callback on the token -- when it's been refreshed,
|
|
|
|
// save the new tokens.
|
|
|
|
$user->authkit->setRefreshCallback(
|
|
|
|
/**
|
|
|
|
* When a token has been refreshed, save the updated values
|
|
|
|
* to the token model.
|
|
|
|
* @param \authkit2\Oidc\Token $oidc_token
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
static function(\authkit2\Oidc\Token $oidc_token) use ($token): void {
|
|
|
|
$token->access_token = $oidc_token->getAccessToken();
|
|
|
|
$token->refresh_token = $oidc_token->getRefreshToken();
|
|
|
|
$token->save();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Before we save a user model, remove the token/client so the ORM doesn't
|
|
|
|
* try and write those out.
|
|
|
|
*
|
|
|
|
* @param mixed $user
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function saving($user): void
|
|
|
|
{
|
|
|
|
if (isset($user->authkit))
|
|
|
|
{
|
|
|
|
static::$token_cache[$user->{$user->getAuthIdentifierName()}] = $user->authkit;
|
|
|
|
}
|
|
|
|
unset($user->authkit);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* After a user model is saved, restore the client and token.
|
|
|
|
*
|
|
|
|
* @param mixed $user
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function saved($user): void
|
|
|
|
{
|
|
|
|
$user_id = $user->{$user->getAuthIdentifierName()};
|
|
|
|
if (isset(static::$token_cache[$user_id]))
|
|
|
|
{
|
|
|
|
$user->authkit = static::$token_cache[$user_id];
|
|
|
|
unset(static::$token_cache[$user_id]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|