]> BookStack Code Mirror - bookstack/blobdiff - app/Auth/Access/Oidc/OidcService.php
Fixed occurances of altered titles in search results
[bookstack] / app / Auth / Access / Oidc / OidcService.php
index be6a5c3c45d8fc204efe9d0999f99d556937197f..b8e017b4b135c85fd3b7aee9afbce252b0b372c1 100644 (file)
@@ -1,5 +1,8 @@
-<?php namespace BookStack\Auth\Access\Oidc;
+<?php
 
+namespace BookStack\Auth\Access\Oidc;
+
+use function auth;
 use BookStack\Auth\Access\LoginService;
 use BookStack\Auth\Access\RegistrationService;
 use BookStack\Auth\User;
@@ -7,12 +10,12 @@ use BookStack\Exceptions\JsonDebugException;
 use BookStack\Exceptions\OpenIdConnectException;
 use BookStack\Exceptions\StoppedAuthenticationException;
 use BookStack\Exceptions\UserRegistrationException;
+use function config;
 use Exception;
-use GuzzleHttp\Client;
 use Illuminate\Support\Facades\Cache;
+use League\OAuth2\Client\OptionProvider\HttpBasicAuthOptionProvider;
 use Psr\Http\Client\ClientExceptionInterface;
-use function auth;
-use function config;
+use Psr\Http\Client\ClientInterface as HttpClient;
 use function trans;
 use function url;
 
@@ -24,28 +27,30 @@ class OidcService
 {
     protected $registrationService;
     protected $loginService;
-    protected $config;
+    protected $httpClient;
 
     /**
      * OpenIdService constructor.
      */
-    public function __construct(RegistrationService $registrationService, LoginService $loginService)
+    public function __construct(RegistrationService $registrationService, LoginService $loginService, HttpClient $httpClient)
     {
-        $this->config = config('oidc');
         $this->registrationService = $registrationService;
         $this->loginService = $loginService;
+        $this->httpClient = $httpClient;
     }
 
     /**
      * Initiate an authorization flow.
+     *
      * @return array{url: string, state: string}
      */
     public function login(): array
     {
         $settings = $this->getProviderSettings();
         $provider = $this->getProvider($settings);
+
         return [
-            'url' => $provider->getAuthorizationUrl(),
+            'url'   => $provider->getAuthorizationUrl(),
             'state' => $provider->getState(),
         ];
     }
@@ -55,6 +60,7 @@ class OidcService
      * return the matching, or new if registration active, user matched to
      * the authorization server.
      * Returns null if not authenticated.
+     *
      * @throws Exception
      * @throws ClientExceptionInterface
      */
@@ -77,23 +83,24 @@ class OidcService
      */
     protected function getProviderSettings(): OidcProviderSettings
     {
+        $config = $this->config();
         $settings = new OidcProviderSettings([
-            'issuer' => $this->config['issuer'],
-            'clientId' => $this->config['client_id'],
-            'clientSecret' => $this->config['client_secret'],
-            'redirectUri' => url('/oidc/redirect'),
-            'authorizationEndpoint' => $this->config['authorization_endpoint'],
-            'tokenEndpoint' => $this->config['token_endpoint'],
+            'issuer'                => $config['issuer'],
+            'clientId'              => $config['client_id'],
+            'clientSecret'          => $config['client_secret'],
+            'redirectUri'           => url('/oidc/callback'),
+            'authorizationEndpoint' => $config['authorization_endpoint'],
+            'tokenEndpoint'         => $config['token_endpoint'],
         ]);
 
         // Use keys if configured
-        if (!empty($this->config['jwt_public_key'])) {
-            $settings->keys = [$this->config['jwt_public_key']];
+        if (!empty($config['jwt_public_key'])) {
+            $settings->keys = [$config['jwt_public_key']];
         }
 
         // Run discovery
-        if ($this->config['discover'] ?? false) {
-            $settings->discoverFromIssuer(new Client(['timeout' => 3]), Cache::store(null), 15);
+        if ($config['discover'] ?? false) {
+            $settings->discoverFromIssuer($this->httpClient, Cache::store(null), 15);
         }
 
         $settings->validate();
@@ -106,15 +113,18 @@ class OidcService
      */
     protected function getProvider(OidcProviderSettings $settings): OidcOAuthProvider
     {
-        return new OidcOAuthProvider($settings->arrayForProvider());
+        return new OidcOAuthProvider($settings->arrayForProvider(), [
+            'httpClient'     => $this->httpClient,
+            'optionProvider' => new HttpBasicAuthOptionProvider(),
+        ]);
     }
 
     /**
-     * Calculate the display name
+     * Calculate the display name.
      */
     protected function getUserDisplayName(OidcIdToken $token, string $defaultValue): string
     {
-        $displayNameAttr = $this->config['display_name_claims'];
+        $displayNameAttr = $this->config()['display_name_claims'];
 
         $displayName = [];
         foreach ($displayNameAttr as $dnAttr) {
@@ -133,21 +143,24 @@ class OidcService
 
     /**
      * Extract the details of a user from an ID token.
+     *
      * @return array{name: string, email: string, external_id: string}
      */
     protected function getUserDetails(OidcIdToken $token): array
     {
         $id = $token->getClaim('sub');
+
         return [
             'external_id' => $id,
-            'email' => $token->getClaim('email'),
-            'name' => $this->getUserDisplayName($token, $id),
+            'email'       => $token->getClaim('email'),
+            'name'        => $this->getUserDisplayName($token, $id),
         ];
     }
 
     /**
      * Processes a received access token for a user. Login the user when
      * they exist, optionally registering them automatically.
+     *
      * @throws OpenIdConnectException
      * @throws JsonDebugException
      * @throws UserRegistrationException
@@ -162,7 +175,7 @@ class OidcService
             $settings->keys,
         );
 
-        if ($this->config['dump_user_details']) {
+        if ($this->config()['dump_user_details']) {
             throw new JsonDebugException($idToken->getAllClaims());
         }
 
@@ -175,7 +188,7 @@ class OidcService
         $userDetails = $this->getUserDetails($idToken);
         $isLoggedIn = auth()->check();
 
-        if ($userDetails['email'] === null) {
+        if (empty($userDetails['email'])) {
             throw new OpenIdConnectException(trans('errors.oidc_no_email_address'));
         }
 
@@ -184,7 +197,9 @@ class OidcService
         }
 
         $user = $this->registrationService->findOrRegister(
-            $userDetails['name'], $userDetails['email'], $userDetails['external_id']
+            $userDetails['name'],
+            $userDetails['email'],
+            $userDetails['external_id']
         );
 
         if ($user === null) {
@@ -192,6 +207,15 @@ class OidcService
         }
 
         $this->loginService->login($user, 'oidc');
+
         return $user;
     }
+
+    /**
+     * Get the OIDC config from the application.
+     */
+    protected function config(): array
+    {
+        return config('oidc');
+    }
 }