Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a0d460a
Merge tag '4.1.0' into develop
turegjorup Mar 20, 2026
4f1e45c
Bump actions/checkout to v6 and improve Taskfile
turegjorup Mar 24, 2026
d029165
Merge pull request #29 from itk-dev/feature/ci-and-taskfile-improvements
turegjorup Mar 24, 2026
bd43892
Expand README note on Symfony native OIDC support
turegjorup May 7, 2026
b5cd84d
Expose http_client_options for per-provider HTTP timeout/proxy/verify
turegjorup May 7, 2026
f626dd4
Fix broken CI badge in README
turegjorup May 7, 2026
5e378cf
Merge pull request #30 from itk-dev/feature/readme-symfony-native-oidc
turegjorup May 7, 2026
900c872
Clarify docs and comments for http client options
turegjorup May 8, 2026
075e3dd
Map LoginController failures to specific HTTP errors
turegjorup May 8, 2026
ada8ba1
Tighten http_client_options absent-by-default assertion
turegjorup May 8, 2026
f303f86
Clarify that bundle config rejects unknown http_client_options keys
turegjorup May 8, 2026
c08958d
Expose per-provider cache_duration option
turegjorup May 8, 2026
f211885
Merge branch 'develop' into feature/http-client-options
turegjorup May 8, 2026
2d3781c
Merge pull request #31 from itk-dev/feature/http-client-options
turegjorup May 8, 2026
a367f8c
Merge branch 'develop' into feature/login-controller-http-errors
turegjorup May 8, 2026
1874fa3
Merge branch 'develop' into feature/cache-duration-option
turegjorup May 11, 2026
73b94dd
Merge pull request #34 from itk-dev/feature/cache-duration-option
turegjorup May 11, 2026
a341a30
Address review on LoginController HTTP error mapping
turegjorup May 11, 2026
65ab332
Merge remote-tracking branch 'origin/develop' into feature/login-cont…
turegjorup May 11, 2026
c3385ca
Declare all login() throws including league boundary
turegjorup May 11, 2026
53c62a5
Merge pull request #33 from itk-dev/feature/login-controller-http-errors
turegjorup May 11, 2026
3b6152b
Preserve $previous in CliLoginHelper and validateClaims wraps
turegjorup May 11, 2026
f2764ad
docs: add ADR 001 — marker-interface exception hierarchy
turegjorup May 11, 2026
3daaf78
docs: clarify ADR 001 is a course correction, not a redesign
turegjorup May 11, 2026
c65ff56
Merge pull request #35 from itk-dev/fix/exception-cause-chain
turegjorup May 11, 2026
bada46d
Merge branch 'develop' into docs/adr-exception-contract-migration
turegjorup May 11, 2026
1faf7d8
Merge pull request #36 from itk-dev/docs/adr-exception-contract-migra…
turegjorup May 11, 2026
e236274
release: 4.2.0
turegjorup May 11, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 2

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/composer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
matrix:
prefer: [prefer-lowest, prefer-stable]
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6

- name: Create docker network
run: |
Expand All @@ -58,7 +58,7 @@ jobs:
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6

- name: Create docker network
run: |
Expand All @@ -73,7 +73,7 @@ jobs:
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6

- name: Create docker network
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/github_build_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
APP_ENV: prod
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: Create a release in GitHub
run: gh release create ${{ github.ref_name }} --verify-tag --generate-notes
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/markdown.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: Create docker network
run: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/php.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
name: PHP - Check Coding Standards
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6

- name: Create docker network
run: |
Expand All @@ -29,7 +29,7 @@ jobs:
name: PHPStan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6

- name: Create docker network
run: |
Expand Down Expand Up @@ -65,7 +65,7 @@ jobs:
php: "8.5"
prefer: prefer-stable
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6

- name: Create docker network
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/yaml.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
yaml-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6

- name: Create docker network
run: |
Expand Down
34 changes: 33 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [4.2.0] - 2026-05-11

### Added

- Per-provider `cache_duration` option (seconds) forwarded to the
underlying library; lets consumers tighten or extend the 24h default
TTL for the cached OIDC discovery document and JWKS
- Per-provider `http_client_options` block (`timeout`, `proxy`, `verify`)
forwarded to the underlying Guzzle HTTP client used by league/oauth2-client.
Closes the long-standing inability to bound HTTP requests to the IdP.

