| 
									
										
										
										
											2021-10-11 02:14:08 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | namespace BookStack\Access\Oidc; | 
					
						
							| 
									
										
										
										
											2021-10-11 02:14:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-12 02:05:16 +08:00
										 |  |  | use League\OAuth2\Client\Grant\AbstractGrant; | 
					
						
							| 
									
										
										
										
											2021-10-11 02:14:08 +08:00
										 |  |  | 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. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-10-13 06:04:28 +08:00
										 |  |  | class OidcOAuthProvider extends AbstractProvider | 
					
						
							| 
									
										
										
										
											2021-10-11 02:14:08 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     use BearerAuthorizationTrait; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-08 21:16:09 +08:00
										 |  |  |     protected string $authorizationEndpoint; | 
					
						
							|  |  |  |     protected string $tokenEndpoint; | 
					
						
							| 
									
										
										
										
											2021-10-11 02:14:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-02 23:56:56 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2022-08-30 00:46:41 +08:00
										 |  |  |      * Scopes to use for the OIDC authorization call. | 
					
						
							| 
									
										
										
										
											2022-08-02 23:56:56 +08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     protected array $scopes = ['openid', 'profile', 'email']; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-11 02:14:08 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * 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 ''; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-02 23:56:56 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2023-09-08 21:16:09 +08:00
										 |  |  |      * Add another scope to this provider upon the default. | 
					
						
							| 
									
										
										
										
											2022-08-02 23:56:56 +08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public function addScope(string $scope): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->scopes[] = $scope; | 
					
						
							|  |  |  |         $this->scopes = array_unique($this->scopes); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-11 02:14:08 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * 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 | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-08-02 23:56:56 +08:00
										 |  |  |         return $this->scopes; | 
					
						
							| 
									
										
										
										
											2021-10-11 02:14:08 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * 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 | 
					
						
							| 
									
										
										
										
											2021-10-16 23:01:59 +08:00
										 |  |  |      * @param array|string      $data     Parsed response data | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-10-11 02:14:08 +08:00
										 |  |  |      * @throws IdentityProviderException | 
					
						
							| 
									
										
										
										
											2021-10-16 23:01:59 +08:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return void | 
					
						
							| 
									
										
										
										
											2021-10-11 02:14:08 +08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     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. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-10-16 23:01:59 +08:00
										 |  |  |      * @param array       $response | 
					
						
							| 
									
										
										
										
											2021-10-11 02:14:08 +08:00
										 |  |  |      * @param AccessToken $token | 
					
						
							| 
									
										
										
										
											2021-10-16 23:01:59 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-10-11 02:14:08 +08:00
										 |  |  |      * @return ResourceOwnerInterface | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function createResourceOwner(array $response, AccessToken $token) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return new GenericResourceOwner($response, ''); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-12 02:05:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Creates an access token from a response. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * The grant that was used to fetch the response can be used to provide | 
					
						
							|  |  |  |      * additional context. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-10-16 23:01:59 +08:00
										 |  |  |      * @param array         $response | 
					
						
							| 
									
										
										
										
											2021-10-12 02:05:16 +08:00
										 |  |  |      * @param AbstractGrant $grant | 
					
						
							| 
									
										
										
										
											2021-10-16 23:01:59 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-10-13 06:04:28 +08:00
										 |  |  |      * @return OidcAccessToken | 
					
						
							| 
									
										
										
										
											2021-10-12 02:05:16 +08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     protected function createAccessToken(array $response, AbstractGrant $grant) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-10-13 06:04:28 +08:00
										 |  |  |         return new OidcAccessToken($response); | 
					
						
							| 
									
										
										
										
											2021-10-12 02:05:16 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-16 23:01:59 +08:00
										 |  |  | } |