From 2535071cde661dade3fb94fc9e25323e46835108 Mon Sep 17 00:00:00 2001 From: Yasasr1 Date: Mon, 4 Nov 2024 10:19:22 +0530 Subject: [PATCH 1/2] Support org discovery in self-registration. --- .../login/OrganizationAuthenticator.java | 24 +++++++++++++++++++ .../constant/AuthenticatorConstants.java | 2 ++ 2 files changed, 26 insertions(+) diff --git a/components/org.wso2.carbon.identity.application.authenticator.organization.login/src/main/java/org/wso2/carbon/identity/application/authenticator/organization/login/OrganizationAuthenticator.java b/components/org.wso2.carbon.identity.application.authenticator.organization.login/src/main/java/org/wso2/carbon/identity/application/authenticator/organization/login/OrganizationAuthenticator.java index 801672c..1f9ba06 100644 --- a/components/org.wso2.carbon.identity.application.authenticator.organization.login/src/main/java/org/wso2/carbon/identity/application/authenticator/organization/login/OrganizationAuthenticator.java +++ b/components/org.wso2.carbon.identity.application.authenticator.organization.login/src/main/java/org/wso2/carbon/identity/application/authenticator/organization/login/OrganizationAuthenticator.java @@ -129,10 +129,12 @@ import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.REQUEST_ORG_PAGE_URL; import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.REQUEST_ORG_PAGE_URL_CONFIG; import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.REQUEST_ORG_SELECT_PAGE_URL; +import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.SELF_REGISTRATION_PARAMETER; import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.SP_ID_PARAMETER; import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.TOKEN_ENDPOINT_ORGANIZATION_PATH; import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.USERINFO_ENDPOINT_ORGANIZATION_PATH; import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.USERINFO_URL; +import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.USERNAME_PARAMETER; import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.USER_ORGANIZATION_CLAIM; import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.OAuth2.CALLBACK_URL; import static org.wso2.carbon.identity.organization.config.service.constant.OrganizationConfigConstants.ErrorMessages.ERROR_CODE_DISCOVERY_CONFIG_NOT_EXIST; @@ -407,6 +409,10 @@ public AuthenticatorFlowStatus process(HttpServletRequest request, HttpServletRe return super.process(request, response, context); } + if (request.getParameter(SELF_REGISTRATION_PARAMETER) != null) { + context.setProperty(SELF_REGISTRATION_PARAMETER, request.getParameter(SELF_REGISTRATION_PARAMETER)); + } + /** * First priority for organization Id. * Check for the organization Id in the request attribute first since the organization Id is set in the @@ -672,6 +678,11 @@ private void redirectToOrgDiscoveryInputCapture(HttpServletResponse response, Au .append(urlEncode((String) context.getProperties().get(ORGANIZATION_LOGIN_FAILURE))); } + if (context.getProperty(SELF_REGISTRATION_PARAMETER) != null) { + addQueryParam(queryStringBuilder, SELF_REGISTRATION_PARAMETER, + (String) context.getProperty(SELF_REGISTRATION_PARAMETER)); + } + String url; if (redirectToOrgNameCapture) { url = FrameworkUtils.appendQueryParamsStringToUrl(getOrganizationRequestPageUrl(context), @@ -712,6 +723,19 @@ private String getQueryParams(AuthenticationContext context, ClaimMapping[] clai paramBuilder.append(AMPERSAND_SIGN).append(Constants.RESPONSE_MODE).append(EQUAL_SIGN) .append(Constants.DIRECT); } + + if (context.getProperty(SELF_REGISTRATION_PARAMETER) != null) { + paramBuilder.append(AMPERSAND_SIGN).append(SELF_REGISTRATION_PARAMETER).append(EQUAL_SIGN) + .append(context.getProperty(SELF_REGISTRATION_PARAMETER)); + + // Used to auto complete the username in self-registration page. + if (context.getProperty(ORG_DISCOVERY_PARAMETER) != null && + EMAIL_DOMAIN_DISCOVERY_TYPE.equals(context.getProperty(ORGANIZATION_DISCOVERY_TYPE))) { + paramBuilder.append(AMPERSAND_SIGN).append(USERNAME_PARAMETER).append(EQUAL_SIGN) + .append(context.getProperty(ORG_DISCOVERY_PARAMETER)); + } + } + return paramBuilder.toString(); } diff --git a/components/org.wso2.carbon.identity.application.authenticator.organization.login/src/main/java/org/wso2/carbon/identity/application/authenticator/organization/login/constant/AuthenticatorConstants.java b/components/org.wso2.carbon.identity.application.authenticator.organization.login/src/main/java/org/wso2/carbon/identity/application/authenticator/organization/login/constant/AuthenticatorConstants.java index f263719..59e3a72 100644 --- a/components/org.wso2.carbon.identity.application.authenticator.organization.login/src/main/java/org/wso2/carbon/identity/application/authenticator/organization/login/constant/AuthenticatorConstants.java +++ b/components/org.wso2.carbon.identity.application.authenticator.organization.login/src/main/java/org/wso2/carbon/identity/application/authenticator/organization/login/constant/AuthenticatorConstants.java @@ -49,6 +49,8 @@ private AuthenticatorConstants() { public static final String ORG_DISCOVERY_ENABLED_PARAMETER = "orgDiscoveryEnabled"; public static final String ORG_DISCOVERY_TYPE_PARAMETER = "orgDiscoveryType"; public static final String PROMPT_PARAMETER = "prompt"; + public static final String SELF_REGISTRATION_PARAMETER = "isSelfRegistration"; + public static final String USERNAME_PARAMETER = "discoveredUsername"; public static final String ORGANIZATION_DISCOVERY_TYPE = "discoveryType"; public static final String ORGANIZATION_NAME = "orgName"; public static final String ENABLE_CONFIG = ".enable"; From 409aa2fee535ef84d176d83ff5e960684ed31859 Mon Sep 17 00:00:00 2001 From: Yasasr1 Date: Thu, 28 Nov 2024 10:16:22 +0530 Subject: [PATCH 2/2] Add unit tests. --- .../login/OrganizationAuthenticatorTest.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/components/org.wso2.carbon.identity.application.authenticator.organization.login/src/test/java/org/wso2/carbon/identity/application/authenticator/organization/login/OrganizationAuthenticatorTest.java b/components/org.wso2.carbon.identity.application.authenticator.organization.login/src/test/java/org/wso2/carbon/identity/application/authenticator/organization/login/OrganizationAuthenticatorTest.java index fb2ff19..458e0ae 100644 --- a/components/org.wso2.carbon.identity.application.authenticator.organization.login/src/test/java/org/wso2/carbon/identity/application/authenticator/organization/login/OrganizationAuthenticatorTest.java +++ b/components/org.wso2.carbon.identity.application.authenticator.organization.login/src/test/java/org/wso2/carbon/identity/application/authenticator/organization/login/OrganizationAuthenticatorTest.java @@ -91,10 +91,13 @@ import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.INBOUND_AUTH_TYPE_OAUTH; import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.LOGIN_HINT_PARAMETER; import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.OIDC_CLAIM_DIALECT_URL; +import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.ORGANIZATION_DISCOVERY_TYPE; +import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.ORG_DISCOVERY_PARAMETER; import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.ORG_DISCOVERY_TYPE_PARAMETER; import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.ORG_ID_PARAMETER; import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.ORG_PARAMETER; import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.SAML_RESP; +import static org.wso2.carbon.identity.application.authenticator.organization.login.constant.AuthenticatorConstants.SELF_REGISTRATION_PARAMETER; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_APPLICATION_NOT_SHARED; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_INVALID_APPLICATION; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_INVALID_ORGANIZATION_ID; @@ -385,6 +388,61 @@ public void testProcessWithValidOrgIdParamSet() throws Exception { Assert.assertEquals(status, AuthenticatorFlowStatus.INCOMPLETE); } + @Test + public void testProcessWithSelfRegParam() throws Exception { + + when(mockServletRequest.getParameter(SELF_REGISTRATION_PARAMETER)).thenReturn("true"); + when(mockAuthenticationContext.getContextIdentifier()).thenReturn(contextIdentifier); + when(mockAuthenticationContext.getExternalIdP()).thenReturn(mockExternalIdPConfig); + when(mockExternalIdPConfig.getName()).thenReturn(AUTHENTICATOR_FRIENDLY_NAME); + when(mockAuthenticationContext.getServiceProviderResourceId()).thenReturn(saasAppResourceId); + when(authenticatorDataHolder.getOrganizationConfigManager().getDiscoveryConfiguration()) + .thenReturn(mockDiscoveryConfig); + when(mockAuthenticationContext.getProperty(SELF_REGISTRATION_PARAMETER)).thenReturn("true"); + AuthenticatorFlowStatus status = organizationAuthenticator.process(mockServletRequest, mockServletResponse, + mockAuthenticationContext); + Assert.assertEquals(status, AuthenticatorFlowStatus.INCOMPLETE); + } + + @Test + public void testProcessWithSelfRegContext() throws Exception { + + setMockContextParamForValidOrganization(); + when(mockAuthenticationContext.getAuthenticatorProperties()).thenReturn(authenticatorProperties); + when(mockAuthenticationContext.getServiceProviderName()).thenReturn(saasApp); + when(mockAuthenticationContext.getTenantDomain()).thenReturn(saasAppOwnedTenant); + when(authenticatorDataHolder.getOrganizationManager().resolveOrganizationId(anyString())) + .thenReturn(saasAppOwnedOrgId); + when(authenticatorDataHolder.getOrganizationManager().resolveTenantDomain(anyString())).thenReturn( + orgId); + when(authenticatorDataHolder.getOrgApplicationManager() + .resolveSharedApplication(anyString(), anyString(), anyString())).thenReturn(mockServiceProvider); + + List claims = new ArrayList<>(); + claims.add(new Claim(OIDC_CLAIM_DIALECT_URL, "custom", null)); + when(authenticatorDataHolder.getClaimMetadataManagementService().getMappedExternalClaimsForLocalClaim( + anyString(), anyString())).thenReturn(claims); + when(mockServiceProvider.getInboundAuthenticationConfig()).thenReturn(mockInboundAuthenticationConfig); + when(mockServiceProvider.getClaimConfig()).thenReturn(mockClaimConfig); + + InboundAuthenticationRequestConfig inbound = new InboundAuthenticationRequestConfig(); + inbound.setInboundAuthType(INBOUND_AUTH_TYPE_OAUTH); + inbound.setInboundAuthKey(clientId); + InboundAuthenticationRequestConfig[] inbounds = {inbound}; + when(mockInboundAuthenticationConfig.getInboundAuthenticationRequestConfigs()).thenReturn(inbounds); + + when(authenticatorDataHolder.getOAuthAdminService().getOAuthApplicationData(anyString(), anyString())) + .thenReturn(mockOAuthConsumerAppDTO); + when(mockOAuthConsumerAppDTO.getOauthConsumerSecret()).thenReturn(secretKey); + + when(mockAuthenticationContext.getProperty(SELF_REGISTRATION_PARAMETER)).thenReturn("true"); + when(mockAuthenticationContext.getProperty(ORG_DISCOVERY_PARAMETER)).thenReturn(userEmailWithValidDomain); + when(mockAuthenticationContext.getProperty(ORGANIZATION_DISCOVERY_TYPE)).thenReturn(emailDomainDiscoveryType); + AuthenticatorFlowStatus status = organizationAuthenticator.process(mockServletRequest, mockServletResponse, + mockAuthenticationContext); + Assert.assertEquals(status, AuthenticatorFlowStatus.INCOMPLETE); + } + @DataProvider(name = "testProcessWithSharedAppPublicClientStatusData") public Object[][] testProcessWithSharedAppPublicClientStatusData() {