Started on a custom oidc oauth provider

This commit is contained in:
Dan Brown 2021-10-10 19:14:08 +01:00
parent 41438adbd1
commit 8ce696dff6
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
2 changed files with 124 additions and 16 deletions

View File

@ -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, '');
}
}

View 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();