Description
During the organization discovery login flow, if fail() is called from a conditional authentication script, EmailDomainValidationHandler [1] crashes with a NullPointerException instead of letting the script's failure propagate cleanly.
Root cause: EmailDomainValidationHandler.handle() reads the federated user's email claim from context.getProperty(FrameworkConstants.UNFILTERED_LOCAL_CLAIM_VALUES) [2]. This property is only populated on the success path (as part of JIT provisioning/claim mapping). When the conditional authentication script calls fail() inside a step's onSuccess callback, the sequence is marked as failed, and the handler responsible for populating UNFILTERED_LOCAL_CLAIM_VALUES skips its work; reasonably, since there's no need to provision/map claims for a user who is being denied.
However, EmailDomainValidationHandler still executes unconditionally as a registered post-authentication handler, with no check for a failed sequence and no null check on the returned map. It calls localClaimValues.get(FrameworkConstants.EMAIL_ADDRESS_CLAIM) directly, and since localClaimValues itself is null (not just missing the email key), this throws:
java.lang.NullPointerException: Cannot invoke "java.util.Map.get(Object)" because "localClaimValues" is null
at org.wso2.carbon.identity.organization.discovery.service.listener.EmailDomainValidationHandler.handle(EmailDomainValidationHandler.java:159)
at org.wso2.carbon.identity.application.authentication.framework.services.PostAuthenticationMgtService.executePostAuthnHandler(PostAuthenticationMgtService.java:119)
at org.wso2.carbon.identity.application.authentication.framework.services.PostAuthenticationMgtService.handlePostAuthentication(PostAuthenticationMgtService.java:85)
After removing the conditional authentication script, the sequence completes successfully, UNFILTERED_LOCAL_CLAIM_VALUES is present in the context's properties, localClaimValues resolves to the email address correctly, and the flow completes without error.
User-facing impact: the user never sees the script's intended access_denied / "Access not allowed" message. Instead they land on the generic retry.do error page ("Authentication Error! Something went wrong during the authentication process. Please try signing in again."), which is misleading; it looks like a broken login rather than an intentional access denial.
[1] - https://github.com/wso2-extensions/identity-organization-management/blob/main/components/org.wso2.carbon.identity.organization.discovery.service/src/main/java/org/wso2/carbon/identity/organization/discovery/service/listener/EmailDomainValidationHandler.java
[2] - https://github.com/wso2-extensions/identity-organization-management/blob/4c62c9e0356e4ccfca607554de544a69ac6c2e86/components/org.wso2.carbon.identity.organization.discovery.service/src/main/java/org/wso2/carbon/identity/organization/discovery/service/listener/EmailDomainValidationHandler.java#L148
Affected Component
org.wso2.carbon.identity.organization.discovery.service
Steps to Reproduce
- Add the following to
deployment.toml to allow conditional authentication scripts for applications in a sub-organization, then start the server:
[authentication.adaptive.shared_applications] enable=true
- Create an application and a sub-organization at the root level, and share the application with the sub-organization.
- Enable Organization Discovery and map a domain (e.g.
abc.com) to that sub-organization.
- Switch to the sub-organization and create a connection to another IS instance (running on port 9444) as an identity provider.
- In the IS instance on 9444, create a user with an email as the username, using a domain that matches the one mapped in step 3 i.e.
abc.com.
- Set this connection as the login option for step 1 of the application's sign-in flow.
- Also add the following conditional authentication script to the application at the sub-organization level:
var onLoginRequest = function(context) {
executeStep(1, {
onSuccess: function(context) {
var hasRole = hasAnyOfTheRolesV2(context, ['any role that is not assigned to the user']);
if (!hasRole) {
fail({'errorCode': 'access_denied', 'errorMessage': 'Access not allowed.'});
}
}
});
};
- Attempt to log in to the registered application: click Sign in with SSO → enter the email → authenticate with that IdP → observe the error.
Please select the area issue is related to
Other
Version
IS 7.2.0
Environment Details (with versions)
No response
Developer Checklist
Description
During the organization discovery login flow, if
fail()is called from a conditional authentication script,EmailDomainValidationHandler[1] crashes with aNullPointerExceptioninstead of letting the script's failure propagate cleanly.Root cause:
EmailDomainValidationHandler.handle()reads the federated user's email claim fromcontext.getProperty(FrameworkConstants.UNFILTERED_LOCAL_CLAIM_VALUES)[2]. This property is only populated on the success path (as part of JIT provisioning/claim mapping). When the conditional authentication script callsfail()inside a step'sonSuccesscallback, the sequence is marked as failed, and the handler responsible for populatingUNFILTERED_LOCAL_CLAIM_VALUESskips its work; reasonably, since there's no need to provision/map claims for a user who is being denied.However,
EmailDomainValidationHandlerstill executes unconditionally as a registered post-authentication handler, with no check for a failed sequence and no null check on the returned map. It callslocalClaimValues.get(FrameworkConstants.EMAIL_ADDRESS_CLAIM)directly, and sincelocalClaimValuesitself isnull(not just missing the email key), this throws:After removing the conditional authentication script, the sequence completes successfully,
UNFILTERED_LOCAL_CLAIM_VALUESis present in the context's properties,localClaimValuesresolves to the email address correctly, and the flow completes without error.User-facing impact: the user never sees the script's intended
access_denied/"Access not allowed"message. Instead they land on the genericretry.doerror page ("Authentication Error! Something went wrong during the authentication process. Please try signing in again."), which is misleading; it looks like a broken login rather than an intentional access denial.[1] - https://github.com/wso2-extensions/identity-organization-management/blob/main/components/org.wso2.carbon.identity.organization.discovery.service/src/main/java/org/wso2/carbon/identity/organization/discovery/service/listener/EmailDomainValidationHandler.java
[2] - https://github.com/wso2-extensions/identity-organization-management/blob/4c62c9e0356e4ccfca607554de544a69ac6c2e86/components/org.wso2.carbon.identity.organization.discovery.service/src/main/java/org/wso2/carbon/identity/organization/discovery/service/listener/EmailDomainValidationHandler.java#L148
Affected Component
org.wso2.carbon.identity.organization.discovery.serviceSteps to Reproduce
deployment.tomlto allow conditional authentication scripts for applications in a sub-organization, then start the server:abc.com) to that sub-organization.abc.com.Please select the area issue is related to
Other
Version
IS 7.2.0
Environment Details (with versions)
No response
Developer Checklist
impact/behavioral-changeadded7.2.0-migration)configadded