diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/pom.xml b/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/pom.xml index ff299d41..8b3b6608 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/pom.xml +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/pom.xml @@ -194,6 +194,18 @@ org.jacoco jacoco-maven-plugin + + org.apache.maven.plugins + maven-surefire-plugin + + + src/test/resources/testng.xml + + + org.ops4j.pax.logging + + + diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/analytics/CallAnalyticsFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/analytics/CallAnalyticsFunctionImpl.java index ad763d20..cba1246c 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/analytics/CallAnalyticsFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/analytics/CallAnalyticsFunctionImpl.java @@ -28,6 +28,7 @@ import org.apache.http.entity.StringEntity; import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; import org.apache.http.util.EntityUtils; +import org.graalvm.polyglot.HostAccess; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; @@ -41,6 +42,7 @@ import java.net.SocketTimeoutException; import java.net.URL; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -60,14 +62,23 @@ public class CallAnalyticsFunctionImpl extends AbstractAnalyticsFunction impleme private static final String PARAM_INPUT_STREAM = "InputStream"; @Override + @HostAccess.Export public void callAnalytics(Map metadata, Map payloadData, Map eventHandlers) { + /* + * Here, we need to clone the parameters since, even though we're accessing the parameters as Map objects, + * these may be instances of child classes of Map class (Script Engine specific implementations). + * When the AsyncProcess is executed, the objects will not be available if the relevant Script Engine is closed. + * Eg: Polyglot Map (Map implementation from GraalJS) will be unavailable when the Polyglot Context is closed. + */ + Map metadataMap = new HashMap<>(metadata); + Map payloadDataMap = new HashMap<>(payloadData); AsyncProcess asyncProcess = new AsyncProcess((authenticationContext, asyncReturn) -> { - String appName = metadata.get(PARAM_APP_NAME); - String inputStream = metadata.get(PARAM_INPUT_STREAM); - String receiverUrl = metadata.get(PARAM_EP_URL); + String appName = metadataMap.get(PARAM_APP_NAME); + String inputStream = metadataMap.get(PARAM_INPUT_STREAM); + String receiverUrl = metadataMap.get(PARAM_EP_URL); String targetPath; try { if (appName != null && inputStream != null) { @@ -92,7 +103,7 @@ public void callAnalytics(Map metadata, JSONObject jsonObject = new JSONObject(); JSONObject event = new JSONObject(); - for (Map.Entry dataElements : payloadData.entrySet()) { + for (Map.Entry dataElements : payloadDataMap.entrySet()) { event.put(dataElements.getKey(), dataElements.getValue()); } jsonObject.put("event", event); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/analytics/PublishToAnalyticsFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/analytics/PublishToAnalyticsFunctionImpl.java index 4b9cd877..439e24f7 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/analytics/PublishToAnalyticsFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/analytics/PublishToAnalyticsFunctionImpl.java @@ -26,6 +26,7 @@ import org.apache.http.concurrent.FutureCallback; import org.apache.http.entity.StringEntity; import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; +import org.graalvm.polyglot.HostAccess; import org.json.simple.JSONObject; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; @@ -34,6 +35,7 @@ import java.io.IOException; import java.net.URL; +import java.util.HashMap; import java.util.Map; import static org.apache.http.HttpHeaders.CONTENT_TYPE; @@ -48,12 +50,23 @@ public class PublishToAnalyticsFunctionImpl extends AbstractAnalyticsFunction im private static final String PARAM_INPUT_STREAM = "InputStream"; @Override + @HostAccess.Export public void publishToAnalytics(Map metadata, Map payloadData, JsAuthenticationContext context) { - String appName = metadata.get(PARAM_APP_NAME); - String inputStream = metadata.get(PARAM_INPUT_STREAM); - String targetPath = metadata.get(PARAM_EP_URL); + /* + * Here, we need to clone the parameters since, even though we're accessing the parameters as Map objects, + * these may be instances of child classes of Map class (Script Engine specific implementations). + * When the AsyncProcess is executed, the objects will not be available if the relevant Script Engine is closed. + * Eg: Polyglot Map (Map implementation from GraalJS) will be unavailable when the Polyglot Context is closed. + */ + Map metadataMap = new HashMap<>(metadata); + Map payloadDataMap = new HashMap<>(payloadData); + String contextIdentifier = context.getWrapped().getContextIdentifier(); + + String appName = metadataMap.get(PARAM_APP_NAME); + String inputStream = metadataMap.get(PARAM_INPUT_STREAM); + String targetPath = metadataMap.get(PARAM_EP_URL); String epUrl = null; try { if (appName != null && inputStream != null) { @@ -64,7 +77,7 @@ public void publishToAnalytics(Map metadata, Map LOG.error("Target path cannot be found."); return; } - String tenantDomain = context.getContext().getTenantDomain(); + String tenantDomain = context.getWrapped().getTenantDomain(); String targetHostUrl = CommonUtils.getConnectorConfig(AnalyticsEngineConfigImpl.RECEIVER, tenantDomain); if (targetHostUrl == null) { LOG.error("Target host cannot be found."); @@ -78,7 +91,7 @@ public void publishToAnalytics(Map metadata, Map JSONObject jsonObject = new JSONObject(); JSONObject event = new JSONObject(); - for (Map.Entry dataElements : payloadData.entrySet()) { + for (Map.Entry dataElements : payloadDataMap.entrySet()) { event.put(dataElements.getKey(), dataElements.getValue()); } jsonObject.put("event", event); @@ -105,11 +118,11 @@ public void completed(final HttpResponse response) { if (responseCode == 200) { if (LOG.isDebugEnabled()) { LOG.debug("Successfully published data to the analytics for session data key: " + - context.getContext().getContextIdentifier()); + contextIdentifier); } } else { LOG.error("Error while publishing data to analytics engine for session data key: " + - context.getContext().getContextIdentifier() + ". Request completed successfully. " + + contextIdentifier + ". Request completed successfully. " + "But response code was not 200"); } } @@ -118,25 +131,25 @@ public void completed(final HttpResponse response) { public void failed(final Exception ex) { LOG.error("Error while publishing data to analytics engine for session data key: " + - context.getContext().getContextIdentifier() + ". Request failed with: " + ex); + contextIdentifier + ". Request failed with: " + ex); } @Override public void cancelled() { LOG.error("Error while publishing data to analytics engine for session data key: " + - context.getContext().getContextIdentifier() + ". Request canceled."); + contextIdentifier + ". Request canceled."); } }); } } catch (IOException e) { - LOG.error("Error while calling analytics engine for tenant: " + context.getContext().getTenantDomain(), e); + LOG.error("Error while calling analytics engine for tenant: " + context.getWrapped().getTenantDomain(), e); } catch (IdentityEventException e) { - LOG.error("Error while preparing authentication information for tenant: " + context.getContext() + LOG.error("Error while preparing authentication information for tenant: " + context.getWrapped() .getTenantDomain(), e); } catch (FrameworkException e) { - LOG.error("Error while building client to invoke analytics engine for tenant: " + context.getContext() + LOG.error("Error while building client to invoke analytics engine for tenant: " + context.getWrapped() .getTenantDomain(), e); } } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/analytics/CallAnalyticsFunctionImplTest.java b/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/analytics/CallAnalyticsFunctionImplTest.java index 6049264c..f5b1856c 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/analytics/CallAnalyticsFunctionImplTest.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/analytics/CallAnalyticsFunctionImplTest.java @@ -74,8 +74,6 @@ public class CallAnalyticsFunctionImplTest extends JsSequenceHandlerAbstractTest @BeforeMethod protected void setUp() throws Exception { - super.setUp(); - CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME = true; sequenceHandlerRunner.registerJsFunction("callAnalytics", new CallAnalyticsFunctionImpl()); UserRealm userRealm = realmService.getTenantUserRealm(-1234); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/test/resources/testng.xml b/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/test/resources/testng.xml new file mode 100644 index 00000000..496f993e --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.analytics/src/test/resources/testng.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.choreo/pom.xml b/components/org.wso2.carbon.identity.conditional.auth.functions.choreo/pom.xml index f1ce892b..762ca256 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.choreo/pom.xml +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.choreo/pom.xml @@ -234,6 +234,18 @@ org.jacoco jacoco-maven-plugin + + org.apache.maven.plugins + maven-surefire-plugin + + + src/test/resources/testng.xml + + + org.ops4j.pax.logging + + + diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.choreo/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/choreo/CallChoreoFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.choreo/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/choreo/CallChoreoFunctionImpl.java index c6a42466..ff31ec38 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.choreo/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/choreo/CallChoreoFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.choreo/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/choreo/CallChoreoFunctionImpl.java @@ -34,6 +34,7 @@ import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; +import org.graalvm.polyglot.HostAccess; import org.json.simple.JSONObject; import org.wso2.carbon.identity.application.authentication.framework.AsyncProcess; import org.wso2.carbon.identity.application.authentication.framework.AsyncReturn; @@ -63,6 +64,7 @@ import java.util.Base64; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -122,13 +124,22 @@ public CallChoreoFunctionImpl() { } @Override + @HostAccess.Export public void callChoreo(Map connectionMetaData, Map payloadData, Map eventHandlers) { + /* + * Here, we need to clone the parameters since, even though we're accessing the parameters as Map objects, + * these may be instances of child classes of Map class (Script Engine specific implementations). + * When the AsyncProcess is executed, the objects will not be available if the relevant Script Engine is closed. + * Eg: Polyglot Map (Map implementation from GraalJS) will be unavailable when the Polyglot Context is closed. + */ + Map connectionMetaDataMap = new HashMap<>(connectionMetaData); + Map payloadDataMap = new HashMap<>(payloadData); AsyncProcess asyncProcess = new AsyncProcess((authenticationContext, asyncReturn) -> { LOG.info("Starting the callChoreo function for session data key: " + authenticationContext.getContextIdentifier()); - String epUrl = connectionMetaData.get(URL_VARIABLE_NAME); + String epUrl = connectionMetaDataMap.get(URL_VARIABLE_NAME); try { if (!isValidChoreoDomain(epUrl)) { LOG.error("Provided Url does not contain a configured choreo domain. Invalid Url: " + epUrl); @@ -138,7 +149,7 @@ public void callChoreo(Map connectionMetaData, Map + + + + + + + + + + + + + + + + + diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.elk/pom.xml b/components/org.wso2.carbon.identity.conditional.auth.functions.elk/pom.xml index c8aba460..b1ca4e4d 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.elk/pom.xml +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.elk/pom.xml @@ -161,6 +161,18 @@ org.jacoco jacoco-maven-plugin + + org.apache.maven.plugins + maven-surefire-plugin + + + src/test/resources/testng.xml + + + org.ops4j.pax.logging + + + diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.elk/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/elk/CallElasticFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.elk/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/elk/CallElasticFunctionImpl.java index 582e22cf..c6b42b66 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.elk/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/elk/CallElasticFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.elk/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/elk/CallElasticFunctionImpl.java @@ -28,6 +28,7 @@ import org.apache.http.entity.StringEntity; import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; import org.apache.http.util.EntityUtils; +import org.graalvm.polyglot.HostAccess; import org.json.JSONException; import org.json.JSONObject; import org.wso2.carbon.identity.application.authentication.framework.AsyncProcess; @@ -66,8 +67,10 @@ public CallElasticFunctionImpl() { } @Override + @HostAccess.Export public void callElastic(Map params, Map eventHandlers) { + Map paramsMap = new HashMap<>(params); AsyncProcess asyncProcess = new AsyncProcess((authenticationContext, asyncReturn) -> { try { @@ -78,13 +81,13 @@ public void callElastic(Map params, Map eventHan throw new FrameworkException("Elasticsearch host cannot be found."); } - HttpPost request = new HttpPost(elasticConfigProvider.getElasticSearchUrl(targetHostUrl,params)); + HttpPost request = new HttpPost(elasticConfigProvider.getElasticSearchUrl(targetHostUrl,paramsMap)); request.setHeader(ACCEPT, TYPE_APPLICATION_JSON); request.setHeader(CONTENT_TYPE, TYPE_APPLICATION_JSON); handleAuthentication(request, authenticationContext.getTenantDomain()); - String query = elasticConfigProvider.getQuery(params); + String query = elasticConfigProvider.getQuery(paramsMap); request.setEntity(new StringEntity(query, StandardCharsets.UTF_8)); String[] targetHostUrls = targetHostUrl.split(";"); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.elk/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/elk/CallElasticFunctionImplTest.java b/components/org.wso2.carbon.identity.conditional.auth.functions.elk/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/elk/CallElasticFunctionImplTest.java index 95a0cfe5..a5e0f0a2 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.elk/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/elk/CallElasticFunctionImplTest.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.elk/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/elk/CallElasticFunctionImplTest.java @@ -22,6 +22,7 @@ import org.json.JSONObject; import org.mockito.Mockito; import org.testng.annotations.BeforeClass; +import org.testng.annotations.Parameters; import org.testng.annotations.Test; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.identity.application.authentication.framework.config.model.SequenceConfig; @@ -74,9 +75,10 @@ public class CallElasticFunctionImplTest extends JsSequenceHandlerAbstractTest { private int microServicePort; @BeforeClass - protected void initClass() throws Exception { + @Parameters({"scriptEngine"}) + protected void initClass(String scriptEngine) throws Exception { - super.setUp(); + super.setUp(scriptEngine); CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME = true; sequenceHandlerRunner.registerJsFunction("callElastic", new CallElasticFunctionImpl()); } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.elk/src/test/resources/testng.xml b/components/org.wso2.carbon.identity.conditional.auth.functions.elk/src/test/resources/testng.xml new file mode 100644 index 00000000..84389b21 --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.elk/src/test/resources/testng.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.http/pom.xml b/components/org.wso2.carbon.identity.conditional.auth.functions.http/pom.xml index 68de8149..545c2997 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.http/pom.xml +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.http/pom.xml @@ -217,6 +217,18 @@ org.jacoco jacoco-maven-plugin + + org.apache.maven.plugins + maven-surefire-plugin + + + src/test/resources/testng.xml + + + org.ops4j.pax.logging + + + diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/AbstractHTTPFunction.java b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/AbstractHTTPFunction.java index 0898d09d..b7aa4f52 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/AbstractHTTPFunction.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/AbstractHTTPFunction.java @@ -46,6 +46,7 @@ import java.net.SocketTimeoutException; import java.net.URI; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -95,15 +96,19 @@ public boolean shouldRetry() { protected void executeHttpMethod(HttpUriRequest clientRequest, Map eventHandlers, AuthConfigModel authConfigModel) { + Map eventHandlersMap = new HashMap<>(eventHandlers); + AuthConfigModel authConfigModelClone = + authConfigModel == null ? null : new AuthConfigModel(authConfigModel.getType(), + new HashMap<>(authConfigModel.getProperties())); AsyncProcess asyncProcess = new AsyncProcess((context, asyncReturn) -> { String outcome; String endpointURL = null; HttpUriRequest request; try { - if (authConfigModel != null) { - AuthConfig authConfig = AuthConfigFactory.getAuthConfig(authConfigModel, context, asyncReturn); - request = authConfig.applyAuth(clientRequest, authConfigModel); + if (authConfigModelClone != null) { + AuthConfig authConfig = AuthConfigFactory.getAuthConfig(authConfigModelClone, context, asyncReturn); + request = authConfig.applyAuth(clientRequest, authConfigModelClone); } else { request = clientRequest; } @@ -131,7 +136,7 @@ protected void executeHttpMethod(HttpUriRequest clientRequest, Map properties = null; @@ -117,10 +119,11 @@ public void setCookie(JsServletResponse response, String name, Object... params) Optional.ofNullable((sameSite != null) ? SameSiteCookie.valueOf(sameSite) : null) .ifPresent(cookie::setSameSite); } - response.addCookie(cookie); + response.getWrapped().getWrapped().addCookie(cookie); } @Override + @Deprecated public String getCookieValue(JsServletRequest request, Object... params) { Map properties = null; diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/GetCookieFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/GetCookieFunctionImpl.java new file mode 100644 index 00000000..02b95051 --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/GetCookieFunctionImpl.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.http; + +import org.apache.axiom.om.util.Base64; +import org.apache.commons.io.Charsets; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.wso2.carbon.core.util.CryptoException; +import org.wso2.carbon.core.util.CryptoUtil; +import org.wso2.carbon.core.util.SignatureUtil; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsServletRequest; +import org.wso2.carbon.identity.conditional.auth.functions.http.util.HTTPConstants; + +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Optional; + +import javax.servlet.http.Cookie; + +/** + * Implementation of GetCookieFunction. + */ +public class GetCookieFunctionImpl implements GetCookieFunction { + + private static final Log log = LogFactory.getLog(GetCookieFunctionImpl.class); + private static final String ENABLE_ADAPTIVE_SCRIPT_COOKIE_LEGACY_MODE = "enableAdaptiveScriptCookieLegacyMode"; + + @Override + @HostAccess.Export + public String getCookieValue(JsServletRequest request, Object... params) { + + Map properties = null; + if (params.length == 0 || params.length > 2) { + return null; + } + if (params.length == 2) { + if (params[1] instanceof Map) { + properties = (Map) params[1]; + } + } + String name = (String) params[0]; + Cookie[] cookies = request.getWrapped().getWrapped().getCookies(); + if (cookies == null) { + return null; + } + for (Cookie cookie : cookies) { + if (name.equals(cookie.getName())) { + JSONObject cookieValueJSON; + try { + JSONParser jsonParser = new JSONParser(); + cookieValueJSON = (JSONObject) jsonParser.parse(new String(Base64.decode(cookie.getValue()), + Charsets.UTF_8)); + } catch (ParseException e) { + log.error("Error occurred when converting cookie value to JSON.", e); + return null; + } + String valueString = (String) cookieValueJSON.get(HTTPConstants.VALUE); + + if (properties != null) { + boolean validateSignature = Optional.ofNullable((Boolean) properties.get( + HTTPConstants.VALIDATE_SIGN)).orElse(false); + boolean decrypt = Optional.ofNullable((Boolean) properties.get(HTTPConstants.DECRYPT)) + .orElse(false); + if (decrypt) { + try { + if (Boolean.parseBoolean(System.getProperty(ENABLE_ADAPTIVE_SCRIPT_COOKIE_LEGACY_MODE))) { + valueString = Base64.encode(CryptoUtil.getDefaultCryptoUtil() + .base64DecodeAndDecrypt(valueString)); + } else { + valueString = new String(CryptoUtil.getDefaultCryptoUtil() + .base64DecodeAndDecrypt(valueString), StandardCharsets.UTF_8); + } + } catch (CryptoException e) { + log.error("Error occurred when decrypting the cookie value.", e); + return null; + } + } + if (validateSignature) { + byte[] signature = Base64.decode((String) cookieValueJSON.get(HTTPConstants.SIGNATURE)); + try { + boolean isValid = SignatureUtil.validateSignature(valueString, signature); + if (!isValid) { + log.error("Cookie signature didn't matched with the cookie value."); + return null; + } + } catch (Exception e) { + log.error("Error occurred when validating signature of the cookie value.", e); + return null; + } + } + } + return valueString; + } + } + return null; + } +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPGetFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPGetFunctionImpl.java index f8aa1fb9..7986a177 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPGetFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPGetFunctionImpl.java @@ -21,6 +21,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.client.methods.HttpGet; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.conditional.auth.functions.http.util.AuthConfigModel; import java.util.HashMap; @@ -39,6 +40,7 @@ public HTTPGetFunctionImpl() { } @Override + @HostAccess.Export public void httpGet(String endpointURL, Object... params) { Map eventHandlers; diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPPostFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPPostFunctionImpl.java index e5f7ab9a..7a0fc60f 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPPostFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPPostFunctionImpl.java @@ -26,6 +26,7 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.message.BasicNameValuePair; +import org.graalvm.polyglot.HostAccess; import org.json.simple.JSONObject; import org.wso2.carbon.identity.conditional.auth.functions.http.util.AuthConfigModel; @@ -51,6 +52,7 @@ public HTTPPostFunctionImpl() { } @Override + @HostAccess.Export public void httpPost(String endpointURL, Object... params) { Map eventHandlers; diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/SetCookieFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/SetCookieFunctionImpl.java new file mode 100644 index 00000000..3a8d090a --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/SetCookieFunctionImpl.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.http; + +import org.apache.axiom.om.util.Base64; +import org.apache.commons.io.Charsets; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; +import org.json.simple.JSONObject; +import org.wso2.carbon.core.SameSiteCookie; +import org.wso2.carbon.core.ServletCookie; +import org.wso2.carbon.core.util.CryptoException; +import org.wso2.carbon.core.util.CryptoUtil; +import org.wso2.carbon.core.util.SignatureUtil; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsServletResponse; +import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; +import org.wso2.carbon.identity.conditional.auth.functions.http.util.HTTPConstants; + +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Optional; + +/** + * Implementation of SetCookieFunction. + */ +public class SetCookieFunctionImpl implements SetCookieFunction { + + private static final Log log = LogFactory.getLog(SetCookieFunctionImpl.class); + private static final String ENABLE_ADAPTIVE_SCRIPT_COOKIE_LEGACY_MODE = "enableAdaptiveScriptCookieLegacyMode"; + + @Override + @HostAccess.Export + public void setCookie(JsServletResponse response, String name, Object... params) { + + Map properties = null; + if (params.length == 0 || params.length > 2) { + return; + } + if (params.length == 2) { + if (params[1] instanceof Map) { + properties = (Map) params[1]; + } + } + + String value = (String) params[0]; + String signature = null; + if (properties != null) { + boolean sign = Optional.ofNullable((Boolean) properties.get(HTTPConstants.SIGN)).orElse(false); + boolean encrypt = Optional.ofNullable((Boolean) properties.get(HTTPConstants.ENCRYPT)).orElse(false); + if (sign) { + try { + signature = Base64.encode(SignatureUtil.doSignature(value)); + } catch (Exception e) { + log.error("Error occurred when signing the cookie value.", e); + return; + } + } + if (encrypt) { + try { + if (Boolean.parseBoolean(System.getProperty(ENABLE_ADAPTIVE_SCRIPT_COOKIE_LEGACY_MODE))) { + value = CryptoUtil.getDefaultCryptoUtil().encryptAndBase64Encode(Base64.decode(value)); + } else { + value = CryptoUtil.getDefaultCryptoUtil().encryptAndBase64Encode( + value.getBytes(StandardCharsets.UTF_8)); + } + } catch (CryptoException e) { + log.error("Error occurred when encrypting the cookie value.", e); + return; + } + } + } + JSONObject cookieValueJson = new JSONObject(); + cookieValueJson.put(HTTPConstants.VALUE, value); + cookieValueJson.put(HTTPConstants.SIGNATURE, signature); + + String cookieValue = cookieValueJson.toString(); + + cookieValue = Base64.encode((cookieValue.getBytes(Charsets.UTF_8))); + ServletCookie cookie = new ServletCookie(name, cookieValue); + if (properties != null) { + Optional.ofNullable((String) properties.get(FrameworkConstants.JSAttributes.JS_COOKIE_DOMAIN)) + .ifPresent(cookie::setDomain); + Optional.ofNullable((String) properties.get(FrameworkConstants.JSAttributes.JS_COOKIE_PATH)) + .ifPresent(cookie::setPath); + Optional.ofNullable((String) properties.get(FrameworkConstants.JSAttributes.JS_COOKIE_COMMENT)) + .ifPresent(cookie::setComment); + Optional.ofNullable((Integer) properties.get(FrameworkConstants.JSAttributes.JS_COOKIE_MAX_AGE)) + .ifPresent(cookie::setMaxAge); + Optional.ofNullable((Integer) properties.get(FrameworkConstants.JSAttributes.JS_COOKIE_VERSION)) + .ifPresent(cookie::setVersion); + Optional.ofNullable((Boolean) properties.get(FrameworkConstants.JSAttributes.JS_COOKIE_HTTP_ONLY)) + .ifPresent(cookie::setHttpOnly); + Optional.ofNullable((Boolean) properties.get(FrameworkConstants.JSAttributes.JS_COOKIE_SECURE)) + .ifPresent(cookie::setSecure); + String sameSite = (String) properties.get(FrameworkConstants.JSAttributes.JS_COOKIE_SAMESITE); + Optional.ofNullable((sameSite != null) ? SameSiteCookie.valueOf(sameSite) : null) + .ifPresent(cookie::setSameSite); + } + response.getWrapped().getWrapped().addCookie(cookie); + } +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/internal/HTTPFunctionsServiceComponent.java b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/internal/HTTPFunctionsServiceComponent.java index 2c60b636..cb4fb9de 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/internal/HTTPFunctionsServiceComponent.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/internal/HTTPFunctionsServiceComponent.java @@ -29,13 +29,12 @@ import org.osgi.service.component.annotations.ReferenceCardinality; import org.osgi.service.component.annotations.ReferencePolicy; import org.wso2.carbon.identity.application.authentication.framework.JsFunctionRegistry; +import org.wso2.carbon.identity.conditional.auth.functions.http.GetCookieFunctionImpl; import org.wso2.carbon.identity.conditional.auth.functions.http.HTTPGetFunction; import org.wso2.carbon.identity.conditional.auth.functions.http.HTTPGetFunctionImpl; import org.wso2.carbon.identity.conditional.auth.functions.http.HTTPPostFunction; import org.wso2.carbon.identity.conditional.auth.functions.http.HTTPPostFunctionImpl; -import org.wso2.carbon.identity.conditional.auth.functions.http.CookieFunctionImpl; -import org.wso2.carbon.identity.conditional.auth.functions.http.GetCookieFunction; -import org.wso2.carbon.identity.conditional.auth.functions.http.SetCookieFunction; +import org.wso2.carbon.identity.conditional.auth.functions.http.SetCookieFunctionImpl; import org.wso2.carbon.identity.core.util.IdentityCoreInitializedEvent; /** @@ -58,12 +57,10 @@ public class HTTPFunctionsServiceComponent { @Activate protected void activate(ComponentContext ctxt) { - CookieFunctionImpl cookieFunction = new CookieFunctionImpl(); JsFunctionRegistry jsFunctionRegistry = HTTPFunctionsServiceHolder.getInstance().getJsFunctionRegistry(); - jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, FUNC_SET_COOKIE, - (SetCookieFunction) cookieFunction::setCookie); - jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, FUNC_GET_COOKIE_VALUE, - (GetCookieFunction) cookieFunction::getCookieValue); + jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, FUNC_SET_COOKIE, new GetCookieFunctionImpl()); + jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, + FUNC_GET_COOKIE_VALUE, new SetCookieFunctionImpl()); HTTPPostFunction httpPost = new HTTPPostFunctionImpl(); jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, FUNC_HTTP_POST, httpPost); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/http/CookieFunctionImplTest.java b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/http/CookieFunctionImplTest.java index 6b7bc473..20ce7c06 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/http/CookieFunctionImplTest.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/http/CookieFunctionImplTest.java @@ -68,11 +68,9 @@ public class CookieFunctionImplTest extends JsSequenceHandlerAbstractTest { @BeforeMethod protected void setUp() throws Exception { - super.setUp(); CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME = true; - sequenceHandlerRunner.registerJsFunction("setCookie", (SetCookieFunction) new CookieFunctionImpl()::setCookie); - sequenceHandlerRunner.registerJsFunction("getCookieValue", (GetCookieFunction) new CookieFunctionImpl() - ::getCookieValue); + sequenceHandlerRunner.registerJsFunction("setCookie", new SetCookieFunctionImpl()); + sequenceHandlerRunner.registerJsFunction("getCookieValue", new GetCookieFunctionImpl()); DefaultCryptoService defaultCryptoService = new DefaultCryptoService(); defaultCryptoService.registerInternalCryptoProvider(new SimpleCryptoProviderTest()); CarbonCoreDataHolder.getInstance().setCryptoService(defaultCryptoService); @@ -169,7 +167,9 @@ public Object[][] getCookieValues() { private void internalTestSetAndGetCookieValues(String inputCookieValue, boolean shouldEncrypt, boolean shouldDecrypt, boolean shouldSign) throws JsTestException { - CookieFunctionImpl cookieFunction = new CookieFunctionImpl(); + GetCookieFunctionImpl getCookieFunction = new GetCookieFunctionImpl(); + SetCookieFunctionImpl setCookieFunction = new SetCookieFunctionImpl(); + String name = "test"; HttpServletResponse resp = sequenceHandlerRunner.createHttpServletResponse(); @@ -178,7 +178,7 @@ private void internalTestSetAndGetCookieValues(String inputCookieValue, boolean setCookieParams.put(HTTPConstants.ENCRYPT, shouldEncrypt); setCookieParams.put(HTTPConstants.SIGN, shouldSign); // Set the Cookie value. - cookieFunction.setCookie(jsServletResponse, name, inputCookieValue, setCookieParams); + setCookieFunction.setCookie(jsServletResponse, name, inputCookieValue, setCookieParams); // Get the cookie value that added to the response when setCookie method value is called. ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Cookie.class); @@ -192,7 +192,7 @@ private void internalTestSetAndGetCookieValues(String inputCookieValue, boolean Map getCookieParams = new HashMap<>(); getCookieParams.put(HTTPConstants.DECRYPT, shouldDecrypt); // Get the cookie value - String value = cookieFunction.getCookieValue(jsServletRequest, name, getCookieParams ); + String value = getCookieFunction.getCookieValue(jsServletRequest, name, getCookieParams ); Assert.assertEquals(value, inputCookieValue); } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPGetFunctionImplTest.java b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPGetFunctionImplTest.java index 0087c4b0..c18ea294 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPGetFunctionImplTest.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPGetFunctionImplTest.java @@ -20,6 +20,7 @@ import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; +import org.testng.annotations.Parameters; import org.testng.annotations.Test; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.identity.application.authentication.framework.config.model.SequenceConfig; @@ -79,9 +80,10 @@ public class HTTPGetFunctionImplTest extends JsSequenceHandlerAbstractTest { private int microServicePort; @BeforeClass - protected void initClass() throws Exception { + @Parameters({"scriptEngine"}) + protected void initClass(String scriptEngine) throws Exception { - super.setUp(); + super.setUp(scriptEngine); CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME = true; LongWaitStatusDAOImpl daoImpl = new LongWaitStatusDAOImpl(); CacheBackedLongWaitStatusDAO cacheBackedDao = new CacheBackedLongWaitStatusDAO(daoImpl); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPPostFunctionImplTest.java b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPPostFunctionImplTest.java index b8c2382f..203ca487 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPPostFunctionImplTest.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/http/HTTPPostFunctionImplTest.java @@ -20,6 +20,7 @@ import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; +import org.testng.annotations.Parameters; import org.testng.annotations.Test; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.identity.application.authentication.framework.config.model.SequenceConfig; @@ -82,9 +83,10 @@ public class HTTPPostFunctionImplTest extends JsSequenceHandlerAbstractTest { private int microServicePort; @BeforeClass - protected void initClass() throws Exception { + @Parameters({"scriptEngine"}) + protected void initClass(String scriptEngine) throws Exception { - super.setUp(); + super.setUp(scriptEngine); CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME = true; LongWaitStatusDAOImpl daoImpl = new LongWaitStatusDAOImpl(); CacheBackedLongWaitStatusDAO cacheBackedDao = new CacheBackedLongWaitStatusDAO(daoImpl); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/resources/testng.xml b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/resources/testng.xml index f89d9b33..fc2589e5 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/resources/testng.xml +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/test/resources/testng.xml @@ -1,5 +1,5 @@ @@ -19,7 +19,8 @@ - + + @@ -27,4 +28,12 @@ + + + + + + + + diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.jwt.decode/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/jwt/decode/JwtDecodeImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.jwt.decode/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/jwt/decode/JwtDecodeImpl.java index c2a59400..fbf7fd48 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.jwt.decode/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/jwt/decode/JwtDecodeImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.jwt.decode/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/jwt/decode/JwtDecodeImpl.java @@ -22,6 +22,7 @@ import net.minidev.json.JSONObject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; import java.text.ParseException; @@ -42,6 +43,7 @@ public class JwtDecodeImpl implements JwtDecode { * @throws FrameworkException */ @Override + @HostAccess.Export public String getValueFromDecodedAssertion(String clientAssertion, String parameterName, boolean isParameterInPayload) throws FrameworkException { diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.notification/pom.xml b/components/org.wso2.carbon.identity.conditional.auth.functions.notification/pom.xml index 51d9248c..74214b66 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.notification/pom.xml +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.notification/pom.xml @@ -142,6 +142,18 @@ org.jacoco jacoco-maven-plugin + + org.apache.maven.plugins + maven-surefire-plugin + + + src/test/resources/testng.xml + + + org.ops4j.pax.logging + + + diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.notification/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/notification/SendEmailFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.notification/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/notification/SendEmailFunctionImpl.java index 60e40709..16f2f861 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.notification/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/notification/SendEmailFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.notification/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/notification/SendEmailFunctionImpl.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; import org.wso2.carbon.identity.conditional.auth.functions.notification.internal.NotificationFunctionServiceHolder; import org.wso2.carbon.identity.event.IdentityEventConstants; @@ -40,6 +41,7 @@ public class SendEmailFunctionImpl implements SendEmailFunction { private static final Log LOG = LogFactory.getLog(SendEmailFunctionImpl.class); @Override + @HostAccess.Export public boolean sendMail(JsAuthenticatedUser user, String templateId, Map paramMap) { String eventName = IdentityEventConstants.Event.TRIGGER_NOTIFICATION; diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.notification/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/notification/SendEmailFunctionImplTest.java b/components/org.wso2.carbon.identity.conditional.auth.functions.notification/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/notification/SendEmailFunctionImplTest.java index 52b5f5ea..11be437b 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.notification/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/notification/SendEmailFunctionImplTest.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.notification/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/notification/SendEmailFunctionImplTest.java @@ -57,8 +57,6 @@ public class SendEmailFunctionImplTest extends JsSequenceHandlerAbstractTest { @BeforeMethod protected void setUp() throws Exception { - super.setUp(); - CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME = true; sequenceHandlerRunner.registerJsFunction("sendEmail", new SendEmailFunctionImpl()); } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.notification/src/test/resources/testng.xml b/components/org.wso2.carbon.identity.conditional.auth.functions.notification/src/test/resources/testng.xml new file mode 100644 index 00000000..92d1df88 --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.notification/src/test/resources/testng.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.test.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/test/utils/sequence/JsSequenceHandlerAbstractTest.java b/components/org.wso2.carbon.identity.conditional.auth.functions.test.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/test/utils/sequence/JsSequenceHandlerAbstractTest.java index 172dfed4..931bde48 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.test.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/test/utils/sequence/JsSequenceHandlerAbstractTest.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.test.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/test/utils/sequence/JsSequenceHandlerAbstractTest.java @@ -22,6 +22,7 @@ import org.apache.commons.logging.LogFactory; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Parameters; import org.wso2.carbon.identity.application.authentication.framework.internal.FrameworkServiceDataHolder; import org.wso2.carbon.identity.core.util.IdentityConfigParser; @@ -80,7 +81,8 @@ protected void initialize() throws IOException { } @BeforeMethod - protected void setUp() throws Exception { + @Parameters({"scriptEngine"}) + protected void setUp(String scriptEngine) throws Exception { if (sequenceHandlerRunner == null) { sequenceHandlerRunner = new JsSequenceHandlerRunner(); @@ -89,7 +91,7 @@ protected void setUp() throws Exception { if (applicationAuthenticatorFileName != null) { url = this.getClass().getClassLoader().getResource(applicationAuthenticatorFileName); } - sequenceHandlerRunner.init(url); + sequenceHandlerRunner.init(url, scriptEngine); } FrameworkServiceDataHolder.getInstance().setAdaptiveAuthenticationAvailable(true); } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.test.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/test/utils/sequence/JsSequenceHandlerRunner.java b/components/org.wso2.carbon.identity.conditional.auth.functions.test.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/test/utils/sequence/JsSequenceHandlerRunner.java index ee22edb2..544ce07d 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.test.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/test/utils/sequence/JsSequenceHandlerRunner.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.test.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/test/utils/sequence/JsSequenceHandlerRunner.java @@ -28,14 +28,21 @@ import org.wso2.carbon.identity.application.authentication.framework.config.loader.UIBasedConfigurationLoader; import org.wso2.carbon.identity.application.authentication.framework.config.model.SequenceConfig; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JSExecutionSupervisor; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JsBaseGraphBuilderFactory; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JsFunctionRegistryImpl; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JsGenericGraphBuilderFactory; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JsGraphBuilderFactory; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JsWrapperFactory; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JsWrapperFactoryProvider; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.graaljs.JsGraalGraphBuilderFactory; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.graaljs.JsGraalWrapperFactory; import org.wso2.carbon.identity.application.authentication.framework.context.AuthenticationContext; import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; import org.wso2.carbon.identity.application.authentication.framework.handler.sequence.impl.AsyncSequenceExecutor; import org.wso2.carbon.identity.application.authentication.framework.handler.sequence.impl.GraphBasedSequenceHandler; import org.wso2.carbon.identity.application.authentication.framework.internal.FrameworkServiceDataHolder; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; +import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; import org.wso2.carbon.identity.application.common.model.ClaimMapping; import org.wso2.carbon.identity.application.common.model.ServiceProvider; import org.wso2.carbon.identity.conditional.auth.functions.test.utils.api.MockAuthenticator; @@ -91,23 +98,28 @@ public class JsSequenceHandlerRunner { protected GraphBasedSequenceHandler graphBasedSequenceHandler = new GraphBasedSequenceHandler(); protected UIBasedConfigurationLoader configurationLoader; - protected JsGraphBuilderFactory graphBuilderFactory; + protected JsGenericGraphBuilderFactory graphBuilderFactory; protected JSExecutionSupervisor jsExecutionSupervisor; private JsFunctionRegistryImpl jsFunctionRegistry; private URL applicationAuthenticatorConfigFileLocation; public static final int THREAD_COUNT = 1; - public static final long SUPERVISOR_TIMEOUT = 500L; + public static final long SUPERVISOR_TIMEOUT = 500000L; private static final String DEFAULT_APPLICATION_AUTHENTICATION_XML_FILE_NAME = "application-authentication-test.xml"; - public void init(URL applicationAuthenticatorConfigFileLocation) throws InvocationTargetException { + public void init(URL applicationAuthenticatorConfigFileLocation, String scriptEngine) + throws InvocationTargetException, NoSuchFieldException, IllegalAccessException { this.applicationAuthenticatorConfigFileLocation = applicationAuthenticatorConfigFileLocation; configurationLoader = new UIBasedConfigurationLoader(); - graphBuilderFactory = new JsGraphBuilderFactory(); + if (scriptEngine.contentEquals(FrameworkConstants.JSAttributes.NASHORN)) { + graphBuilderFactory = new JsGraphBuilderFactory(); + } else if (scriptEngine.contentEquals(FrameworkConstants.JSAttributes.GRAALJS)) { + graphBuilderFactory = new JsGraalGraphBuilderFactory(); + } jsFunctionRegistry = new JsFunctionRegistryImpl(); FrameworkServiceDataHolder.getInstance().setJsFunctionRegistry(jsFunctionRegistry); @@ -115,7 +127,15 @@ public void init(URL applicationAuthenticatorConfigFileLocation) throws Invocati FrameworkServiceDataHolder.getInstance().setJsExecutionSupervisor(jsExecutionSupervisor); graphBuilderFactory.init(); - FrameworkServiceDataHolder.getInstance().setJsGraphBuilderFactory(graphBuilderFactory); + FrameworkServiceDataHolder.getInstance().setJsGenericGraphBuilderFactory(graphBuilderFactory); + + Field wrapperFactory = JsWrapperFactoryProvider.class.getDeclaredField("jsWrapperBaseFactory"); + wrapperFactory.setAccessible(true); + if (graphBuilderFactory instanceof JsGraphBuilderFactory) { + wrapperFactory.set(JsWrapperFactoryProvider.getInstance(), new JsWrapperFactory()); + } else if (graphBuilderFactory instanceof JsGraalGraphBuilderFactory) { + wrapperFactory.set(JsWrapperFactoryProvider.getInstance(), new JsGraalWrapperFactory()); + } AsyncSequenceExecutor asyncSequenceExecutor = new AsyncSequenceExecutor(); asyncSequenceExecutor.init(); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/GetUserWithClaimValuesV2Function.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/GetUserWithClaimValuesV2Function.java new file mode 100644 index 00000000..de7e5099 --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/GetUserWithClaimValuesV2Function.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user.store; + +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; +import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; + +import java.util.Map; + +@FunctionalInterface +public interface GetUserWithClaimValuesV2Function { + + JsAuthenticatedUser getUniqueUserWithClaimValues(Map claimMap, + JsAuthenticationContext authenticationContext, + String... parameters) throws FrameworkException; +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/GetUserWithClaimValuesV2FunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/GetUserWithClaimValuesV2FunctionImpl.java new file mode 100644 index 00000000..23a126e3 --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/GetUserWithClaimValuesV2FunctionImpl.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user.store; + +import org.graalvm.polyglot.HostAccess; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; +import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; + +import java.util.Map; + +/** + * Implementation of GetUserWithClaimValuesV2Function. This will return a user given a set of claim values. + */ +public class GetUserWithClaimValuesV2FunctionImpl implements GetUserWithClaimValuesV2Function { + + @Override + @HostAccess.Export + public JsAuthenticatedUser getUniqueUserWithClaimValues(Map claimMap, + JsAuthenticationContext authenticationContext, + String... parameters) throws FrameworkException { + + return new UserStoreFunctions().getUniqueUserWithClaimValues(claimMap, authenticationContext, parameters); + } +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/UserStoreFunctions.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/UserStoreFunctions.java index 39583a0c..307415ca 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/UserStoreFunctions.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/UserStoreFunctions.java @@ -47,6 +47,11 @@ public class UserStoreFunctions implements GetUserWithClaimValues { public JsAuthenticatedUser getUniqueUserWithClaimValues(Map claimMap, Object... parameters) throws FrameworkException { + return getUniqueUserWithClaimValuesInternal(claimMap, parameters); + } + + private JsAuthenticatedUser getUniqueUserWithClaimValuesInternal(Map claimMap, Object... parameters) + throws FrameworkException { JsAuthenticationContext authenticationContext = null; String tenantDomain = null; @@ -57,6 +62,7 @@ public JsAuthenticatedUser getUniqueUserWithClaimValues(Map clai } return null; } + if (parameters.length == 2) { if ( parameters[0] instanceof JsAuthenticationContext) { authenticationContext = (JsAuthenticationContext) parameters[0]; @@ -70,7 +76,6 @@ public JsAuthenticatedUser getUniqueUserWithClaimValues(Map clai authenticationContext = (JsAuthenticationContext) parameters[0]; tenantDomain = authenticationContext.getContext().getTenantDomain(); } - if (tenantDomain != null) { int tenantId = IdentityTenantUtil.getTenantId(tenantDomain); try { @@ -121,10 +126,10 @@ public JsAuthenticatedUser getUniqueUserWithClaimValues(Map clai authenticatedUser.setTenantDomain(tenantDomain); if (authenticationContext != null) { return (JsAuthenticatedUser) JsWrapperFactoryProvider.getInstance().getWrapperFactory(). - createJsAuthenticatedUser(authenticationContext.getContext(), authenticatedUser); + createJsAuthenticatedUser(authenticatedUser); } return (JsAuthenticatedUser) JsWrapperFactoryProvider.getInstance().getWrapperFactory(). - createJsAuthenticatedUser(authenticatedUser); + createJsAuthenticatedUser(authenticationContext.getWrapped(), authenticatedUser); } else { LOG.error("Cannot find the user realm for the given tenant: " + tenantId); } @@ -138,4 +143,5 @@ public JsAuthenticatedUser getUniqueUserWithClaimValues(Map clai } return null; } + } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/internal/UserStoreFunctionsServiceComponent.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/internal/UserStoreFunctionsServiceComponent.java index 87e269ca..3b149918 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/internal/UserStoreFunctionsServiceComponent.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user.store/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/store/internal/UserStoreFunctionsServiceComponent.java @@ -28,8 +28,7 @@ import org.osgi.service.component.annotations.ReferenceCardinality; import org.osgi.service.component.annotations.ReferencePolicy; import org.wso2.carbon.identity.application.authentication.framework.JsFunctionRegistry; -import org.wso2.carbon.identity.conditional.auth.functions.user.store.GetUserWithClaimValues; -import org.wso2.carbon.identity.conditional.auth.functions.user.store.UserStoreFunctions; +import org.wso2.carbon.identity.conditional.auth.functions.user.store.GetUserWithClaimValuesV2FunctionImpl; import org.wso2.carbon.user.core.service.RealmService; /** @@ -48,12 +47,12 @@ public class UserStoreFunctionsServiceComponent { protected void activate(ComponentContext ctxt) { try { - UserStoreFunctions storeFunctions = new UserStoreFunctions(); + GetUserWithClaimValuesV2FunctionImpl storeFunctions = new GetUserWithClaimValuesV2FunctionImpl(); JsFunctionRegistry jsFunctionRegistry = UserStoreFunctionsServiceHolder.getInstance() .getJsFunctionRegistry(); jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "getUniqueUserWithClaimValues", - (GetUserWithClaimValues) storeFunctions::getUniqueUserWithClaimValues); + new GetUserWithClaimValuesV2FunctionImpl()); } catch (Throwable e) { LOG.error("Error occurred during conditional authentication user functions bundle activation. ", e); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/pom.xml b/components/org.wso2.carbon.identity.conditional.auth.functions.user/pom.xml index 64bf3745..55366f2e 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/pom.xml +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/pom.xml @@ -114,6 +114,11 @@ nashorn-core provided + + org.graalvm.sdk + graal-sdk + provided + org.wso2.orbit.com.nimbusds nimbus-jose-jwt @@ -188,8 +193,14 @@ version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js; version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.openjdk.*; + version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.graaljs; + version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.application.authentication.framework.config.model.graph; version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.application.authentication.framework.config.model.graph.graaljs; + version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.application.authentication.framework.config.model; version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.application.authentication.framework.context; @@ -249,6 +260,18 @@ org.jacoco jacoco-maven-plugin + + org.apache.maven.plugins + maven-surefire-plugin + + + src/test/resources/testng.xml + + + org.ops4j.pax.logging + + + diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesFunctionImpl.java index d0179a98..8f443b92 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesFunctionImpl.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; import org.wso2.carbon.user.core.UserRealm; @@ -44,6 +45,7 @@ public class AssignUserRolesFunctionImpl implements AssignUserRolesFunction { * @return true If the role assigning is successfully completed. false for any other case. */ @Override + @HostAccess.Export public boolean assignUserRoles(JsAuthenticatedUser user, List assigningRoles) { if (user == null) { diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2FunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2FunctionImpl.java index 7464260b..b5332988 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2FunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/AssignUserRolesV2FunctionImpl.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; @@ -46,6 +47,7 @@ public class AssignUserRolesV2FunctionImpl implements AssignUserRolesV2Function private static final Log LOG = LogFactory.getLog(AssignUserRolesV2FunctionImpl.class); @Override + @HostAccess.Export public boolean assignUserRolesV2(JsAuthenticationContext context, List roleListToAssign) { if (roleListToAssign == null || roleListToAssign.isEmpty()) { diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/CheckSessionExistenceFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/CheckSessionExistenceFunctionImpl.java index 3d71430e..afb2ced7 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/CheckSessionExistenceFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/CheckSessionExistenceFunctionImpl.java @@ -19,6 +19,7 @@ package org.wso2.carbon.identity.conditional.auth.functions.user; import org.apache.commons.collections.MapUtils; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.AuthenticatorConfig; import org.wso2.carbon.identity.application.authentication.framework.config.model.StepConfig; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; @@ -30,6 +31,7 @@ public class CheckSessionExistenceFunctionImpl implements CheckSessionExistenceFunction { @Override + @HostAccess.Export public boolean checkSessionExistence(int step, JsAuthenticationContext context) { StepConfig stepConfig = context.getWrapped() diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAssociatedLocalUserFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAssociatedLocalUserFunctionImpl.java index b997fc9d..506a6476 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAssociatedLocalUserFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAssociatedLocalUserFunctionImpl.java @@ -22,6 +22,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JsWrapperFactoryProvider; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; @@ -38,6 +39,7 @@ public class GetAssociatedLocalUserFunctionImpl implements GetAssociatedLocalUse private static final Log LOG = LogFactory.getLog(GetAssociatedLocalUserFunctionImpl.class); @Override + @HostAccess.Export public JsAuthenticatedUser getAssociatedLocalUser(JsAuthenticatedUser federatedUser) { if (!federatedUser.getWrapped().isFederatedUser()) { diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAuthenticatedApplicationsV2Function.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAuthenticatedApplicationsV2Function.java new file mode 100644 index 00000000..2490b9d2 --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAuthenticatedApplicationsV2Function.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user; + +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsApplication; + +import java.util.List; + +/** + * Function definition for retrieving authenticated applications. + */ +@FunctionalInterface +public interface GetAuthenticatedApplicationsV2Function { + + /** + * Retrieve the already authenticated applications for a given session. + * + * @param context context object. + * @return List of already authenticated applications of the given session. + */ + List getAuthenticatedApplications(JsAuthenticationContext context); +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAuthenticatedApplicationsV2FunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAuthenticatedApplicationsV2FunctionImpl.java new file mode 100644 index 00000000..b6a04154 --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAuthenticatedApplicationsV2FunctionImpl.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user; + +import org.graalvm.polyglot.HostAccess; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsApplication; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsWrapperFactoryProvider; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Function for retrieving javascript authenticated applications for a given session. + */ +public class GetAuthenticatedApplicationsV2FunctionImpl implements GetAuthenticatedApplicationsV2Function { + + @Override + @HostAccess.Export + public List getAuthenticatedApplications(JsAuthenticationContext context) { + + return new GetAuthenticatedAppsFuncImp().getAuthenticatedApplications(context) + .stream() + .map(app -> JsWrapperFactoryProvider.getInstance().getWrapperFactory().createJsApplication(app)) + .collect(Collectors.toList()); + } +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAuthenticatedAppsFuncImp.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAuthenticatedAppsFuncImp.java index fd0fba79..ca278312 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAuthenticatedAppsFuncImp.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetAuthenticatedAppsFuncImp.java @@ -20,14 +20,18 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; import org.wso2.carbon.identity.application.authentication.framework.exception.session.mgt.SessionManagementException; -import org.wso2.carbon.identity.application.authentication.framework.model.Application; import org.wso2.carbon.identity.application.authentication.framework.model.UserSession; +import org.wso2.carbon.identity.application.authentication.framework.model.Application; import org.wso2.carbon.identity.conditional.auth.functions.user.internal.UserFunctionsServiceHolder; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsApplication; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsWrapperFactoryProvider; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; /** * Function for retrieving authenticated applications for a given session. @@ -43,6 +47,7 @@ public class GetAuthenticatedAppsFuncImp implements GetAuthenticatedApplications * @return List of already authenticated applications of the given session. */ @Override + @HostAccess.Export public List getAuthenticatedApplications(JsAuthenticationContext context) { String sessionContextKey = context.getWrapped().getSessionIdentifier(); @@ -50,6 +55,7 @@ public List getAuthenticatedApplications(JsAuthenticationContext co if (sessionContextKey != null) { UserSession userSession = UserFunctionsServiceHolder.getInstance().getUserSessionManagementService() .getUserSessionBySessionId(sessionContextKey).get(); + return userSession.getApplications(); } } catch (SessionManagementException e) { diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetUserSessionsFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetUserSessionsFunctionImpl.java index 47a58780..304552c6 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetUserSessionsFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/GetUserSessionsFunctionImpl.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException; @@ -43,6 +44,7 @@ public class GetUserSessionsFunctionImpl implements GetUserSessionsFunction { private static final Log LOG = LogFactory.getLog(GetUserSessionsFunctionImpl.class); @Override + @HostAccess.Export public List getUserSessions(JsAuthenticatedUser user) { List sessionsForUser = null; diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesFunctionImpl.java index 4fa9e4b9..77d08696 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesFunctionImpl.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; import org.wso2.carbon.user.core.UserRealm; @@ -37,6 +38,7 @@ public class HasAnyOfTheRolesFunctionImpl implements HasAnyOfTheRolesFunction { private static final Log LOG = LogFactory.getLog(HasAnyOfTheRolesFunctionImpl.class); @Override + @HostAccess.Export public boolean hasAnyOfTheRoles(JsAuthenticatedUser user, List roleNames) { boolean result = false; diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2FunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2FunctionImpl.java index 6f17c0b3..80aca1c6 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2FunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesV2FunctionImpl.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; @@ -56,6 +57,7 @@ public class HasAnyOfTheRolesV2FunctionImpl implements HasAnyOfTheRolesV2Functio private static final Log LOG = LogFactory.getLog(HasAnyOfTheRolesV2FunctionImpl.class); @Override + @HostAccess.Export public boolean hasAnyOfTheRolesV2(JsAuthenticationContext context, List roleNames) { if (roleNames == null || roleNames.isEmpty()) { diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasRoleFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasRoleFunctionImpl.java index 14ba24f6..6f18aab0 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasRoleFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasRoleFunctionImpl.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; import org.wso2.carbon.user.core.UserRealm; @@ -39,6 +40,7 @@ public class HasRoleFunctionImpl implements HasRoleFunction { private static final Log LOG = LogFactory.getLog(HasRoleFunctionImpl.class); @Override + @HostAccess.Export public boolean hasRole(JsAuthenticatedUser user, String roleName) { boolean result = false; diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/IsAnyOfTheRolesAssignedToUserFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/IsAnyOfTheRolesAssignedToUserFunctionImpl.java index 8af4245a..23d19f8c 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/IsAnyOfTheRolesAssignedToUserFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/IsAnyOfTheRolesAssignedToUserFunctionImpl.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; @@ -41,6 +42,7 @@ public class IsAnyOfTheRolesAssignedToUserFunctionImpl implements IsAnyOfTheRole private final static String DEFAULT_FILTER = "*"; @Override + @HostAccess.Export public boolean IsAnyOfTheRolesAssignedToUser(JsAuthenticatedUser user, List roleNames) { boolean result = false; diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/IsMemberOfAnyOfGroupsFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/IsMemberOfAnyOfGroupsFunctionImpl.java index a5b7dfd9..4bd7055a 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/IsMemberOfAnyOfGroupsFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/IsMemberOfAnyOfGroupsFunctionImpl.java @@ -22,6 +22,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.ExternalIdPConfig; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; @@ -52,6 +53,7 @@ public class IsMemberOfAnyOfGroupsFunctionImpl implements IsMemberOfAnyOfGroupsF private static final String GROUPS_LOCAL_CLAIM = "http://wso2.org/claims/groups"; @Override + @HostAccess.Export public boolean isMemberOfAnyOfGroups(JsAuthenticatedUser user, List groupNames) { boolean result = false; diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/MicrosoftEmailVerificationFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/MicrosoftEmailVerificationFunctionImpl.java index addc7a7c..bdbbc85c 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/MicrosoftEmailVerificationFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/MicrosoftEmailVerificationFunctionImpl.java @@ -22,6 +22,7 @@ import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; import java.text.ParseException; @@ -45,6 +46,7 @@ public class MicrosoftEmailVerificationFunctionImpl implements MicrosoftEmailVer "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0"; @Override + @HostAccess.Export public boolean checkMicrosoftEmailVerification(JsAuthenticationContext context) { if (context.getWrapped().getParameter(ID_TOKEN) == null) { diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/PromptIdentifierFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/PromptIdentifierFunctionImpl.java index 90fe4fcf..7fd4ad2b 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/PromptIdentifierFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/PromptIdentifierFunctionImpl.java @@ -18,9 +18,11 @@ package org.wso2.carbon.identity.conditional.auth.functions.user; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JsGraphBuilder; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.SerializableJsFunction; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.ShowPromptNode; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsWrapperFactoryProvider; import java.util.HashMap; import java.util.Map; @@ -33,6 +35,7 @@ public class PromptIdentifierFunctionImpl implements PromptIdentifierFunction { public static final String STEP_PARAM = "step"; @Override + @HostAccess.Export public void promptIdentifier(int step, Object... parameters) { Map validators; @@ -48,7 +51,8 @@ public void promptIdentifier(int step, Object... parameters) { } if (validators.get(ShowPromptNode.PRE_HANDLER) == null) { - validators.put(ShowPromptNode.PRE_HANDLER, new SerializableJsFunction(DEFAULT_PRE_HANDLER_FUNC, true)); + validators.put(ShowPromptNode.PRE_HANDLER, JsWrapperFactoryProvider.getInstance() + .getWrapperFactory().createJsSerializableFunction(DEFAULT_PRE_HANDLER_FUNC, true)); } Map promptParameters = new HashMap<>(); promptParameters.put(STEP_PARAM, step); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesFunctionImpl.java index 107655a0..34db511b 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesFunctionImpl.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; import org.wso2.carbon.user.core.UserRealm; @@ -44,6 +45,7 @@ public class RemoveUserRolesFunctionImpl implements RemoveUserRolesFunction { * @return true If the role assigning is successfully completed. false for any other case. */ @Override + @HostAccess.Export public boolean removeUserRoles(JsAuthenticatedUser user, List removingRoles) { if (user == null) { diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2FunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2FunctionImpl.java index 1b291787..2376524e 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2FunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/RemoveUserRolesV2FunctionImpl.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext; import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; @@ -46,6 +47,7 @@ public class RemoveUserRolesV2FunctionImpl implements RemoveUserRolesV2Function private static final Log LOG = LogFactory.getLog(RemoveUserRolesV2FunctionImpl.class); @Override + @HostAccess.Export public boolean removeUserRolesV2(JsAuthenticationContext context, List roleListToRemove) { if (roleListToRemove == null || roleListToRemove.isEmpty()) { diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/SetAccountAssociationToLocalUserImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/SetAccountAssociationToLocalUserImpl.java index 02195156..b2e84701 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/SetAccountAssociationToLocalUserImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/SetAccountAssociationToLocalUserImpl.java @@ -21,6 +21,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import org.wso2.carbon.identity.user.profile.mgt.UserProfileException; @@ -34,6 +35,7 @@ public class SetAccountAssociationToLocalUserImpl implements SetAccountAssociati private static final Log log = LogFactory.getLog(SetAccountAssociationToLocalUserImpl.class); @Override + @HostAccess.Export public boolean doAssociationWithLocalUser(JsAuthenticatedUser federatedUser, String username, String tenantDomain, String userStoreDomainName) { diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/TerminateUserSessionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/TerminateUserSessionImpl.java index e42e1369..3e86d1da 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/TerminateUserSessionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/TerminateUserSessionImpl.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException; @@ -37,6 +38,7 @@ public class TerminateUserSessionImpl implements TerminateUserSession { private static final Log LOG = LogFactory.getLog(TerminateUserSession.class); @Override + @HostAccess.Export public boolean terminateUserSession(JsAuthenticatedUser user, String sessionId) { try { diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/UpdateUserPasswordFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/UpdateUserPasswordFunctionImpl.java index 250857ca..d27d2ca2 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/UpdateUserPasswordFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/UpdateUserPasswordFunctionImpl.java @@ -21,6 +21,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.AsyncProcess; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JsGraphBuilder; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser; @@ -43,6 +44,7 @@ public class UpdateUserPasswordFunctionImpl implements UpdateUserPasswordFunctio private static final Log LOG = LogFactory.getLog(UpdateUserPasswordFunctionImpl.class); @Override + @HostAccess.Export public void updateUserPassword(JsAuthenticatedUser user, Object... parameters) { if (user == null) { diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceComponent.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceComponent.java index 1021069f..d3aa4213 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceComponent.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/internal/UserFunctionsServiceComponent.java @@ -35,14 +35,13 @@ import org.wso2.carbon.identity.conditional.auth.functions.user.AssignUserRolesV2Function; import org.wso2.carbon.identity.conditional.auth.functions.user.AssignUserRolesV2FunctionImpl; import org.wso2.carbon.identity.conditional.auth.functions.user.CheckSessionExistenceFunctionImpl; +import org.wso2.carbon.identity.conditional.auth.functions.user.GetAuthenticatedApplicationsV2FunctionImpl; import org.wso2.carbon.identity.conditional.auth.functions.user.HasAnyOfTheRolesV2Function; import org.wso2.carbon.identity.conditional.auth.functions.user.HasAnyOfTheRolesV2FunctionImpl; import org.wso2.carbon.identity.conditional.auth.functions.user.MicrosoftEmailVerificationFunction; import org.wso2.carbon.identity.conditional.auth.functions.user.MicrosoftEmailVerificationFunctionImpl; import org.wso2.carbon.identity.conditional.auth.functions.user.GetAssociatedLocalUserFunction; import org.wso2.carbon.identity.conditional.auth.functions.user.GetAssociatedLocalUserFunctionImpl; -import org.wso2.carbon.identity.conditional.auth.functions.user.GetAuthenticatedApplicationsFunction; -import org.wso2.carbon.identity.conditional.auth.functions.user.GetAuthenticatedAppsFuncImp; import org.wso2.carbon.identity.conditional.auth.functions.user.GetUserSessionsFunctionImpl; import org.wso2.carbon.identity.conditional.auth.functions.user.IsMemberOfAnyOfGroupsFunction; import org.wso2.carbon.identity.conditional.auth.functions.user.IsMemberOfAnyOfGroupsFunctionImpl; @@ -91,7 +90,6 @@ protected void activate(ComponentContext ctxt) { RemoveUserRolesFunction removeUserRolesFunctionImpl = new RemoveUserRolesFunctionImpl(); GetAssociatedLocalUserFunction getAssociatedLocalUserFunctionImpl = new GetAssociatedLocalUserFunctionImpl(); SetAccountAssociationToLocalUser setAccountAssociationToLocalUserImpl = new SetAccountAssociationToLocalUserImpl(); - GetAuthenticatedApplicationsFunction getAuthenticatedApplicationsFunctionImp = new GetAuthenticatedAppsFuncImp(); MicrosoftEmailVerificationFunction microsoftEmailVerificationFunction = new MicrosoftEmailVerificationFunctionImpl(); UpdateUserPasswordFunction updateUserPasswordFunction = new UpdateUserPasswordFunctionImpl(); @@ -126,7 +124,7 @@ protected void activate(ComponentContext ctxt) { jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "isAnyOfTheRolesAssignedToUser", new IsAnyOfTheRolesAssignedToUserFunctionImpl()); jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "getAuthenticatedApplications", - getAuthenticatedApplicationsFunctionImp); + new GetAuthenticatedApplicationsV2FunctionImpl()); jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "checkMicrosoftEmailVerification", microsoftEmailVerificationFunction); jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "updateUserPassword", diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsGraalWrapperFactory.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsGraalWrapperFactory.java new file mode 100644 index 00000000..a85742fb --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsGraalWrapperFactory.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user.model; + +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.graaljs.GraalSerializableJsFunction; +import org.wso2.carbon.identity.application.authentication.framework.model.Application; +import org.wso2.carbon.identity.application.authentication.framework.model.UserSession; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.graaljs.JsGraalApplication; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.graaljs.JsGraalUserSession; + +/** + * Factory to create a Javascript Object Wrappers for GraalJS execution. + * Since Nashorn is deprecated in JDK 11 and onwards. We are introducing GraalJS engine. + */ +public class JsGraalWrapperFactory implements JsWrapperBaseFactory { + + @Override + public JsUserSession createJsUserSession(UserSession userSession) { + + return new JsGraalUserSession(userSession); + } + + @Override + public JsApplication createJsApplication(Application application) { + + return new JsGraalApplication(application); + } + + public GraalSerializableJsFunction createJsSerializableFunction(String source, boolean isFunction) { + + return new GraalSerializableJsFunction(source, isFunction); + } +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsOpenJdkNashornWrapperFactory.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsOpenJdkNashornWrapperFactory.java index 01ceedb9..f9857edb 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsOpenJdkNashornWrapperFactory.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsOpenJdkNashornWrapperFactory.java @@ -18,7 +18,10 @@ package org.wso2.carbon.identity.conditional.auth.functions.user.model; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.openjdk.nashorn.OpenJdkNashornSerializableJsFunction; +import org.wso2.carbon.identity.application.authentication.framework.model.Application; import org.wso2.carbon.identity.application.authentication.framework.model.UserSession; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.openjdk.nashorn.JsOpenJdkNashornApplication; import org.wso2.carbon.identity.conditional.auth.functions.user.model.openjdk.nashorn.JsOpenJdkNashornUserSession; /** @@ -32,4 +35,15 @@ public JsUserSession createJsUserSession(UserSession userSession) { return new JsOpenJdkNashornUserSession(userSession); } + + @Override + public JsApplication createJsApplication(Application application) { + + return new JsOpenJdkNashornApplication(application); + } + + public OpenJdkNashornSerializableJsFunction createJsSerializableFunction(String source, boolean isFunction) { + + return new OpenJdkNashornSerializableJsFunction(source, isFunction); + } } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsWrapperBaseFactory.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsWrapperBaseFactory.java index eee2f8c8..4edc3cc4 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsWrapperBaseFactory.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsWrapperBaseFactory.java @@ -18,6 +18,8 @@ package org.wso2.carbon.identity.conditional.auth.functions.user.model; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.GenericSerializableJsFunction; +import org.wso2.carbon.identity.application.authentication.framework.model.Application; import org.wso2.carbon.identity.application.authentication.framework.model.UserSession; /** @@ -32,5 +34,19 @@ public interface JsWrapperBaseFactory { */ JsUserSession createJsUserSession(UserSession userSession); + /** + * Creates a JavaScript Proxy for Application. + * @param application - Represent Application Subject + * @return Proxy for Application + */ + JsApplication createJsApplication(Application application); + /** + * Creates a Serializable Javascript function. + * + * @param source - Source of the function + * @param isFunction - Is the source a function + * @return Serializable Javascript function + */ + GenericSerializableJsFunction createJsSerializableFunction(String source, boolean isFunction); } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsWrapperFactory.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsWrapperFactory.java index 80848481..229eb3c3 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsWrapperFactory.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsWrapperFactory.java @@ -18,7 +18,10 @@ package org.wso2.carbon.identity.conditional.auth.functions.user.model; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.SerializableJsFunction; +import org.wso2.carbon.identity.application.authentication.framework.model.Application; import org.wso2.carbon.identity.application.authentication.framework.model.UserSession; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.nashorn.JsNashornApplication; import org.wso2.carbon.identity.conditional.auth.functions.user.model.nashorn.JsNashornUserSession; /** @@ -30,4 +33,13 @@ public class JsWrapperFactory implements JsWrapperBaseFactory { public JsUserSession createJsUserSession(UserSession userSession) { return new JsNashornUserSession(userSession); } + + public JsApplication createJsApplication(Application application) { + return new JsNashornApplication(application); + } + + public SerializableJsFunction createJsSerializableFunction(String source, boolean isFunction) { + + return new SerializableJsFunction(source, isFunction); + } } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsWrapperFactoryProvider.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsWrapperFactoryProvider.java index 27308c67..c6e35ec4 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsWrapperFactoryProvider.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/JsWrapperFactoryProvider.java @@ -18,6 +18,8 @@ package org.wso2.carbon.identity.conditional.auth.functions.user.model; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JsGenericGraphBuilderFactory; +import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.graaljs.JsGraalGraphBuilderFactory; import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.openjdk.nashorn.JsOpenJdkNashornGraphBuilderFactory; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils; @@ -32,8 +34,11 @@ public class JsWrapperFactoryProvider { private JsWrapperFactoryProvider() { - if (FrameworkUtils.createJsGraphBuilderFactoryFromConfig() instanceof JsOpenJdkNashornGraphBuilderFactory) { + JsGenericGraphBuilderFactory jsGraphBuilderFactory = FrameworkUtils.createJsGraphBuilderFactoryFromConfig(); + if (jsGraphBuilderFactory instanceof JsOpenJdkNashornGraphBuilderFactory) { jsWrapperBaseFactory = new JsOpenJdkNashornWrapperFactory(); + } else if (jsGraphBuilderFactory instanceof JsGraalGraphBuilderFactory) { + jsWrapperBaseFactory = new JsGraalWrapperFactory(); } else { jsWrapperBaseFactory = new JsWrapperFactory(); } diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/graaljs/JsGraalApplication.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/graaljs/JsGraalApplication.java new file mode 100644 index 00000000..994792ae --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/graaljs/JsGraalApplication.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user.model.graaljs; + +import org.graalvm.polyglot.Value; +import org.graalvm.polyglot.proxy.ProxyArray; +import org.graalvm.polyglot.proxy.ProxyObject; +import org.wso2.carbon.identity.application.authentication.framework.model.Application; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsApplication; + +/** + * Javascript wrapper for Java level Application. + * This provides controlled access to UserSession object via provided javascript native syntax. + * Also, it prevents writing an arbitrary values to the respective fields, keeping consistency on runtime + * AuthenticatedUser. + * + * @see Application + */ +public class JsGraalApplication extends JsApplication implements ProxyObject { + + public JsGraalApplication(Application wrappedApplication) { + + super(wrappedApplication); + } + + @Override + public Object getMemberKeys() { + + return ProxyArray.fromArray("subject", "appName", "appId"); + } + + @Override + public boolean hasMember(String key) { + + return "subject".equals(key) || "appName".equals(key) || "appId".equals(key); + } + + @Override + public Object getMember(String name) { + + switch (name) { + case "subject": + return getWrapped().getSubject(); + case "appName": + return getWrapped().getAppName(); + case "appId": + return getWrapped().getAppId(); + default: + return super.getMember(name); + } + } + + @Override + public void putMember(String key, Value value) { + + // read-only object. + } +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/graaljs/JsGraalUserAgent.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/graaljs/JsGraalUserAgent.java new file mode 100644 index 00000000..98f44ae4 --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/graaljs/JsGraalUserAgent.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user.model.graaljs; + +import org.graalvm.polyglot.Value; +import org.graalvm.polyglot.proxy.ProxyObject; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsUserAgent; +import org.wso2.carbon.identity.core.model.UserAgent; + +/** + * Javascript wrapper for Java level UserAgent. + * This provides controlled access to UserSession object via provided javascript native syntax. + * Also, it prevents writing an arbitrary values to the respective fields, keeping consistency on runtime + * AuthenticatedUser. + * + * @see UserAgent + */ +public class JsGraalUserAgent extends JsUserAgent implements ProxyObject { + + public JsGraalUserAgent(UserAgent wrappedUserAgent) { + + super(wrappedUserAgent); + } + + @Override + public Object getMemberKeys() { + + return new String[]{"rawString", "browser", "platform", "device"}; + } + + @Override + public boolean hasMember(String key) { + + return "rawString".equals(key) || "browser".equals(key) || "platform".equals(key) || "device".equals(key); + } + + @Override + public void putMember(String key, Value value) { + + // read-only object. + } + + @Override + public Object getMember(String name) { + + switch (name) { + case "rawString": + return getWrapped().getRawString(); + case "browser": + return getWrapped().getBrowser(); + case "platform": + return getWrapped().getPlatform(); + case "device": + return getWrapped().getDevice(); + default: + return super.getMember(name); + } + } +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/graaljs/JsGraalUserSession.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/graaljs/JsGraalUserSession.java new file mode 100644 index 00000000..2f4b9084 --- /dev/null +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/user/model/graaljs/JsGraalUserSession.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.conditional.auth.functions.user.model.graaljs; + +import org.graalvm.polyglot.Value; +import org.graalvm.polyglot.proxy.ProxyObject; +import org.wso2.carbon.identity.application.authentication.framework.model.UserSession; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsUserSession; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.nashorn.JsNashornApplication; +import org.wso2.carbon.identity.conditional.auth.functions.user.model.nashorn.JsNashornUserAgent; +import org.wso2.carbon.identity.core.model.UserAgent; + +import java.util.stream.Collectors; + +/** + * Javascript wrapper for Java level UserSession. + * This provides controlled access to UserSession object via provided javascript native syntax. + * Also it prevents writing an arbitrary values to the respective fields, keeping consistency on runtime + * AuthenticatedUser. + * + * @see UserSession + */ +public class JsGraalUserSession extends JsUserSession implements ProxyObject { + + private final UserAgent userAgent; + + public JsGraalUserSession(UserSession wrappedUserSession) { + + super(wrappedUserSession); + userAgent = new UserAgent(wrappedUserSession.getUserAgent()); + } + + @Override + public Object getMemberKeys() { + + return new String[]{"id", "createdTimestamp", "lastAccessTime", "tenantDomain", "user", "application", + "userAgent"}; + } + + @Override + public boolean hasMember(String key) { + + return "id".equals(key) || "createdTimestamp".equals(key) || "lastAccessTime".equals(key) || + "tenantDomain".equals(key) || "user".equals(key) || "application".equals(key) || + "userAgent".equals(key); + } + + @Override + public void putMember(String key, Value value) { + + // read-only object. + } + + @Override + public Object getMember(String name) { + + switch (name) { + case "userAgent": + return new JsNashornUserAgent(userAgent); + case "ip": + return getWrapped().getIp(); + case "loginTime": + return getWrapped().getLoginTime(); + case "lastAccessTime": + return getWrapped().getLastAccessTime(); + case "id": + return getWrapped().getSessionId(); + case "applications": + return getWrapped().getApplications().stream().map(JsNashornApplication::new) + .collect(Collectors.toList()); + default: + return super.getMember(name); + } + } +} diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesFunctionImplTest.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesFunctionImplTest.java index ee02610e..2357febf 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesFunctionImplTest.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasAnyOfTheRolesFunctionImplTest.java @@ -55,8 +55,6 @@ public class HasAnyOfTheRolesFunctionImplTest extends JsSequenceHandlerAbstractT @BeforeMethod protected void setUp() throws Exception { - super.setUp(); - CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME = true; sequenceHandlerRunner.registerJsFunction("hasAnyOfTheRoles", new HasAnyOfTheRolesFunctionImpl()); UserRealm userRealm = realmService.getTenantUserRealm(-1234); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasRoleFunctionImplTest.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasRoleFunctionImplTest.java index e2751916..53fd21ea 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasRoleFunctionImplTest.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/HasRoleFunctionImplTest.java @@ -57,8 +57,6 @@ public class HasRoleFunctionImplTest extends JsSequenceHandlerAbstractTest { @BeforeMethod protected void setUp() throws Exception { - super.setUp(); - CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME = true; sequenceHandlerRunner.registerJsFunction("hasRole", new HasRoleFunctionImpl()); UserRealm userRealm = realmService.getTenantUserRealm(-1234); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/IsMemberOfAnyOfGroupsFunctionImplTest.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/IsMemberOfAnyOfGroupsFunctionImplTest.java index 7b8afd19..84ea0349 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/IsMemberOfAnyOfGroupsFunctionImplTest.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/IsMemberOfAnyOfGroupsFunctionImplTest.java @@ -55,7 +55,6 @@ public class IsMemberOfAnyOfGroupsFunctionImplTest extends JsSequenceHandlerAbst @BeforeMethod protected void setUp() throws Exception { - super.setUp(); CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME = true; sequenceHandlerRunner.registerJsFunction("isMemberOfAnyOfGroups", new IsMemberOfAnyOfGroupsFunctionImpl()); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/UpdateUserPasswordFunctionImplTest.java b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/UpdateUserPasswordFunctionImplTest.java index 84ab0c71..0c3b93fc 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/UpdateUserPasswordFunctionImplTest.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/user/UpdateUserPasswordFunctionImplTest.java @@ -23,6 +23,7 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; +import org.testng.annotations.Parameters; import org.testng.annotations.Test; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.base.ServerConfiguration; @@ -82,9 +83,10 @@ public class UpdateUserPasswordFunctionImplTest extends JsSequenceHandlerAbstrac private UpdateUserPasswordFunctionImpl testFunction; @BeforeClass - public void setUp() throws Exception { + @Parameters({"scriptEngine"}) + public void setUp(String scriptEngine) throws Exception { - super.setUp(); + super.setUp(scriptEngine); CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME = true; sequenceHandlerRunner.registerJsFunction("updateUserPassword", new UpdateUserPasswordFunctionImpl()); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/resources/testng.xml b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/resources/testng.xml index 0138bf73..aca467db 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/resources/testng.xml +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.user/src/test/resources/testng.xml @@ -11,15 +11,16 @@ ~ Unless required by applicable law or agreed to in writing, ~ software distributed under the License is distributed on an ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - ~ KIND, either express or implied. See the License for the + ~ KIND, either express or implied. See the License for the ~ specific language governing permissions and limitations ~ under the License. --> - - + + + @@ -27,4 +28,13 @@ - + + + + + + + + + + \ No newline at end of file diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/utils/FilterAuthenticatorsFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/utils/FilterAuthenticatorsFunctionImpl.java index 15ee47e2..6eb6b933 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/utils/FilterAuthenticatorsFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/utils/FilterAuthenticatorsFunctionImpl.java @@ -19,6 +19,7 @@ package org.wso2.carbon.identity.conditional.auth.functions.utils; import org.apache.commons.lang.StringUtils; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; import java.util.HashMap; import java.util.List; @@ -29,6 +30,7 @@ */ public class FilterAuthenticatorsFunctionImpl implements FilterAuthenticatorsFunction { @Override + @HostAccess.Export public Map> filterAuthenticators(List> authenticatorOptions, String excludeAuthenticator) { diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/utils/ResolveMultiAttributeLoginIdentifierFunctionImpl.java b/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/utils/ResolveMultiAttributeLoginIdentifierFunctionImpl.java index 776053e2..747f9c4e 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/utils/ResolveMultiAttributeLoginIdentifierFunctionImpl.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/utils/ResolveMultiAttributeLoginIdentifierFunctionImpl.java @@ -18,6 +18,7 @@ package org.wso2.carbon.identity.conditional.auth.functions.utils; +import org.graalvm.polyglot.HostAccess; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils; import org.wso2.carbon.identity.multi.attribute.login.mgt.ResolvedUserResult; @@ -27,6 +28,7 @@ public class ResolveMultiAttributeLoginIdentifierFunctionImpl implements ResolveMultiAttributeLoginIdentifierFunction { @Override + @HostAccess.Export public String resolveMultiAttributeLoginIdentifier(String loginIdentifier, String tenantDomain) { ResolvedUserResult resolvedUserResult = FrameworkUtils.processMultiAttributeLoginIdentification( diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/utils/ResolveMultiAttributeLoginIdentifierFunctionImplTest.java b/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/utils/ResolveMultiAttributeLoginIdentifierFunctionImplTest.java index 50c4d398..9cfef8ef 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/utils/ResolveMultiAttributeLoginIdentifierFunctionImplTest.java +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/test/java/org/wso2/carbon/identity/conditional/auth/functions/utils/ResolveMultiAttributeLoginIdentifierFunctionImplTest.java @@ -22,6 +22,7 @@ import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; +import org.testng.annotations.Parameters; import org.testng.annotations.Test; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.identity.application.authentication.framework.config.model.SequenceConfig; @@ -59,9 +60,10 @@ public class ResolveMultiAttributeLoginIdentifierFunctionImplTest extends JsSequ private MultiAttributeLoginService multiAttributeLoginServiceMock; @BeforeClass - public void setUp() throws Exception { + @Parameters({"scriptEngine"}) + public void setUp(String scriptEngine) throws Exception { - super.setUp(); + super.setUp(scriptEngine); CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME = true; sequenceHandlerRunner.registerJsFunction("resolveMultiAttributeLoginIdentifier", new ResolveMultiAttributeLoginIdentifierFunctionImpl()); diff --git a/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/test/resources/testng.xml b/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/test/resources/testng.xml index f2499701..c334b444 100644 --- a/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/test/resources/testng.xml +++ b/components/org.wso2.carbon.identity.conditional.auth.functions.utils/src/test/resources/testng.xml @@ -19,7 +19,14 @@ - + + + + + + + + diff --git a/pom.xml b/pom.xml index 017cc656..85b2e172 100644 --- a/pom.xml +++ b/pom.xml @@ -180,9 +180,9 @@ ${json.wso2.version} - net.minidev - json-smart - ${json-smart.version} + net.minidev + json-smart + ${json-smart.version} @@ -299,6 +299,12 @@ ${nashorn.core.version} provided + + org.graalvm.sdk + graal-sdk + ${graalvm.version} + provided + javax.ws.rs jsr311-api @@ -493,7 +499,7 @@ 4.9.17 [4.6.0, 5.0.0) [1.0.1, 2.0.0) - 5.25.509 + 7.2.29 1.0.89 5.20.447 [5.14.0, 8.0.0) @@ -543,6 +549,7 @@ [1.9.0,2.0.0) 1.4.01 15.3 + 22.3.4 **/*Exception.java, **/*Constants*.java,