N°5809 Update thenetworg/oauth2-azure from 2.1.1 to 2.2.2

This commit is contained in:
Pierre Goiffon
2024-01-25 17:34:55 +01:00
parent e1296105f9
commit 9235c395b4
13 changed files with 112 additions and 179 deletions

View File

@@ -5284,17 +5284,17 @@
},
{
"name": "thenetworg/oauth2-azure",
"version": "v2.1.1",
"version_normalized": "2.1.1.0",
"version": "v2.2.2",
"version_normalized": "2.2.2.0",
"source": {
"type": "git",
"url": "https://github.com/TheNetworg/oauth2-azure.git",
"reference": "06fb2d620fb6e6c934f632c7ec7c5ea2e978a844"
"reference": "be204a5135f016470a9c33e82ab48785bbc11af2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/TheNetworg/oauth2-azure/zipball/06fb2d620fb6e6c934f632c7ec7c5ea2e978a844",
"reference": "06fb2d620fb6e6c934f632c7ec7c5ea2e978a844",
"url": "https://api.github.com/repos/TheNetworg/oauth2-azure/zipball/be204a5135f016470a9c33e82ab48785bbc11af2",
"reference": "be204a5135f016470a9c33e82ab48785bbc11af2",
"shasum": ""
},
"require": {
@@ -5304,7 +5304,10 @@
"league/oauth2-client": "~2.0",
"php": "^7.1|^8.0"
},
"time": "2022-06-23T10:35:36+00:00",
"require-dev": {
"phpunit/phpunit": "^9.6"
},
"time": "2023-12-19T12:10:48+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -5338,7 +5341,7 @@
],
"support": {
"issues": "https://github.com/TheNetworg/oauth2-azure/issues",
"source": "https://github.com/TheNetworg/oauth2-azure/tree/v2.1.1"
"source": "https://github.com/TheNetworg/oauth2-azure/tree/v2.2.2"
},
"install-path": "../thenetworg/oauth2-azure"
},

View File