### Fixed

- Preserve original cause via `$previous` in `CliLoginHelper` and
`OpenIdLoginAuthenticator::validateClaims` exception wraps. Previously
the message was copied but the chain to the originating PSR cache or
upstream OIDC failure was lost, making logs harder to debug.

### Changed

- Mapped LoginController failures to 404 (unknown provider) or 503
(upstream/cache) instead of a generic 500; cause chained via `previous`
- Expanded README note on Symfony native OIDC support (7.3 features,
comparison table, link to upstream authorization-code-flow issue)
- Bumped actions/checkout from v5 to v6 in all GitHub workflows
- Renamed PHP_EXEC variable to PHP in Taskfile
- Added lint:composer task to Taskfile
- Improved test:coverage to enable XDEBUG_MODE and add text output
- Fixed test:matrix:reset to include CI profile when removing volumes
- Fixed test:run to remove stale composer.lock before updating dependencies

## [4.1.0] - 2026-03-20

### Added
Expand Down Expand Up @@ -123,7 +154,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`itk-dev/openid-connect` 1.0.0 to 2.1.0
- OpenId Connect Bundle: Added CLI login feature.

[unreleased]: https://github.com/itk-dev/openid-connect-bundle/compare/4.1.0...HEAD
[unreleased]: https://github.com/itk-dev/openid-connect-bundle/compare/4.2.0...HEAD
[4.2.0]: https://github.com/itk-dev/openid-connect-bundle/compare/4.1.0...4.2.0
[4.1.0]: https://github.com/itk-dev/openid-connect-bundle/compare/4.0.1...4.1.0
[4.0.1]: https://github.com/itk-dev/openid-connect-bundle/compare/4.0.0...4.0.1
[4.0.0]: https://github.com/itk-dev/openid-connect-bundle/compare/3.1.0...4.0.0
Expand Down
90 changes: 81 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Github](https://img.shields.io/badge/source-itk--dev/openid--connect--bundle-blue?style=flat-square)](https://github.com/itk-dev/openid-connect-bundle)
[![Release](https://img.shields.io/packagist/v/itk-dev/openid-connect-bundle.svg?style=flat-square&label=release)](https://packagist.org/packages/itk-dev/openid-connect-bundle)
[![PHP Version](https://img.shields.io/packagist/php-v/itk-dev/openid-connect-bundle.svg?style=flat-square&colorB=%238892BF)](https://www.php.net/downloads)
[![Build Status](https://img.shields.io/github/actions/workflow/status/itk-dev/openid-connect-bundle/pr.yaml?label=CI&logo=github&style=flat-square)](https://github.com/itk-dev/openid-connect-bundle/actions?query=workflow%3A%22Test+%26+Code+Style+Review%22)
[![Build Status](https://img.shields.io/github/actions/workflow/status/itk-dev/openid-connect-bundle/php.yaml?branch=develop&label=CI&logo=github&style=flat-square)](https://github.com/itk-dev/openid-connect-bundle/actions/workflows/php.yaml?query=branch%3Adevelop)
[![Codecov Code Coverage](https://img.shields.io/codecov/c/gh/itk-dev/openid-connect-bundle?label=codecov&logo=codecov&style=flat-square)](https://codecov.io/gh/itk-dev/openid-connect-bundle)
[![Read License](https://img.shields.io/packagist/l/itk-dev/openid-connect-bundle.svg?style=flat-square&colorB=darkcyan)](https://github.com/itk-dev/openid-connect-bundle/blob/master/LICENSE.md)
[![Package downloads on Packagist](https://img.shields.io/packagist/dt/itk-dev/openid-connect-bundle.svg?style=flat-square&colorB=darkmagenta)](https://packagist.org/packages/itk-dev/openid-connect-bundle/stats)
Expand All @@ -17,16 +17,48 @@ Symfony bundle for authorization via OpenID Connect.
> Since this bundle was created Symfony has added [support for OpenID Connect](https://symfony.com/blog/new-in-symfony-6-3-openid-connect-token-handler)
> as documented in ["Using OpenID Connect (OIDC)"](https://symfony.com/doc/current/security/access_token.html#using-openid-connect-oidc).
>
> As of Symfony 7.4 (March 2026), Symfony's native OIDC support has matured:
> Symfony's native OIDC support has improved significantly in recent releases:
>
> * [OIDC discovery](https://github.com/symfony/symfony/pull/54932) was added in Symfony 7.3, removing the need
> for manual keyset configuration.
> * Multiple providers are supported via multiple `base_uri` and `issuers` entries in the discovery config.
> * [OIDC discovery](https://github.com/symfony/symfony/pull/54932) was added in
> Symfony 7.3 (May 2025), removing the need for manual keyset configuration.
> Keys are fetched and cached automatically from the provider's
> `.well-known/openid-configuration` endpoint.
> * [OAuth2 Token Introspection](https://symfony.com/blog/new-in-symfony-7-3-security-improvements)
> (RFC 7662) support was added in Symfony 7.3, useful when access tokens are
> opaque (not JWTs).
> * [JWE (encrypted token) support](https://github.com/symfony/symfony/pull/57721)
> was added in Symfony 7.3 for OIDC token handlers.
>
> However, Symfony's native OIDC support is designed for **bearer token validation** (API authentication) only.
> It does not implement the **authorization code flow** (browser-based login with redirect to the IdP and callback
> handling), which is the primary use case of this bundle. If your application needs browser-based OIDC login,
> this bundle is still required.
> However, Symfony's native OIDC support is designed for **stateless bearer
> token validation** (the `access_token` authenticator) only. It validates tokens
> that are already present on the request (e.g. in an `Authorization: Bearer`
> header).
>
> It does **not** implement the **authorization code flow** — the browser-based
> login where the application redirects to the IdP, handles the callback with an
> authorization code, exchanges it for tokens, and establishes a session. This
> is tracked upstream in [symfony/symfony#50896](https://github.com/symfony/symfony/issues/50896).
>
> This means the following features of this bundle have no native Symfony
> equivalent:
>
> | Feature | This bundle | Symfony native |
> |--------------------------------|:-----------:|:--------------:|
> | Authorization code flow | ✅ | ❌ |
> | Session-based browser login | ✅ | ❌ |
> | Multiple named OIDC providers | ✅ | ❌ ¹ |
> | CLI login tokens | ✅ | ❌ |
> | OIDC discovery | ✅ | ✅ |
> | Bearer token validation (API) | ❌ | ✅ |
> | OAuth2 token introspection | ❌ | ✅ |
>
> ¹ Symfony's `access_token` handler accepts multiple `issuers` for token
> validation, but this is not the same as this bundle's named provider model
> with distinct client credentials, redirect URIs, and selectable login routes
> per provider.
>
> If your application needs browser-based OIDC login, this bundle is still
> required.

## Installation

Expand Down Expand Up @@ -76,6 +108,9 @@ itkdev_openid_connect:
# Optional: Specify leeway (seconds) to account for clock skew between provider and hosting
# Defaults to 10
leeway: '%env(int:ADMIN_OIDC_LEEWAY)%'
# Optional: Cache duration (seconds) for the OIDC discovery document and JWKS
# Defaults to 86400 (24 hours)
cache_duration: '%env(int:ADMIN_OIDC_CACHE_DURATION)%'
# Optional: Allow (non-secure) http requests (used for mocking a IdP). NOT RECOMMENDED FOR PRODUCTION.
# Defaults to false
allow_http: '%env(bool:ADMIN_OIDC_ALLOW_HTTP)%'
Expand All @@ -101,6 +136,7 @@ ADMIN_OIDC_CLIENT_ID=ADMIN_APP_CLIENT_ID
ADMIN_OIDC_CLIENT_SECRET=ADMIN_APP_CLIENT_SECRET
ADMIN_OIDC_REDIRECT_URI=ADMIN_APP_REDIRECT_URI
ADMIN_OIDC_LEEWAY=30
ADMIN_OIDC_CACHE_DURATION=86400
ADMIN_OIDC_ALLOW_HTTP=false

# "user" open id connect configuration variables
Expand All @@ -115,6 +151,42 @@ OIDC_CLI_LOGIN_ROUTE=OIDC_CLI_LOGIN_ROUTE

Set the actual values your `env.local` file to ensure they are not committed to Git.

#### 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.

```yaml
itkdev_openid_connect:
openid_providers:
user:
options:
# ... 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).
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)%"
# Describes the SSL certificate verification behavior of a request. (Default: true)
verify: true
```

The bundle accepts only `timeout`, `proxy`, and `verify` under
`http_client_options` — these are the keys `league/oauth2-client` forwards to
Guzzle (`verify` is consulted only when `proxy` is set). Any other key causes
an `InvalidConfigurationException` at container compile time.

> **Why Guzzle and not Symfony HttpClient?**
> `league/oauth2-client`, which the underlying `itk-dev/openid-connect`
> library extends, hard-types its HTTP client as `GuzzleHttp\ClientInterface`.
> Symfony HttpClient implements PSR-18 / HTTPlug, not Guzzle's interface, and
> no maintained adapter goes Symfony → Guzzle. Configure Guzzle via the
> options above; full transport replacement is not currently possible without
> a custom adapter we are not yet shipping.

In `/config/routes/` you need a similar `itkdev_openid_connect.yaml` file for
configuring the routing

Expand Down
27 changes: 18 additions & 9 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ version: "3"

vars:
DOCKER_COMPOSE: "docker compose"
PHP_EXEC: "{{.DOCKER_COMPOSE}} exec phpfpm"
COMPOSER: "{{.PHP_EXEC}} composer"
PHP: "{{.DOCKER_COMPOSE}} exec phpfpm"
COMPOSER: "{{.PHP}} composer"

tasks:
default:
Expand Down Expand Up @@ -74,7 +74,7 @@ tasks:
composer:check:
desc: Validate and audit composer
cmds:
- "{{.PHP_EXEC}} composer validate --strict"
- "{{.PHP}} composer validate --strict"
- "{{.COMPOSER}} normalize --dry-run"
- "{{.COMPOSER}} audit"

Expand All @@ -84,18 +84,26 @@ tasks:
desc: Run all linters
cmds:
- task: lint:php
- task: lint:composer
- task: lint:markdown
- task: lint:yaml

lint:php:
desc: Check PHP coding standards
cmds:
- "{{.PHP_EXEC}} vendor/bin/php-cs-fixer fix --dry-run --diff"
- "{{.PHP}} vendor/bin/php-cs-fixer fix --dry-run --diff"

lint:php:fix:
desc: Fix PHP coding standards
cmds:
- "{{.PHP_EXEC}} vendor/bin/php-cs-fixer fix"
- "{{.PHP}} vendor/bin/php-cs-fixer fix"

lint:composer:
desc: Validate and audit composer
cmds:
- "{{.PHP}} composer validate --strict"
- "{{.COMPOSER}} normalize --dry-run"
- "{{.COMPOSER}} audit"

lint:markdown:
desc: Lint markdown files
Expand All @@ -122,19 +130,19 @@ tasks:
analyze:php:
desc: Run PHPStan static analysis
cmds:
- "{{.PHP_EXEC}} vendor/bin/phpstan"
- "{{.PHP}} vendor/bin/phpstan"

# Testing

test:
desc: Run tests
cmds:
- "{{.PHP_EXEC}} vendor/bin/phpunit"
- "{{.PHP}} vendor/bin/phpunit"

test:coverage:
desc: Run tests with coverage
cmds:
- "{{.PHP_EXEC}} vendor/bin/phpunit --coverage-clover=coverage/unit.xml"
- "{{.DOCKER_COMPOSE}} exec -e XDEBUG_MODE=coverage phpfpm vendor/bin/phpunit --coverage-text --coverage-clover=coverage/unit.xml"

test:run:
desc: "Run tests for a PHP version and dependency set (e.g. task test:run PHP=8.4 DEPS=lowest)"
Expand All @@ -154,6 +162,7 @@ tasks:
cp /app/vendor/.composer.lock /app/composer.lock
composer install -q
else
rm -f /app/composer.lock
composer update -q --{{.PREFER}}
cp /app/composer.lock /app/vendor/.composer.lock
fi'
Expand All @@ -162,7 +171,7 @@ tasks:
test:matrix:reset:
desc: Remove cached vendor volumes to force a fresh dependency resolve
cmds:
- "{{.DOCKER_COMPOSE}} down --volumes"
- "{{.DOCKER_COMPOSE}} --profile ci down --volumes"

test:matrix:
desc: Run tests across all PHP versions (mirrors CI matrix)
Expand Down
Loading
Loading