]> BookStack Code Mirror - bookstack/commitdiff
Started on a custom oidc oauth provider
authorDan Brown <redacted>
Sun, 10 Oct 2021 18:14:08 +0000 (19:14 +0100)
committerDan Brown <redacted>
Sun, 10 Oct 2021 18:14:08 +0000 (19:14 +0100)
app/Auth/Access/OpenIdConnectOAuthProvider.php [new file with mode: 0644]
app/Auth/Access/OpenIdConnectService.php

diff --git a/app/Auth/Access/OpenIdConnectOAuthProvider.php b/app/Auth/Access/OpenIdConnectOAuthProvider.php
new file mode 100644 (file)
index 0000000..60ae2aa
--- /dev/null
@@ -0,0 +1,109 @@
+<?php
+
+namespace BookStack\Auth\Access;
+
+use League\OAuth2\Client\Provider\AbstractProvider;
+use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
+use League\OAuth2\Client\Provider\GenericResourceOwner;
+use League\OAuth2\Client\Provider\ResourceOwnerInterface;
+use League\OAuth2\Client\Token\AccessToken;
+use League\OAuth2\Client\Tool\BearerAuthorizationTrait;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Extended OAuth2Provider for using with OIDC.
+ * Credit to the https://github.com/steverhoades/oauth2-openid-connect-client
+ * project for the idea of extending a League\OAuth2 client for this use-case.
+ */
+class OpenIdConnectOAuthProvider extends AbstractProvider
+{
+    use BearerAuthorizationTrait;
+
+    /**
+     * @var string
+     */
+    protected $authorizationEndpoint;
+
+    /**
+     * @var string
+     */
+    protected $tokenEndpoint;
+
+
+    /**
+     * Returns the base URL for authorizing a client.
+     */
+    public function getBaseAuthorizationUrl(): string
+    {
+        return $this->authorizationEndpoint;
+    }
+
+    /**
+     * Returns the base URL for requesting an access token.
+     */
+    public function getBaseAccessTokenUrl(array $params): string
+    {
+        return $this->tokenEndpoint;
+    }
+
+    /**
+     * Returns the URL for requesting the resource owner's details.
+     */
+    public function getResourceOwnerDetailsUrl(AccessToken $token): string
+    {
+        return '';
+    }
+
+    /**
+     * Returns the default scopes used by this provider.
+     *
+     * This should only be the scopes that are required to request the details
+     * of the resource owner, rather than all the available scopes.
+     */
+    protected function getDefaultScopes(): array
+    {
+        return ['openid', 'profile', 'email'];
+    }
+
+
+    /**
+     * Returns the string that should be used to separate scopes when building
+     * the URL for requesting an access token.
+     */
+    protected function getScopeSeparator(): string
+    {
+        return ' ';
+    }
+
+    /**
+     * Checks a provider response for errors.
+     *
+     * @param ResponseInterface $response
+     * @param array|string $data Parsed response data
+     * @return void
+     * @throws IdentityProviderException
+     */
+    protected function checkResponse(ResponseInterface $response, $data)
+    {
+        if ($response->getStatusCode() >= 400 || isset($data['error'])) {
+            throw new IdentityProviderException(
+                $data['error'] ?? $response->getReasonPhrase(),
+                $response->getStatusCode(),
+                (string) $response->getBody()
+            );
+        }
+    }
+
+    /**
+     * Generates a resource owner object from a successful resource owner
+     * details request.
+     *
+     * @param array $response
+     * @param AccessToken $token
+     * @return ResourceOwnerInterface
+     */
+    protected function createResourceOwner(array $response, AccessToken $token)
+    {
+        return new GenericResourceOwner($response, '');
+    }
+}
\ No newline at end of file
index 2548aee6edf4dafababb07aa8cc086fc03114802..01050b5e5a58f36d20da9ae3d0eefe4be9d7c0b2 100644 (file)
@@ -6,10 +6,8 @@ use BookStack\Exceptions\OpenIdConnectException;
 use BookStack\Exceptions\StoppedAuthenticationException;
 use BookStack\Exceptions\UserRegistrationException;
 use Exception;
-use Lcobucci\JWT\Signer\Rsa\Sha256;
 use Lcobucci\JWT\Token;
-use OpenIDConnectClient\AccessToken;
-use OpenIDConnectClient\OpenIDConnectProvider;
+use League\OAuth2\Client\Token\AccessToken;
 
 /**
  * Class OpenIdConnectService
@@ -66,27 +64,18 @@ class OpenIdConnectService
     /**
      * Load the underlying OpenID Connect Provider.
      */
-    protected function getProvider(): OpenIDConnectProvider
+    protected function getProvider(): OpenIdConnectOAuthProvider
     {
         // Setup settings
         $settings = [
             'clientId' => $this->config['client_id'],
             'clientSecret' => $this->config['client_secret'],
-            'idTokenIssuer' => $this->config['issuer'],
             'redirectUri' => url('/oidc/redirect'),
-            'urlAuthorize' => $this->config['authorization_endpoint'],
-            'urlAccessToken' => $this->config['token_endpoint'],
-            'urlResourceOwnerDetails' => null,
-            'publicKey' => $this->config['jwt_public_key'],
-            'scopes' => 'profile email',
+            'authorizationEndpoint' => $this->config['authorization_endpoint'],
+            'tokenEndpoint' => $this->config['token_endpoint'],
         ];
 
-        // Setup services
-        $services = [
-            'signer' => new Sha256(),
-        ];
-
-        return new OpenIDConnectProvider($settings, $services);
+        return new OpenIdConnectOAuthProvider($settings);
     }
 
     /**
@@ -135,6 +124,16 @@ class OpenIdConnectService
      */
     protected function processAccessTokenCallback(AccessToken $accessToken): User
     {
+        dd($accessToken->getValues());
+        // TODO - Create a class to manage token parsing and validation on this
+        // Using the config params:
+        // $this->config['jwt_public_key']
+        // $this->config['issuer']
+        //
+        // Ensure ID token validation is done:
+        // https://openid.net/specs/openid-connect-basic-1_0.html#IDTokenValidation
+        // To full affect and tested
+
         $userDetails = $this->getUserDetails($accessToken->getIdToken());
         $isLoggedIn = auth()->check();