Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- `http_client_options.timeout` now defaults to `30` seconds when not set,
so a slow or hung identity provider can no longer block worker processes
indefinitely. Previously no timeout was applied and Guzzle's own default
(`0` — wait forever) was used. Set `timeout: 0` to restore the old
behaviour, or override per provider.

## [5.0.0] - 2026-06-02

### Changed (BREAKING)
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,10 @@ Set the actual values your `env.local` file to ensure they are not committed to
#### Configuring the HTTP client

Each provider accepts an optional `http_client_options` block that is forwarded
to the underlying Guzzle HTTP client used by `league/oauth2-client`. This is
useful for setting a request timeout so a slow IdP cannot block worker
processes indefinitely.
to the underlying Guzzle HTTP client used by `league/oauth2-client`. The bundle
applies a sensible default `timeout` of `30` seconds so a slow IdP cannot block
worker processes indefinitely (Guzzle's own default is `0`, i.e. wait forever).
Override it per provider, or set it to `0` to opt back into Guzzle's behaviour.

```yaml
itkdev_openid_connect:
Expand All @@ -166,7 +167,7 @@ itkdev_openid_connect:
# ... existing keys ...
# @see https://docs.guzzlephp.org/en/stable/request-options.html
http_client_options:
# Float describing the total timeout of the request in seconds. Use 0 to wait indefinitely (the default behavior).
# Float describing the total timeout of the request in seconds. Defaults to 30; set to 0 to wait indefinitely.
timeout: 5.0
# Pass a string to specify an HTTP proxy, or an array to specify different proxies for different protocols. (Default: none)
proxy: "%env(string:HTTP_PROXY)%"
Expand Down
4 changes: 3 additions & 1 deletion src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,12 @@ public function getConfigTreeBuilder(): TreeBuilder
// Uses Guzzle under the hood through itk-dev/openid-connect -> league/oauth2-client -> guzzlehttp/guzzle
->arrayNode('http_client_options')
->info('Options forwarded to the underlying Guzzle HTTP client. league/oauth2-client only forwards: timeout, proxy, verify (verify is only consulted when proxy is set).')
->addDefaultsIfNotSet()
->children()
// @see https://docs.guzzlephp.org/en/stable/request-options.html#timeout
->floatNode('timeout')
->info('Total request timeout in seconds')
->info('Total request timeout in seconds. Defaults to 30; set to 0 to wait indefinitely (Guzzle\'s own default).')
->defaultValue(30.0)
->end()
// @see https://docs.guzzlephp.org/en/stable/request-options.html#proxy
->scalarNode('proxy')
Expand Down
12 changes: 7 additions & 5 deletions tests/DependencyInjection/ConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,18 +132,20 @@ public function testHttpClientOptionsAccepted(): void
$this->assertTrue($httpClientOptions['verify']);
}

public function testHttpClientOptionsAbsentByDefault(): void
public function testHttpClientOptionsDefaultsApplied(): void
{
$config = $this->processor->processConfiguration(
$this->configuration,
[$this->getMinimalConfig()]
);

$providerOptions = $config['openid_providers']['provider1']['options'];
// The block has no default value, so an omitted input must produce no
// http_client_options key in the processed config — otherwise an empty
// array would still be merged into the provider options.
$this->assertArrayNotHasKey('http_client_options', $providerOptions);
// The block carries a sensible default timeout so an omitted input still
// protects workers from a hung IdP. proxy/verify have no default and so
// stay absent (Guzzle's own defaults apply).
$this->assertSame(30.0, $providerOptions['http_client_options']['timeout']);
$this->assertArrayNotHasKey('proxy', $providerOptions['http_client_options']);
$this->assertArrayNotHasKey('verify', $providerOptions['http_client_options']);
}

public function testHttpClientOptionsRejectsUnknownKey(): void
Expand Down
Loading