product-is icon indicating copy to clipboard operation
product-is copied to clipboard

Unable to use parseInt with setCookie in adaptive script

Open rksk opened this issue 6 months ago • 0 comments

Describe the issue: When parseInt() is used with Java 11, it was considered an Integer at java level and can be used for max-age property of setCookie() function (see the below adaptive script sample).

But once migrated to a newer IS version and Java 17 is used, the same parseInt() returns a double at Java level and the casting into Integer breaks at [1]. It seems somehow when the OpenJdkNashorn is used with Java 17, the behaviour difference has occurred.

As per the community [2], one should not expect a java.lang.Integer specifically but java.lang.Number and cast appropriately when using Nashorn.

The following was tried out at [1] and it worked fine for both Java versions.

Optional.ofNullable(properties.get(FrameworkConstants.JSAttributes.JS_COOKIE_MAX_AGE))
        .filter(Number.class::isInstance)
        .map(Number.class::cast)
        .map(Number::intValue)
        .ifPresent(cookie::setMaxAge);

Optional.ofNullable(properties.get(FrameworkConstants.JSAttributes.JS_COOKIE_VERSION))
        .filter(Number.class::isInstance)
        .map(Number.class::cast)
        .map(Number::intValue)
        .ifPresent(cookie::setVersion);

[1] https://github.com/wso2-extensions/identity-conditional-auth-functions/blob/f7a433a7d1ca328051316bb52382b21927a26088/components/org.wso2.carbon.identity.conditional.auth.functions.http/src/main/java/org/wso2/carbon/identity/conditional/auth/functions/http/SetCookieFunctionImpl.java#L104 [2] https://stackoverflow.com/a/25996818

How to reproduce:

  • Setup Java 17 and execute <IS_HOME>/bin/adaptive.sh
  • Create a service provider and add following adaptive script (this is a dummy script to demostate the issue)
var sessionAge;

var onLoginRequest = function(context) {

    sessionAge = context.request.params.age[0];   
    Log.info("Session Age: " + sessionAge);

    executeStep(1, {
        onSuccess: function(context) {
            var username = context.steps[1].subject.username;

            if (sessionAge) {
                Log.info("Going to invoke setCookie()");
                setCookie(context.response, "savedUsername", username, {
                    "max-age": parseInt(sessionAge),
                    "path": "/",
                    "httpOnly": true,
                    "secure": true,
                    "sameSite": "STRICT"
                });
            }

        }
    });
};
  • Start an authentication flow with additional query param age=1234
  • Once step 1 is completed, the following error can be observed
ERROR {org.wso2.carbon.identity.application.authentication.framework.config.model.graph.openjdk.nashorn.JsOpenJdkNashornGraphBuilder} - Error in executing the javascript for service provider : test, Javascript Fragment : 
function(context) {
            var username = context.steps[1].subject.username;

            if (sessionAge) {
                Log.info("Going to invoke setCookie()");
                setCookie(context.response, "savedUsername", username, {
                    "max-age": parseInt(sessionAge),
                    "path": "/",
                    "httpOnly": true,
                    "secure": true,
                    "sameSite": "STRICT"
                });
            }

        } java.lang.ClassCastException: class java.lang.Double cannot be cast to class java.lang.Integer (java.lang.Double and java.lang.Integer are in module java.base of loader 'bootstrap')
	at org.wso2.carbon.identity.conditional.auth.functions.http.CookieFunctionImpl.setCookie(CookieFunctionImpl.java:108)
	at org.openjdk.nashorn.internal.scripts.Script$Recompilation$14$\^eval\_/0x00000008018ef840.L:1(<eval>:7)
	at org.openjdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:648)
	at org.openjdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:513)
	at org.openjdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:520)
	at org.openjdk.nashorn.api.scripting.ScriptObjectMirror.call(ScriptObjectMirror.java:111)
	at org.wso2.carbon.identity.application.authentication.framework.config.model.graph.openjdk.nashorn.OpenJdkNashornSerializableJsFunction.apply(OpenJdkNashornSerializableJsFunction.java:85)
	at org.wso2.carbon.identity.application.authentication.framework.config.model.graph.openjdk.nashorn.JsOpenJdkNashornGraphBuilder$JsBasedEvaluator.evaluate(JsOpenJdkNashornGraphBuilder.java:1208)
	at org.wso2.carbon.identity.application.authentication.framework.handler.sequence.impl.GraphBasedSequenceHandler.executeFunction(GraphBasedSequenceHandler.java:722)
	at org.wso2.carbon.identity.application.authentication.framework.handler.sequence.impl.GraphBasedSequenceHandler.handleDecisionPoint(GraphBasedSequenceHandler.java:685)
	at org.wso2.carbon.identity.application.authentication.framework.handler.sequence.impl.GraphBasedSequenceHandler.handleNode(GraphBasedSequenceHandler.java:200)
	at org.wso2.carbon.identity.application.authentication.framework.handler.sequence.impl.GraphBasedSequenceHandler.handle(GraphBasedSequenceHandler.java:152)
	at org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultAuthenticationRequestHandler.handle(DefaultAuthenticationRequestHandler.java:194)
	at org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultRequestCoordinator.handle(DefaultRequestCoordinator.java:320)
	at org.wso2.carbon.identity.application.authentication.framework.CommonAuthenticationHandler.doPost(CommonAuthenticationHandler.java:50)
	at org.wso2.carbon.identity.application.authentication.framework.CommonAuthenticationHandler.doGet(CommonAuthenticationHandler.java:41)
	at org.wso2.carbon.identity.oauth.endpoint.authz.OAuth2AuthzEndpoint.handleAuthFlowThroughFramework(OAuth2AuthzEndpoint.java:3557)
	at org.wso2.carbon.identity.oauth.endpoint.authz.OAuth2AuthzEndpoint.handleInitialAuthorizationRequest(OAuth2AuthzEndpoint.java:1266)
	at org.wso2.carbon.identity.oauth.endpoint.authz.OAuth2AuthzEndpoint.authorize(OAuth2AuthzEndpoint.java:300)
  • But this works fine if Java 11 is used (without executing adaptive.sh)

Expected behavior: The adaptive script should work with the same syntax after version migration

Environment information

  • Product Version: IS 6.1.0
  • Java version: 17

rksk avatar Aug 08 '24 07:08 rksk