Conversation
Ports the provider from SocialiteProviders/Providers#1447 and adds multi-connection registration (one driver per config/oidc.php entry), per-IdP provider classes (entra, keycloak, auth0, okta, google), pluggable issuer validation with an Entra {tenantid} validator, and a full test suite (153 tests).
|
This looks great, thank you for working on it! One interesting issue I found with the Entra provider, based on my continued testing of the other PR: Unlike other providers where the I wonder if the Entra provider should use this field name, or if the general email field name should be configurable. Or perhaps an array of fields, and choose the first one that exists? (I know that the consuming application can check the raw user data for this other field name, but it seems a shame to not be able to use the built-in functionality when the only difference is in the name.) |
Entra returns the contact-info email in the email claim (often empty or unrelated to the account) and the login identity in preferred_username. Adds an email_claims config key (first non-empty claim wins); EntraProvider defaults it to preferred_username then email, skipping values that aren't email-shaped.
A token with a phone-shaped preferred_username and an attacker-chosen email claim would fall through to the unverified directory email (nOAuth). Default email_claims to preferred_username only; the fallback stays available as an opt-in.
Cross-checked against the test suite added to SocialiteProviders/Providers#1447: malformed token shapes, non-numeric exp, HS256 advertised via discovery, falsy-string verify_jwt, logout state and endpoint query edges, PKCE challenge derivation, and token response exposure.
adrum
left a comment
There was a problem hiding this comment.
Did an analysis of my other branch and found these discrepancies
|
|
||
| protected function getCacheTtl(): int | ||
| { | ||
| return (int) ($this->getConfig('cache_ttl') ?: 3600); |
There was a problem hiding this comment.
return (int) ($this->getConfig('cache_ttl') ?: 3600);Two separate collapses land on this line. ConfigTrait::getConfig() returns the default whenever the stored value is empty(), so 0, '0' and '' all arrive as null; the ?: then folds anything falsy into 3600 again. Setting cache_ttl to 0 to turn caching off while debugging an IdP still caches the discovery document and JWKS for an hour.
The fix is the helper this file already has — rawConfig() at line 111, which logoutTokenReplayTtl() already uses for exactly this reason:
protected function getCacheTtl(): int
{
$ttl = $this->rawConfig('cache_ttl');
return ($ttl === null || $ttl === '') ? 3600 : (int) $ttl;
}Treating '' as absent matters because an unset environment variable reads as '', which is absence rather than a deliberate 0. Worth applying the same !== '' guard at line 1128 in logoutTokenReplayTtl() for consistency.
- Restore JWT::$leeway after verification; the global static leaked this provider's skew into later validations in long-running workers. - Read cache_ttl via rawConfig() so an explicit 0 disables caching. - Keep a fragment on a discovered endpoint behind the query string. - Namespace the nonce session key to avoid colliding with the app's.
|
Thanks for the cross-check, all four were real. Fixed in ccd8f59, including the nonce rename as one commit with the tests. Went back over the rest with fresh eyes after this and found a few more in b98628e. Main one is key rotation for tokens with no 199 tests. If your analysis turned up anything else, send it through :) |
b9d8bfc to
3a4946b
Compare
Ports the provider from SocialiteProviders/Providers#1447 (thanks @adrum) into its own repo, so protocol and security fixes can release on their own cadence.
On top of the port:
config/oidc.phpregisters as its own driver (oidc_keycloak,oidc_entra, ...) with isolated config and caches. A plainservices.openidconnectblock still works for a single IdP.entra,keycloak,auth0,okta,google) that derive config from friendlier keys (tenant,realm,domain). AnyProvidersubclass can be named in config the same way.EntraIssuerValidatorfixes the multi-tenant{tenantid}issuer mismatch reported on the original PR.Docs are in the README plus
docs/for extending, the logout flows and the security model.