@@ -3,7 +3,7 @@
'name' => 'combodo/itop',
'pretty_version' => 'dev-develop',
'version' => 'dev-develop',
'reference' => '1400bdb25295b0e50adbd66ed9c2f3ea857bcf71',
'reference' => '195d4137172d9169005b6b7f0569866480e6260f',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -22,7 +22,7 @@
'combodo/itop' => array(
'pretty_version' => 'dev-develop',
'version' => 'dev-develop',
'reference' => '1400bdb25295b0e50adbd66ed9c2f3ea857bcf71',
'reference' => '195d4137172d9169005b6b7f0569866480e6260f',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -717,9 +717,9 @@
),
),
'thenetworg/oauth2-azure' => array(
'pretty_version' => 'v2.1.1',
'version' => '2.1.1.0',
'reference' => '06fb2d620fb6e6c934f632c7ec7c5ea2e978a844',
'pretty_version' => 'v2.2.2',
'version' => '2.2.2.0',
'reference' => 'be204a5135f016470a9c33e82ab48785bbc11af2',
'type' => 'library',
'install_path' => __DIR__ . '/../thenetworg/oauth2-azure',
'aliases' => array(),

View File

@@ -1,15 +0,0 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.134.0/containers/php/.devcontainer/base.Dockerfile
ARG VARIANT="7"
FROM mcr.microsoft.com/vscode/devcontainers/php:0-${VARIANT}
# [Optional] Install a version of Node.js using nvm for front end dev
ARG INSTALL_NODE="true"
ARG NODE_VERSION="lts/*"
RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>
# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1

View File

@@ -1,29 +0,0 @@
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.134.0/containers/php
{
"name": "PHP",
"build": {
"dockerfile": "Dockerfile",
"args": {
// Update VARIANT to pick a PHP version: 7, 7.4, 7.3
"VARIANT": "7",
"INSTALL_NODE": "false",
"NODE_VERSION": "lts/*"
}
},
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"felixfbecker.php-debug",
"felixfbecker.php-intellisense"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "php -v",
// Comment out to connect as root instead.
"remoteUser": "vscode"
}

View File

@@ -1,9 +0,0 @@
/build
/vendor
composer.phar
composer.lock
.DS_Store
# IDE
/.idea
/.vscode

View File

@@ -1,70 +0,0 @@
<?php
$finder = PhpCsFixer\Finder::create()
->in(__DIR__ . '/src');
return PhpCsFixer\Config::create()
->setRiskyAllowed(true)
->setUsingCache(false)
->setRules([
'@PSR2' => true,
'align_multiline_comment' => true,
'array_indentation' => true,
'array_syntax' => ['syntax' => 'short'],
'binary_operator_spaces' => ['default' => 'align_single_space_minimal'],
'blank_line_after_opening_tag' => true,
'class_attributes_separation' => true,
'combine_consecutive_issets' => true,
'general_phpdoc_annotation_remove' => ['annotations' => ['author', 'package', 'subpackage']],
'declare_equal_normalize' => ['space' => 'single'],
'dir_constant' => true,
'fully_qualified_strict_types' => true,
'function_typehint_space' => true,
'heredoc_to_nowdoc' => true,
'include' => true,
'is_null' => ['use_yoda_style' => true],
'linebreak_after_opening_tag' => true,
'lowercase_cast' => true,
'modernize_types_casting' => true,
'new_with_braces' => true,
'no_alias_functions' => true,
'no_alternative_syntax' => true,
'no_blank_lines_after_phpdoc' => true,
'no_empty_comment' => true,
'no_empty_phpdoc' => true,
'no_empty_statement' => true,
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_mixed_echo_print' => ['use' => 'echo'],
'no_multiline_whitespace_before_semicolons' => true,
'no_null_property_initialization' => true,
'no_php4_constructor' => true,
'no_short_echo_tag' => false,
'no_unreachable_default_argument_value' => true,
'no_useless_else' => true,
'no_useless_return' => true,
'ordered_class_elements' => true,
'ordered_imports' => true,
'phpdoc_add_missing_param_annotation' => ['only_untyped' => false],
'phpdoc_order' => true,
'phpdoc_return_self_reference' => true,
'phpdoc_scalar' => true,
'phpdoc_single_line_var_spacing' => true,
'phpdoc_to_comment' => true,
'phpdoc_trim' => true,
'phpdoc_types' => true,
'phpdoc_types_order' => ['null_adjustment' => 'always_last'],
'phpdoc_var_without_name' => true,
'short_scalar_cast' => true,
'simplified_null_return' => true,
'single_blank_line_before_namespace' => true,
'single_line_comment_style' => true,
'single_quote' => ['strings_containing_single_quote_chars' => true],
'standardize_increment' => true,
'standardize_not_equals' => true,
'trailing_comma_in_multiline_array' => true,
'trim_array_spaces' => true,
'whitespace_after_comma_in_array' => true,
'yoda_style' => true,
])
->setFinder($finder);

View File

@@ -1,27 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch application",
"type": "php",
"request": "launch",
"program": "${workspaceFolder}/index.php",
"cwd": "${workspaceFolder}",
"port": 9000
},
{
"name": "Listen for XDebug",
"type": "php",
"request": "launch",
"port": 9000
},
{
"name": "Launch currently open script",
"type": "php",
"request": "launch",
"program": "${file}",
"cwd": "${fileDirname}",
"port": 9000
}
]
}

View File

@@ -1,5 +1,5 @@
# Changelog
All Notable changes to `oauth2-azure` will be documented in this file
This file is not actively maintained. All Notable changes to `oauth2-azure` are documented at https://github.com/TheNetworg/oauth2-azure/releases
## v1.0.0 - 16NOV2015
- Initial release
- Initial release

View File

