[FIX] OIDC: Explicitly request email claim in ID token to comply with OpenID Connect spec#3285
[FIX] OIDC: Explicitly request email claim in ID token to comply with OpenID Connect spec#3285kvizillon wants to merge 1 commit intoLeantime:masterfrom
Conversation
… OpenID Connect spec ### Description This pull request adds the `claims` parameter to the OIDC authorization request to explicitly request the `email` claim to be included in the ID Token. ### Background & Problem Currently, Leantime attempts to read user claims (like `email`) directly from the ID Token. According to the **OpenID Connect Core 1.0 specification**, an ID Token is primarily for authentication and contains only a minimal set of claims (such as `iss`, `sub`, `aud`, `exp`, `iat`). It is not required, nor guaranteed, to contain any user claims like `email` or `name`. The specification states that user claims should be obtained from the **UserInfo Endpoint** using the Access Token. However, Leantime's current OIDC implementation does not call the UserInfo endpoint if an ID Token is present, leading to authentication failures when the Identity Provider (IdP) does not include these claims in the ID Token by default. Many IdPs (like Google) include email as a pragmatic measure, but strictly compliant IdPs (like SimpleSAMLphp with the OIDC module) follow the specification and do not include them, causing Leantime to fail with errors like `Unable to read email to log you in`. ### The Fix This PR implements the correct OIDC flow for requesting claims. As per [**OpenID Connect Core 1.0, Section 5.5.1**](https://openid.net/specs/openid-connect-core-1_0.html#IndividualClaimsRequests), a Client can request specific claims to be returned in the ID Token using the `claims` request parameter. By adding: ```php 'claims' => json_encode(['id_token' => ['email' => ['essential' => true]]]) to the authorization request, Leantime explicitly signals to the IdP that the email claim is essential and should be included in the ID Token. This ensures the IdP includes it, making the authentication flow work with all compliant providers without changing Leantime's core logic of reading the ID Token. Changes Made Modified buildLoginUrl() in Oidc.php to add the claims parameter to the authorization URL. The parameter requests the email claim as essential for the ID Token. Impact Fixes authentication for strictly compliant OpenID Connect Providers (e.g., SimpleSAMLphp). Maintains backward compatibility with providers that already include claims in the ID Token. Brings Leantime's OIDC implementation one step closer to full specification compliance without a major rewrite. Related Issue This addresses a common problem where users integrating Leantime with standard OIDC providers encounter email retrieval errors.
|
Thank you! |
There was a problem hiding this comment.
Pull request overview
This PR updates Leantime’s OIDC authorization URL construction to explicitly request the email claim in the ID Token via the OpenID Connect claims parameter, aiming to improve compatibility with spec-compliant IdPs that don’t include user claims by default.
Changes:
- Add a
claimsparameter to the OIDC authorization request. - Request
emailas an essential claim in theid_token.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 'id_token' => [ | ||
| 'email' => ['essential' => true] | ||
| ] |
There was a problem hiding this comment.
The claims request hard-codes email as an essential ID-token claim, but the login flow actually reads the username from the configurable $this->fieldEmail (which can be changed to a different claim like preferred_username/upn). Marking email as essential can cause otherwise-working IdPs/configs to fail the auth request if they can’t provide an email. Consider only requesting email when $this->fieldEmail === 'email', or deriving the requested claim from $this->fieldEmail when it’s a simple (non-dotted) claim name, and not marking it essential otherwise.
| 'claims' => json_encode([ | ||
| 'id_token' => [ | ||
| 'email' => ['essential' => true] | ||
| ] | ||
| ]), |
There was a problem hiding this comment.
json_encode() can return false (e.g., on encoding errors) and this would silently produce an empty/invalid claims parameter in the authorization URL. Consider encoding with JSON_THROW_ON_ERROR and handling the exception (or otherwise checking json_last_error()) so failures are explicit and easier to diagnose.
|
Can you review the comments and see if you can find a more flexible solution for the email claim? |
Description
This pull request adds the
claimsparameter to the OIDC authorization request to explicitly request theemailclaim to be included in the ID Token.Background & Problem
Currently, Leantime attempts to read user claims (like
email) directly from the ID Token. According to the OpenID Connect Core 1.0 specification, an ID Token is primarily for authentication and contains only a minimal set of claims (such asiss,sub,aud,exp,iat). It is not required, nor guaranteed, to contain any user claims likeemailorname.The specification states that user claims should be obtained from the UserInfo Endpoint using the Access Token. However, Leantime's current OIDC implementation does not call the UserInfo endpoint if an ID Token is present, leading to authentication failures when the Identity Provider (IdP) does not include these claims in the ID Token by default.
From the OpenID Connect Core 1.0 specification:
Many IdPs (like Google) include email as a pragmatic measure, but strictly compliant IdPs (like SimpleSAMLphp with the OIDC module) follow the specification and do not include them, causing Leantime to fail with errors like
Unable to read email to log you in.The Fix
This PR implements the correct OIDC flow for requesting claims. As per the specification, a Client can request specific claims to be returned in the ID Token using the
claimsrequest parameter.By adding this to the authorization request:
Leantime explicitly signals to the IdP that the email claim is essential and should be included in the ID Token. This ensures the IdP includes it, making the authentication flow work with all compliant providers without changing Leantime's core logic of reading the ID Token.
Changes Made
Modified buildLoginUrl() in app/Domain/Oidc/Services/Oidc.php to add the claims parameter to the authorization URL.
The parameter requests the email claim as essential for the ID Token.
Code Changes
Impact
Fixes authentication for strictly compliant OpenID Connect Providers (e.g., SimpleSAMLphp, Keycloak, etc.)
Maintains backward compatibility with providers that already include claims in the ID Token
Brings Leantime's OIDC implementation one step closer to full specification compliance without a major rewrite
No breaking changes for existing installations
Related Issues
This addresses a common problem where users integrating Leantime with standard OIDC providers encounter email retrieval errors. Similar issues have been reported in various integration scenarios.
How Has This Been Tested?
Tested with SimpleSAMLphp OIDC module (strictly compliant provider)
Verified that email is properly extracted from ID Token
Confirmed backward compatibility with existing OIDC providers
References
OpenID Connect Core 1.0, Section 2 - ID Token
OpenID Connect Core 1.0, Section 5.5.1 - Individual Claims Requests
OpenID Connect Core 1.0, Section 5.3 - UserInfo Endpoint
Additional Notes
This change follows the principle of "explicit over implicit" in OIDC. By explicitly requesting the email claim for the ID Token, Leantime becomes more robust and compatible with a wider range of OpenID Connect Providers while maintaining the same user experience.