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
*
*/
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.
*
use BookStack\Exceptions\UserRegistrationException;
use Exception;
use Lcobucci\JWT\Token;
+use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use OpenIDConnectClient\AccessToken;
use OpenIDConnectClient\OpenIDConnectProvider;
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
* return the matching, or new if registration active, user matched to
}
/**
- * Load the underlying Onelogin SAML2 toolkit.
+ * Load the underlying OpenID Connect Provider.
* @throws Error
* @throws Exception
*/
}
/**
- * 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
{
}
auth()->login($user);
+ session()->put('openid_token', json_encode($accessToken));
return $user;
}
}