3 namespace BookStack\Auth\Access\Oidc;
5 use League\OAuth2\Client\Grant\AbstractGrant;
6 use League\OAuth2\Client\Provider\AbstractProvider;
7 use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
8 use League\OAuth2\Client\Provider\GenericResourceOwner;
9 use League\OAuth2\Client\Provider\ResourceOwnerInterface;
10 use League\OAuth2\Client\Token\AccessToken;
11 use League\OAuth2\Client\Tool\BearerAuthorizationTrait;
12 use Psr\Http\Message\ResponseInterface;
15 * Extended OAuth2Provider for using with OIDC.
16 * Credit to the https://github.com/steverhoades/oauth2-openid-connect-client
17 * project for the idea of extending a League\OAuth2 client for this use-case.
19 class OidcOAuthProvider extends AbstractProvider
21 use BearerAuthorizationTrait;
26 protected $authorizationEndpoint;
31 protected $tokenEndpoint;
35 * Returns the base URL for authorizing a client.
37 public function getBaseAuthorizationUrl(): string
39 return $this->authorizationEndpoint;
43 * Returns the base URL for requesting an access token.
45 public function getBaseAccessTokenUrl(array $params): string
47 return $this->tokenEndpoint;
51 * Returns the URL for requesting the resource owner's details.
53 public function getResourceOwnerDetailsUrl(AccessToken $token): string
59 * Returns the default scopes used by this provider.
61 * This should only be the scopes that are required to request the details
62 * of the resource owner, rather than all the available scopes.
64 protected function getDefaultScopes(): array
66 return ['openid', 'profile', 'email'];
71 * Returns the string that should be used to separate scopes when building
72 * the URL for requesting an access token.
74 protected function getScopeSeparator(): string
80 * Checks a provider response for errors.
82 * @param ResponseInterface $response
83 * @param array|string $data Parsed response data
85 * @throws IdentityProviderException
87 protected function checkResponse(ResponseInterface $response, $data)
89 if ($response->getStatusCode() >= 400 || isset($data['error'])) {
90 throw new IdentityProviderException(
91 $data['error'] ?? $response->getReasonPhrase(),
92 $response->getStatusCode(),
93 (string) $response->getBody()
99 * Generates a resource owner object from a successful resource owner
102 * @param array $response
103 * @param AccessToken $token
104 * @return ResourceOwnerInterface
106 protected function createResourceOwner(array $response, AccessToken $token)
108 return new GenericResourceOwner($response, '');
112 * Creates an access token from a response.
114 * The grant that was used to fetch the response can be used to provide
115 * additional context.
117 * @param array $response
118 * @param AbstractGrant $grant
119 * @return OidcAccessToken
121 protected function createAccessToken(array $response, AbstractGrant $grant)
123 return new OidcAccessToken($response);