mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-06-24 22:51:23 +08:00
Token expiration and refreshing using the refresh_token flow
This commit is contained in:
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
namespace BookStack\Auth\Access\Guards;
|
namespace BookStack\Auth\Access\Guards;
|
||||||
|
|
||||||
|
use BookStack\Auth\Access\OpenIdService;
|
||||||
|
use BookStack\Auth\Access\RegistrationService;
|
||||||
|
use Illuminate\Contracts\Auth\UserProvider;
|
||||||
|
use Illuminate\Contracts\Session\Session;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OpenId Session Guard
|
* OpenId Session Guard
|
||||||
*
|
*
|
||||||
@ -14,6 +19,41 @@ namespace BookStack\Auth\Access\Guards;
|
|||||||
*/
|
*/
|
||||||
class OpenIdSessionGuard extends ExternalBaseSessionGuard
|
class OpenIdSessionGuard extends ExternalBaseSessionGuard
|
||||||
{
|
{
|
||||||
|
|
||||||
|
protected $openidService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenIdSessionGuard constructor.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
$name,
|
||||||
|
UserProvider $provider,
|
||||||
|
Session $session,
|
||||||
|
OpenIdService $openidService,
|
||||||
|
RegistrationService $registrationService
|
||||||
|
) {
|
||||||
|
$this->openidService = $openidService;
|
||||||
|
parent::__construct($name, $provider, $session, $registrationService);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the currently authenticated user.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\Auth\Authenticatable|null
|
||||||
|
*/
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
// retrieve the current user
|
||||||
|
$user = parent::user();
|
||||||
|
|
||||||
|
// refresh the current user
|
||||||
|
if ($user && !$this->openidService->refresh()) {
|
||||||
|
$this->user = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->user;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate a user's credentials.
|
* Validate a user's credentials.
|
||||||
*
|
*
|
||||||
|
@ -6,6 +6,7 @@ use BookStack\Exceptions\OpenIdException;
|
|||||||
use BookStack\Exceptions\UserRegistrationException;
|
use BookStack\Exceptions\UserRegistrationException;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Lcobucci\JWT\Token;
|
use Lcobucci\JWT\Token;
|
||||||
|
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
|
||||||
use OpenIDConnectClient\AccessToken;
|
use OpenIDConnectClient\AccessToken;
|
||||||
use OpenIDConnectClient\OpenIDConnectProvider;
|
use OpenIDConnectClient\OpenIDConnectProvider;
|
||||||
|
|
||||||
@ -53,6 +54,46 @@ class OpenIdService extends ExternalAuthService
|
|||||||
return ['url' => $url, 'id' => $id];
|
return ['url' => $url, 'id' => $id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the currently logged in user.
|
||||||
|
* @throws Error
|
||||||
|
*/
|
||||||
|
public function refresh(): bool
|
||||||
|
{
|
||||||
|
// Retrieve access token for current session
|
||||||
|
$json = session()->get('openid_token');
|
||||||
|
$accessToken = new AccessToken(json_decode($json, true));
|
||||||
|
|
||||||
|
// Check whether the access token or ID token is expired
|
||||||
|
if (!$accessToken->getIdToken()->isExpired() && !$accessToken->hasExpired()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no refresh token available, logout
|
||||||
|
if ($accessToken->getRefreshToken() === null) {
|
||||||
|
$this->actionLogout();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID token or access token is expired, we refresh it using the refresh token
|
||||||
|
try {
|
||||||
|
$provider = $this->getProvider();
|
||||||
|
|
||||||
|
$accessToken = $provider->getAccessToken('refresh_token', [
|
||||||
|
'refresh_token' => $accessToken->getRefreshToken(),
|
||||||
|
]);
|
||||||
|
} catch (IdentityProviderException $e) {
|
||||||
|
// Refreshing failed, logout
|
||||||
|
$this->actionLogout();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A valid token was obtained, we update the access token
|
||||||
|
session()->put('openid_token', json_encode($accessToken));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the Authorization response from the authorization server and
|
* Process the Authorization response from the authorization server and
|
||||||
* return the matching, or new if registration active, user matched to
|
* return the matching, or new if registration active, user matched to
|
||||||
@ -86,7 +127,7 @@ class OpenIdService extends ExternalAuthService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the underlying Onelogin SAML2 toolkit.
|
* Load the underlying OpenID Connect Provider.
|
||||||
* @throws Error
|
* @throws Error
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@ -155,7 +196,7 @@ class OpenIdService extends ExternalAuthService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the details of a user from a SAML response.
|
* Extract the details of a user from an ID token.
|
||||||
*/
|
*/
|
||||||
protected function getUserDetails(Token $token): array
|
protected function getUserDetails(Token $token): array
|
||||||
{
|
{
|
||||||
@ -202,6 +243,7 @@ class OpenIdService extends ExternalAuthService
|
|||||||
}
|
}
|
||||||
|
|
||||||
auth()->login($user);
|
auth()->login($user);
|
||||||
|
session()->put('openid_token', json_encode($accessToken));
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user