Skip to content

Commit 0e2fbc3

Browse files
Merge pull request #331 from jumbojett/fix/client_secret_jwt-configurable-alternative
fix: client_secret_jwt and private_key_jwt support is disabled by def…
2 parents a135c5d + 89bdf7c commit 0e2fbc3

File tree

3 files changed

+88
-11
lines changed

3 files changed

+88
-11
lines changed

README.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ PHP OpenID Connect Basic Client
22
========================
33
A simple library that allows an application to authenticate a user through the basic OpenID Connect flow.
44
This library hopes to encourage OpenID Connect use by making it simple enough for a developer with little knowledge of
5-
the OpenID Connect protocol to setup authentication.
5+
the OpenID Connect protocol to set up authentication.
66

77
A special thanks goes to Justin Richer and Amanda Anganes for their help and support of the protocol.
88

@@ -12,11 +12,12 @@ A special thanks goes to Justin Richer and Amanda Anganes for their help and sup
1212
3. JSON extension
1313

1414
## Install ##
15-
1. Install library using composer
15+
1. Install library using composer
1616
```
1717
composer require jumbojett/openid-connect-php
1818
```
19-
2. Include composer autoloader
19+
20+
2. Include composer autoloader
2021
```php
2122
require __DIR__ . '/vendor/autoload.php';
2223
```
@@ -191,6 +192,28 @@ function handleLogout() {
191192

192193
```
193194

195+
## Example 10: Enable Token Endpoint Auth Methods ##
196+
197+
By default, only `client_secret_basic` is enabled on client side which was the only supported for a long time.
198+
Recently `client_secret_jwt` and `private_key_jwt` have been added, but they remain disabled until explicitly enabled.
199+
200+
```php
201+
use Jumbojett\OpenIDConnectClient;
202+
203+
$oidc = new OpenIDConnectClient('https://id.provider.com',
204+
'ClientIDHere',
205+
null);
206+
# enable 'client_secret_basic' and 'client_secret_jwt'
207+
$oidc->setTokenEndpointAuthMethodsSupported(['client_secret_basic', 'client_secret_jwt']);
208+
209+
# for 'private_key_jwt' in addition also the generator function has to be set.
210+
$oidc->setTokenEndpointAuthMethodsSupported(['private_key_jwt']);
211+
$oidc->setPrivateKeyJwtGenerator(function(string $token_endpoint) {
212+
# TODO: what ever is necessary
213+
})
214+
```
215+
216+
194217
## Development Environments ##
195218
In some cases you may need to disable SSL security on your development systems.
196219
Note: This is not recommended on production systems.

src/OpenIDConnectClient.php

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,11 @@ class OpenIDConnectClient
261261
*/
262262
private $backChannelSubject;
263263

264+
/**
265+
* @var array list of supported auth methods
266+
*/
267+
private $token_endpoint_auth_methods_supported = ['client_secret_basic'];
268+
264269
/**
265270
* @param $provider_url string optional
266271
*
@@ -597,6 +602,14 @@ public function addRegistrationParam($param) {
597602
$this->registrationParams = array_merge($this->registrationParams, (array)$param);
598603
}
599604

605+
/**
606+
* @param array $token_endpoint_auth_methods_supported
607+
*/
608+
public function setTokenEndpointAuthMethodsSupported($token_endpoint_auth_methods_supported)
609+
{
610+
$this->token_endpoint_auth_methods_supported = $token_endpoint_auth_methods_supported;
611+
}
612+
600613
/**
601614
* @param $jwk object - example: (object) ['kid' => ..., 'nbf' => ..., 'use' => 'sig', 'kty' => "RSA", 'e' => "", 'n' => ""]
602615
*/
@@ -872,7 +885,7 @@ public function requestResourceOwnerToken($bClientAuth = FALSE) {
872885
//For client authentication include the client values
873886
if($bClientAuth) {
874887
$token_endpoint_auth_methods_supported = $this->getProviderConfigValue('token_endpoint_auth_methods_supported', ['client_secret_basic']);
875-
if (in_array('client_secret_basic', $token_endpoint_auth_methods_supported, true)) {
888+
if ($this->supportsAuthMethod('client_secret_basic', $token_endpoint_auth_methods_supported)) {
876889
$headers = ['Authorization: Basic ' . base64_encode(urlencode($this->clientID) . ':' . urlencode($this->clientSecret))];
877890
} else {
878891
$post_data['client_id'] = $this->clientID;
@@ -911,19 +924,19 @@ protected function requestTokens($code, $headers = array()) {
911924

912925
$authorizationHeader = null;
913926
# Consider Basic authentication if provider config is set this way
914-
if (in_array('client_secret_basic', $token_endpoint_auth_methods_supported, true)) {
927+
if ($this->supportsAuthMethod('client_secret_basic', $token_endpoint_auth_methods_supported)) {
915928
$authorizationHeader = 'Authorization: Basic ' . base64_encode(urlencode($this->clientID) . ':' . urlencode($this->clientSecret));
916929
unset($token_params['client_secret']);
917930
unset($token_params['client_id']);
918931
}
919932

920933
// When there is a private key jwt generator and it is supported then use it as client authentication
921-
if ($this->privateKeyJwtGenerator !== null && in_array('private_key_jwt', $token_endpoint_auth_methods_supported, true)) {
934+
if ($this->privateKeyJwtGenerator !== null && $this->supportsAuthMethod('private_key_jwt', $token_endpoint_auth_methods_supported)) {
922935
$token_params['client_assertion_type'] = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer';
923936
$token_params['client_assertion'] = $this->privateKeyJwtGenerator->__invoke($token_endpoint);
924937
}
925938

926-
if (in_array('client_secret_jwt', $token_endpoint_auth_methods_supported, true)) {
939+
if ($this->supportsAuthMethod('client_secret_jwt', $token_endpoint_auth_methods_supported)) {
927940
$client_assertion_type = $this->getProviderConfigValue('client_assertion_type');
928941

929942
if(isset($this->providerConfig['client_assertion'])){
@@ -994,7 +1007,7 @@ public function requestTokenExchange($subjectToken, $subjectTokenType, $audience
9941007
}
9951008

9961009
# Consider Basic authentication if provider config is set this way
997-
if (in_array('client_secret_basic', $token_endpoint_auth_methods_supported, true)) {
1010+
if ($this->supportsAuthMethod('client_secret_basic', $token_endpoint_auth_methods_supported)) {
9981011
$headers = ['Authorization: Basic ' . base64_encode(urlencode($this->clientID) . ':' . urlencode($this->clientSecret))];
9991012
unset($post_data['client_secret']);
10001013
unset($post_data['client_id']);
@@ -1031,13 +1044,13 @@ public function refreshToken($refresh_token) {
10311044
];
10321045

10331046
# Consider Basic authentication if provider config is set this way
1034-
if (in_array('client_secret_basic', $token_endpoint_auth_methods_supported, true)) {
1047+
if ($this->supportsAuthMethod('client_secret_basic', $token_endpoint_auth_methods_supported)) {
10351048
$headers = ['Authorization: Basic ' . base64_encode(urlencode($this->clientID) . ':' . urlencode($this->clientSecret))];
10361049
unset($token_params['client_secret']);
10371050
unset($token_params['client_id']);
10381051
}
10391052

1040-
if (in_array('client_secret_jwt', $token_endpoint_auth_methods_supported, true)) {
1053+
if ($this->supportsAuthMethod('client_secret_jwt', $token_endpoint_auth_methods_supported)) {
10411054
$client_assertion_type = $this->getProviderConfigValue('client_assertion_type');
10421055
$client_assertion = $this->getJWTClientAssertion($this->getProviderConfigValue('token_endpoint'));
10431056

@@ -1728,7 +1741,7 @@ public function introspectToken($token, $token_type_hint = '', $clientId = null,
17281741
$headers = ['Authorization: Basic ' . base64_encode(urlencode($clientId) . ':' . urlencode($clientSecret)),
17291742
'Accept: application/json'];
17301743

1731-
if (in_array('client_secret_jwt', $token_endpoint_auth_methods_supported, true)) {
1744+
if ($this->supportsAuthMethod('client_secret_jwt', $token_endpoint_auth_methods_supported)) {
17321745
$client_assertion_type = $this->getProviderConfigValue('client_assertion_type');
17331746
$client_assertion = $this->getJWTClientAssertion($this->getProviderConfigValue('introspection_endpoint'));
17341747

@@ -2188,4 +2201,19 @@ public function getSidFromBackChannel() {
21882201
public function getSubjectFromBackChannel() {
21892202
return $this->backChannelSubject;
21902203
}
2204+
2205+
/**
2206+
* @param string $auth_method
2207+
* @param array $token_endpoint_auth_methods_supported
2208+
* @return bool
2209+
*/
2210+
public function supportsAuthMethod($auth_method, $token_endpoint_auth_methods_supported)
2211+
{
2212+
# client_secret_jwt has to explicitly be enabled
2213+
if (!in_array($auth_method, $this->token_endpoint_auth_methods_supported, true)) {
2214+
return false;
2215+
}
2216+
2217+
return in_array($auth_method, $token_endpoint_auth_methods_supported, true);
2218+
}
21912219
}

tests/OpenIDConnectClientTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,30 @@ public function testSerialize()
6262
$serialized = serialize($client);
6363
$this->assertInstanceOf('Jumbojett\OpenIDConnectClient', unserialize($serialized));
6464
}
65+
66+
/**
67+
* @dataProvider provider
68+
*/
69+
public function testAuthMethodSupport($expected, $authMethod, $clientAuthMethods, $idpAuthMethods)
70+
{
71+
$client = new OpenIDConnectClient();
72+
if ($clientAuthMethods !== null) {
73+
$client->setTokenEndpointAuthMethodsSupported($clientAuthMethods);
74+
}
75+
$this->assertEquals($expected, $client->supportsAuthMethod($authMethod, $idpAuthMethods));
76+
}
77+
78+
public function provider()
79+
{
80+
return [
81+
'client_secret_basic - default config' => [true, 'client_secret_basic', null, ['client_secret_basic']],
82+
83+
'client_secret_jwt - default config' => [false, 'client_secret_jwt', null, ['client_secret_basic', 'client_secret_jwt']],
84+
'client_secret_jwt - explicitly enabled' => [true, 'client_secret_jwt', ['client_secret_jwt'], ['client_secret_basic', 'client_secret_jwt']],
85+
86+
'private_key_jwt - default config' => [false, 'private_key_jwt', null, ['client_secret_basic', 'client_secret_jwt', 'private_key_jwt']],
87+
'private_key_jwt - explicitly enabled' => [true, 'private_key_jwt', ['private_key_jwt'], ['client_secret_basic', 'client_secret_jwt', 'private_key_jwt']],
88+
89+
];
90+
}
6591
}

0 commit comments

Comments
 (0)