]> BookStack Code Mirror - bookstack/commitdiff
Token expiration and refreshing using the refresh_token flow
authorJasper Weyne <redacted>
Tue, 7 Jul 2020 00:26:00 +0000 (02:26 +0200)
committerJasper Weyne <redacted>
Tue, 7 Jul 2020 00:26:00 +0000 (02:26 +0200)
app/Auth/Access/Guards/OpenIdSessionGuard.php
app/Auth/Access/OpenIdService.php

index 0dfbb67a3f5328a6cc9d9d6b71a94617cbe21984..6344644930e478255dd4c3ddea5ffc69fbdf1e1c 100644 (file)
@@ -2,6 +2,11 @@
 
 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
  *
@@ -14,6 +19,41 @@ namespace BookStack\Auth\Access\Guards;
  */
 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.
      *
index 084adfb13aa4e1cb733479b0a9a06c66bca26ffd..377925d61cb7805d0a966c57f435eefb410101fd 100644 (file)
@@ -6,6 +6,7 @@ use BookStack\Exceptions\OpenIdException;
 use BookStack\Exceptions\UserRegistrationException;
 use Exception;
 use Lcobucci\JWT\Token;
+use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
 use OpenIDConnectClient\AccessToken;
 use OpenIDConnectClient\OpenIDConnectProvider;
 
@@ -53,6 +54,46 @@ class OpenIdService extends ExternalAuthService
         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
@@ -86,7 +127,7 @@ class OpenIdService extends ExternalAuthService
     }
 
     /**
-     * Load the underlying Onelogin SAML2 toolkit.
+     * Load the underlying OpenID Connect Provider.
      * @throws Error
      * @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
     {
@@ -202,6 +243,7 @@ class OpenIdService extends ExternalAuthService
         }
 
         auth()->login($user);
+        session()->put('openid_token', json_encode($accessToken));
         return $user;
     }
 }