@@ -45,6 +45,10 @@ $provider = new TheNetworg\OAuth2\Client\Provider\Azure([
'clientId' => '{azure-client-id}',
'clientSecret' => '{azure-client-secret}',
'redirectUri' => 'https://example.com/callback-url',
//Optional using key pair instead of secret
'clientCertificatePrivateKey' => '{azure-client-certificate-private-key}',
//Optional using key pair instead of secret
'clientCertificateThumbprint' => '{azure-client-certificate-thumbprint}',
//Optional
'scopes' => ['openid'],
//Optional
@@ -128,6 +132,19 @@ $authUrl = $provider->getAuthorizationUrl([
```
You can find additional parameters [here](https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx).
#### Using a certificate key pair instead of the shared secret
- Generate a key pair, e.g. with:
```bash
openssl genrsa -out private.key 2048
openssl req -new -x509 -key private.key -out publickey.cer -days 365
```
- Upload the `publickey.cer` to your app in the Azure portal
- Note the displayed thumbprint for the certificate (it looks like `B4A94A83092455AC4D3AC827F02B61646EAAC43D`)
- Put that thumbprint into the `clientCertificateThumbprint` constructor option
- Put the contents of `private.key` into the `clientCertificatePrivateKey` constructor option
- You can omit the `clientSecret` constructor option
### Logging out
If you need to quickly generate a logout URL for the user, you can do following:
```php

View File

@@ -32,5 +32,13 @@
"psr-4": {
"TheNetworg\\OAuth2\\Client\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"TheNetworg\\OAuth2\\Client\\Tests\\": "tests/"
}
},
"require-dev": {
"phpunit/phpunit": "^9.6"
}
}

View File

@@ -11,6 +11,7 @@ use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Provider\ResourceOwnerInterface;
use League\OAuth2\Client\Token\AccessTokenInterface;
use League\OAuth2\Client\Tool\BearerAuthorizationTrait;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use TheNetworg\OAuth2\Client\Grant\JwtBearer;
use TheNetworg\OAuth2\Client\Token\AccessToken;
@@ -44,6 +45,20 @@ class Azure extends AbstractProvider
public $authWithResource = true;
public $defaultAlgorithm = null;
/**
* The contents of the private key used for app authentication
* @var string
*/
protected $clientCertificatePrivateKey = '';
/**
* The hexadecimal certificate thumbprint as displayed in the azure portal
* @var string
*/
protected $clientCertificateThumbprint = '';
public function __construct(array $options = [], array $collaborators = [])
{
parent::__construct($options, $collaborators);
@@ -54,6 +69,9 @@ class Azure extends AbstractProvider
in_array($options['defaultEndPointVersion'], self::ENDPOINT_VERSIONS, true)) {
$this->defaultEndPointVersion = $options['defaultEndPointVersion'];
}
if (isset($options['defaultAlgorithm'])) {
$this->defaultAlgorithm = $options['defaultAlgorithm'];
}
$this->grantFactory->setGrant('jwt_bearer', new JwtBearer());
}
@@ -103,6 +121,32 @@ class Azure extends AbstractProvider
return $openIdConfiguration['token_endpoint'];
}
protected function getAccessTokenRequest(array $params): RequestInterface
{
if ($this->clientCertificatePrivateKey && $this->clientCertificateThumbprint) {
$header = [
'x5t' => base64_encode(hex2bin($this->clientCertificateThumbprint)),
];
$now = time();
$payload = [
'aud' => "https://login.microsoftonline.com/{$this->tenant}/oauth2/v2.0/token",
'exp' => $now + 360,
'iat' => $now,
'iss' => $this->clientId,
'jti' => bin2hex(random_bytes(20)),
'nbf' => $now,
'sub' => $this->clientId,
];
$jwt = JWT::encode($payload, str_replace('\n', "\n", $this->clientCertificatePrivateKey), 'RS256', null, $header);
unset($params['client_secret']);
$params['client_assertion_type'] = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer';
$params['client_assertion'] = $jwt;
}
return parent::getAccessTokenRequest($params);
}
/**
* @inheritdoc
*/
@@ -134,7 +178,8 @@ class Azure extends AbstractProvider
*/
public function getResourceOwnerDetailsUrl(\League\OAuth2\Client\Token\AccessToken $token): string
{
return ''; // shouldn't that return such a URL?
$openIdConfiguration = $this->getOpenIdConfiguration($this->tenant, $this->defaultEndPointVersion);
return $openIdConfiguration['userinfo_endpoint'];
}
public function getObjects($tenant, $ref, &$accessToken, $headers = [])
@@ -178,8 +223,8 @@ class Azure extends AbstractProvider
$version = $this->defaultEndPointVersion;
} else {
$idTokenClaims = $accessToken->getIdTokenClaims();
$tenant = array_key_exists('tid', $idTokenClaims) ? $idTokenClaims['tid'] : $this->tenant;
$version = array_key_exists('ver', $idTokenClaims) ? $idTokenClaims['ver'] : $this->defaultEndPointVersion;
$tenant = is_array($idTokenClaims) && array_key_exists('tid', $idTokenClaims) ? $idTokenClaims['tid'] : $this->tenant;
$version = is_array($idTokenClaims) && array_key_exists('ver', $idTokenClaims) ? $idTokenClaims['ver'] : $this->defaultEndPointVersion;
}
$openIdConfiguration = $this->getOpenIdConfiguration($tenant, $version);
return 'https://' . $openIdConfiguration['msgraph_host'];
@@ -295,7 +340,7 @@ class Azure extends AbstractProvider
public function validateAccessToken($accessToken)
{
$keys = $this->getJwtVerificationKeys();
$tokenClaims = (array)JWT::decode($accessToken, $keys, ['RS256']);
$tokenClaims = (array)JWT::decode($accessToken, $keys);
$this->validateTokenClaims($tokenClaims);
@@ -376,13 +421,18 @@ class Azure extends AbstractProvider
$keys[$keyinfo['kid']] = new Key($publicKey, 'RS256');
}
} else if (isset($keyinfo['n']) && isset($keyinfo['e'])) {
$pkey_object = JWK::parseKey($keyinfo);
$alg = $this->defaultAlgorithm;
if (is_null($alg) && isset($keyinfo['kty'])) {
$alg = $keyinfo['kty'];
}
$pkey_object = JWK::parseKey($keyinfo, $alg);
if ($pkey_object === false) {
throw new \RuntimeException('An attempt to read a public key from a ' . $keyinfo['n'] . ' certificate failed.');
}
$pkey_array = openssl_pkey_get_details($pkey_object);
$pkey_array = openssl_pkey_get_details($pkey_object->getKeyMaterial());
if ($pkey_array === false) {
throw new \RuntimeException('An attempt to get a public key as an array from a ' . $keyinfo['n'] . ' certificate failed.');

View File

@@ -3,9 +3,8 @@
namespace TheNetworg\OAuth2\Client\Token;
use Firebase\JWT\JWT;
use InvalidArgumentException;
use League\OAuth2\Client\Tool\RequestFactory;
use RuntimeException;
use TheNetworg\OAuth2\Client\Provider\Azure;
class AccessToken extends \League\OAuth2\Client\Token\AccessToken
{
@@ -13,6 +12,9 @@ class AccessToken extends \League\OAuth2\Client\Token\AccessToken
protected $idTokenClaims;
/**
* @param Azure $provider
*/
public function __construct(array $options, $provider)
{
parent::__construct($options);
@@ -27,7 +29,7 @@ class AccessToken extends \League\OAuth2\Client\Token\AccessToken
$tks = explode('.', $this->idToken);
// Check if the id_token contains signature
if (3 == count($tks) && !empty($tks[2])) {
$idTokenClaims = (array)JWT::decode($this->idToken, $keys, ['RS256']);
$idTokenClaims = (array)JWT::decode($this->idToken, $keys);
} else {
// The id_token is unsigned (coming from v1.0 endpoint) - https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx