Bug: “invalid-iss” error
-
The
get_issuer_from_endpoint()function incorrectly extracts the issuer URL by only usingscheme://host, ignoring the subdirectory path. This causes JWT validation to fail when the Identity Provider’s issuer includes a subdirectory (e.g.,https://example.com/central).
## Environment
– **Plugin Version:** 3.11.2
– **WordPress Version:** 6.9.1
– **PHP Version:** 8.3
– **Identity Provider:** Custom OAuth server (WHMCS-based)
## Steps to Reproduce
1. Configure the plugin with an Identity Provider that has endpoints in a subdirectory:
– Authorization Endpoint:https://example.com/central/oauth/authorize.php
– Token Endpoint:https://example.com/central/oauth/token.php
– JWKS Endpoint:https://example.com/central/oauth/certs.php
2. The Identity Provider returns JWT tokens withissclaim:
json<br> {<br> "iss": "https://example.com/central",<br> ...<br> }<br>
3. Attempt to authenticate via OpenID Connect
4. **Result:** Authentication fails with error:
<br> ERROR (invalid-iss): Token issuer does not match expected issuer.<br>
## Root Cause Analysis
Theget_issuer_from_endpoint()function inincludes/openid-connect-generic-client.phponly extractsscheme://hostfrom the endpoint URL:php<br>public function get_issuer_from_endpoint( $endpoint_url ) {<br> $parsed = wp_parse_url( $endpoint_url );<br> <br> // ...<br> <br> $issuer = $parsed['scheme'] . '://' . $parsed['host']; // ❌ BUG HERE<br> <br> // ...<br> <br> return $issuer;<br>}<br>
**Debug logs show the mismatch:**<br>Endpoint URL received: https://example.com/central/oauth/authorize.php<br>Issuer calculated: https://example.com/central ❌ (missing /central)<br>Issuer in Token: https://example.com/central ✅<br>
The function returnshttps://example.cominstead ofhttps://example.com/central, causing the validation to fail.
## Proposed Fix
Modify theget_issuer_from_endpoint()function to extract the base path from the endpoint URL:php<br>public function get_issuer_from_endpoint( $endpoint_url ) {<br> $parsed = wp_parse_url( $endpoint_url );<br><br> if ( ! $parsed || ! isset( $parsed['scheme'] ) || ! isset( $parsed['host'] ) ) {<br> return $endpoint_url;<br> }<br><br> $issuer = $parsed['scheme'] . '://' . $parsed['host'];<br><br> // Add port if non-standard.<br> if ( isset( $parsed['port'] ) ) {<br> $default_ports = array(<br> 'http' => 80,<br> 'https' => 443,<br> );<br> if ( ! isset( $default_ports[ $parsed['scheme'] ] ) || $parsed['port'] != $default_ports[ $parsed['scheme'] ] ) {<br> $issuer .= ':' . $parsed['port'];<br> }<br> }<br><br> // === FIX: Include base path in issuer ===<br> if ( ! empty( $parsed['path'] ) ) {<br> // Remove the endpoint filename (e.g., authorize.php)<br> $path = dirname( $parsed['path'] );<br> <br> // If there's a parent directory beyond root (e.g., /central/oauth -> /central)<br> if ( $path !== '/' && $path !== '.' ) {<br> // Go up one level to get the base path<br> $base_path = dirname( $path );<br> if ( $base_path !== '/' && $base_path !== '.' ) {<br> $issuer .= $base_path;<br> }<br> }<br> }<br><br> return $issuer;<br>}<br>
## Alternative Approaches
### Option A: Use OpenID Discovery (Preferred)
If the Identity Provider provides a/.well-known/openid-configurationendpoint, the issuer should be fetched from there rather than extracted from the URL.
### Option B: Add Manual Issuer Configuration
Allow users to manually specify the expected issuer in the plugin settings when automatic detection fails.
### Option C: Usertrim()Comparison (Partial Fix – Already Merged)
The recent commit7c9d659addedrtrim()to handle trailing slash differences, but this doesn’t solve the subdirectory path issue:php<br>if ( rtrim( $id_token_claim['iss'], '/' ) !== rtrim( $expected_issuer, '/' ) ) {<br>
## Impact
This bug affects all users whose Identity Provider:
– Uses a subdirectory path (e.g.,/central,/idp,/auth)
– Returns an issuer claim that includes the subdirectory path
Common affected scenarios:
– Self-hosted OAuth servers (WHMCS, Keycloak with context path, etc.)
– Identity Providers behind reverse proxies with path-based routing
– Multi-tenant OAuth servers
## Related
– Commit7c9d65929fabb4fb71590f702d85ff208519443d– Fixed trailing slash comparison
– Issue #629 – Related issuer validation improvements
Thank you for maintaining this excellent plugin! Please let me know if you need any additional information or testing assistance.
The topic ‘Bug: “invalid-iss” error’ is closed to new replies.