From 5550419714e93a02dde78705d3ed84ad9a7b9cec Mon Sep 17 00:00:00 2001 From: Brian Engert Date: Mon, 4 Nov 2024 14:25:29 -0600 Subject: [PATCH] feat: add a configuration option to support clients that don't require consent for internal applications you might want to skip prompting for consent. With this change you can set your clients array like the array below to not prompt users for consent. return array( 'client_id_random_string' => array( 'name' => 'The name of the Client', 'secret' => 'a secret string', 'redirect_uri' => 'https://example.com/redirect.uri', 'grant_types' => array( 'authorization_code' ), 'requires_consent' => false, ), --- src/Http/Handlers/AuthenticateHandler.php | 34 +++++++---------------- src/Http/Handlers/AuthorizeHandler.php | 10 +++++-- src/OpenIDConnectServer.php | 9 +++--- src/Storage/ClientCredentialsStorage.php | 28 +++++++++++++++++++ 4 files changed, 51 insertions(+), 30 deletions(-) diff --git a/src/Http/Handlers/AuthenticateHandler.php b/src/Http/Handlers/AuthenticateHandler.php index 8a069fd..532acb4 100644 --- a/src/Http/Handlers/AuthenticateHandler.php +++ b/src/Http/Handlers/AuthenticateHandler.php @@ -6,13 +6,14 @@ use OAuth2\Response; use OpenIDConnectServer\Http\RequestHandler; use OpenIDConnectServer\Http\Router; +use OpenIDConnectServer\Storage\ClientCredentialsStorage; use OpenIDConnectServer\Storage\ConsentStorage; class AuthenticateHandler extends RequestHandler { private ConsentStorage $consent_storage; - private array $clients; + private ClientCredentialsStorage $clients; - public function __construct( ConsentStorage $consent_storage, array $clients ) { + public function __construct( ConsentStorage $consent_storage, ClientCredentialsStorage $clients ) { $this->consent_storage = $consent_storage; $this->clients = $clients; } @@ -22,15 +23,19 @@ public function handle( Request $request, Response $response ): Response { auth_redirect(); } - $client_name = $this->get_client_name( $request ); + $client_id = $request->query( 'client_id' ); + + $client_name = $this->clients->getClientName( $client_id ); if ( empty( $client_name ) ) { $response->setStatusCode( 404 ); return $response; } - $client_id = $request->query( 'client_id' ); - if ( ! $this->consent_storage->needs_consent( get_current_user_id(), $client_id ) ) { + if ( + ! $this->clients->clientRequiresConsent( $client_id ) + || ! $this->consent_storage->needs_consent( get_current_user_id(), $client_id ) + ) { $this->redirect( $request ); // TODO: return response instead of exiting. exit; @@ -155,25 +160,6 @@ private function redirect( Request $request ) { ); } - /** - * TODO: Remove this function in favour of ClientCredentialsStorage? - */ - private function get_client_name( Request $request ): string { - $client_id = $request->query( 'client_id' ); - - if ( ! isset( $this->clients[ $client_id ] ) ) { - return ''; - } - - $client = $this->clients[ $client_id ]; - - if ( empty( $client['name'] ) ) { - return ''; - } - - return $client['name']; - } - private function get_cancel_url( Request $request ) { return add_query_arg( array( diff --git a/src/Http/Handlers/AuthorizeHandler.php b/src/Http/Handlers/AuthorizeHandler.php index 96371ce..322160f 100644 --- a/src/Http/Handlers/AuthorizeHandler.php +++ b/src/Http/Handlers/AuthorizeHandler.php @@ -8,6 +8,7 @@ use OAuth2\Response; use OAuth2\Server as OAuth2Server; use OpenIDConnectServer\Http\RequestHandler; +use OpenIDConnectServer\Storage\ClientCredentialsStorage; use OpenIDConnectServer\Storage\ConsentStorage; const OIDC_DEFAULT_MINIMAL_CAPABILITY = 'edit_posts'; @@ -15,10 +16,12 @@ class AuthorizeHandler extends RequestHandler { private OAuth2Server $server; private ConsentStorage $consent_storage; + private ClientCredentialsStorage $clients; - public function __construct( OAuth2Server $server, ConsentStorage $consent_storage ) { + public function __construct( OAuth2Server $server, ConsentStorage $consent_storage , ClientCredentialsStorage $clients) { $this->server = $server; $this->consent_storage = $consent_storage; + $this->clients = $clients; } public function handle( Request $request, Response $response ): Response { @@ -44,7 +47,10 @@ public function handle( Request $request, Response $response ): Response { $user = wp_get_current_user(); $client_id = $request->query( 'client_id', $request->request( 'client_id' ) ); - if ( $this->consent_storage->needs_consent( $user->ID, $client_id ) ) { + if ( + $this->clients->clientRequiresConsent( $client_id ) + && $this->consent_storage->needs_consent( $user->ID, $client_id ) + ) { if ( ! isset( $_POST['authorize'] ) || __( 'Authorize', 'openid-connect-server' ) !== $_POST['authorize'] ) { $response->setError( 403, 'user_authorization_required', 'This application requires your consent.' ); return $response; diff --git a/src/OpenIDConnectServer.php b/src/OpenIDConnectServer.php index 8a6fde3..90460e0 100644 --- a/src/OpenIDConnectServer.php +++ b/src/OpenIDConnectServer.php @@ -20,16 +20,17 @@ class OpenIDConnectServer { private string $public_key; - private array $clients; + private ClientCredentialsStorage $clients; private Router $router; private ConsentStorage $consent_storage; public function __construct( string $public_key, string $private_key, array $clients ) { $this->public_key = $public_key; - $this->clients = $clients; + $this->clients = new ClientCredentialsStorage( $clients ); $this->router = new Router(); $this->consent_storage = new ConsentStorage(); + $config = array( 'use_jwt_access_tokens' => true, 'use_openid_connect' => true, @@ -38,7 +39,7 @@ public function __construct( string $public_key, string $private_key, array $cli $server = new Server( new AuthorizationCodeStorage(), $config ); $server->addStorage( new PublicKeyStorage( $public_key, $private_key ), 'public_key' ); - $server->addStorage( new ClientCredentialsStorage( $clients ), 'client_credentials' ); + $server->addStorage( $this->clients, 'client_credentials' ); $server->addStorage( new UserClaimsStorage(), 'user_claims' ); // Declare rest routes. @@ -50,7 +51,7 @@ public function __construct( string $public_key, string $private_key, array $cli ); $this->router->add_rest_route( 'authorize', - new AuthorizeHandler( $server, $this->consent_storage ), + new AuthorizeHandler( $server, $this->consent_storage , $this->clients), array( 'GET', 'POST' ), $this->expected_arguments_specification( 'authorize' ), ); diff --git a/src/Storage/ClientCredentialsStorage.php b/src/Storage/ClientCredentialsStorage.php index b474545..a4c6293 100644 --- a/src/Storage/ClientCredentialsStorage.php +++ b/src/Storage/ClientCredentialsStorage.php @@ -25,6 +25,34 @@ public function getClientDetails( $client_id ) { ); } + public function getClientName( $client_id ) { + if ( ! $this->has( $client_id ) ) { + return ''; + } + + $client = $this->get( $client_id ); + + if ( empty( $client['name'] ) ) { + return ''; + } + + return $client['name']; + } + + public function clientRequiresConsent( $client_id ) : bool { + if ( ! $this->has( $client_id ) ) { + return true; + } + + $client = $this->get( $client_id ); + + if ( ! array_key_exists( 'requires_consent', $client ) ) { + return true; + } + + return $client['requires_consent'] === true; + } + public function getClientScope( $client_id ) { if ( ! $this->has( $client_id ) ) { return '';