Skip to content

Commit

Permalink
Add support for PKCE
Browse files Browse the repository at this point in the history
  • Loading branch information
nikosev committed Oct 29, 2020
1 parent 9f15504 commit ce97230
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Added
* Support for [PKCE](https://tools.ietf.org/html/rfc7636). Currentlly the supported methods are 'plain' and 'S256'.

## [0.9.1]

### Added
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ if (!$data->active) {

```

## Example 8: PKCE Client ##

```php
use Jumbojett\OpenIDConnectClient;

$oidc = new OpenIDConnectClient('https://id.provider.com',
'ClientIDHere',
null);
$oidc->setCodeChallengeMethod('S256');
$oidc->authenticate();
$name = $oidc->requestUserInfo('given_name');

```


## Development Environments ##
In some cases you may need to disable SSL security on on your development systems.
Expand Down
78 changes: 78 additions & 0 deletions src/OpenIDConnectClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,17 @@ class OpenIDConnectClient

protected $enc_type = PHP_QUERY_RFC1738;

/**
* @var string holds code challenge method for PKCE mode
* @see https://tools.ietf.org/html/rfc7636
*/
private $codeChallengeMethod = false;

/**
* @var array holds PKCE supported algorithms
*/
private $pkceAlgs = array('S256' => 'sha256', 'plain' => false);

/**
* @param $provider_url string optional
*
Expand Down Expand Up @@ -640,6 +651,21 @@ private function requestAuthorization() {
$auth_params = array_merge($auth_params, array('response_type' => implode(' ', $this->responseTypes)));
}

// If the client supports Proof Key for Code Exchange (PKCE)
if (!empty($this->getCodeChallengeMethod()) && in_array($this->getCodeChallengeMethod(), $this->getProviderConfigValue('code_challenge_methods_supported'))) {
$codeVerifier = bin2hex(random_bytes(64));
$this->setCodeVerifier($codeVerifier);
if (!empty($this->pkceAlgs[$this->getCodeChallengeMethod()])) {
$codeChallenge = rtrim(strtr(base64_encode(hash($this->pkceAlgs[$this->getCodeChallengeMethod()], $codeVerifier, true)), '+/', '-_'), '=');
} else {
$codeChallenge = $codeVerifier;
}
$auth_params = array_merge($auth_params, array(
'code_challenge' => $codeChallenge,
'code_challenge_method' => $this->getCodeChallengeMethod()
));
}

$auth_endpoint .= (strpos($auth_endpoint, '?') === false ? '?' : '&') . http_build_query($auth_params, null, '&', $this->enc_type);

$this->commitSession();
Expand Down Expand Up @@ -737,6 +763,15 @@ protected function requestTokens($code) {
unset($token_params['client_id']);
}

if (!empty($this->getCodeVerifier())) {
$headers = [];
unset($token_params['client_secret']);
$token_params = array_merge($token_params, array(
'client_id' => $this->clientID,
'code_verifier' => $this->getCodeVerifier()
));
}

// Convert token params to string format
$token_params = http_build_query($token_params, null, '&', $this->enc_type);

Expand Down Expand Up @@ -1579,6 +1614,35 @@ protected function unsetState() {
$this->unsetSessionKey('openid_connect_state');
}

/**
* Stores $codeVerifier
*
* @param string $codeVerifier
* @return string
*/
protected function setCodeVerifier($codeVerifier) {
$this->setSessionKey('openid_connect_code_verifier', $codeVerifier);
return $codeVerifier;
}

/**
* Get stored codeVerifier
*
* @return string
*/
protected function getCodeVerifier() {
return $this->getSessionKey('openid_connect_code_verifier');
}

/**
* Cleanup state
*
* @return void
*/
protected function unsetCodeVerifier() {
$this->unsetSessionKey('openid_connect_code_verifier');
}

/**
* Get the response code from last action/curl request.
*
Expand Down Expand Up @@ -1732,4 +1796,18 @@ public function getLeeway()
{
return $this->leeway;
}

/**
* @return string
*/
public function getCodeChallengeMethod() {
return $this->codeChallengeMethod;
}

/**
* @param string $codeChallengeMethod
*/
public function setCodeChallengeMethod($codeChallengeMethod) {
$this->codeChallengeMethod = $codeChallengeMethod;
}
}

0 comments on commit ce97230

Please sign in to comment.