diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/config/model/graph/js/JsAuthenticationContext.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/config/model/graph/js/JsAuthenticationContext.java index b5fe034b08c9..6942f2a3b3c1 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/config/model/graph/js/JsAuthenticationContext.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/config/model/graph/js/JsAuthenticationContext.java @@ -19,6 +19,7 @@ package org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js; import org.wso2.carbon.identity.application.authentication.framework.context.AuthenticationContext; +import org.wso2.carbon.identity.application.authentication.framework.context.TransientObjectWrapper; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; /** @@ -38,6 +39,7 @@ public class JsAuthenticationContext extends AbstractJSObjectWrapper { public JsAuthenticationContext(AuthenticationContext wrapped) { + super(wrapped); } @@ -45,22 +47,22 @@ public JsAuthenticationContext(AuthenticationContext wrapped) { public Object getMember(String name) { switch (name) { - case FrameworkConstants.JSAttributes.JS_REQUESTED_ACR: - return getWrapped().getRequestedAcr(); - case FrameworkConstants.JSAttributes.JS_AUTHENTICATED_SUBJECT: - return new JsAuthenticatedUser(getWrapped().getSubject()); - case FrameworkConstants.JSAttributes.JS_LAST_AUTHENTICATED_USER: - return new JsAuthenticatedUser(getWrapped().getLastAuthenticatedUser()); - case FrameworkConstants.JSAttributes.JS_TENANT_DOMAIN: - return getWrapped().getTenantDomain(); - case FrameworkConstants.JSAttributes.JS_INITIAL_REQUEST: - return new JsServletRequest(getWrapped().getInitialRequest()); - case FrameworkConstants.JSAttributes.JS_REQUEST: - return new JsServletRequest(getWrapped().getRequest()); - case FrameworkConstants.JSAttributes.JS_RESPONSE: - return new JsServletResponse(getWrapped().getResponse()); - default: - return super.getMember(name); + case FrameworkConstants.JSAttributes.JS_REQUESTED_ACR: + return getWrapped().getRequestedAcr(); + case FrameworkConstants.JSAttributes.JS_AUTHENTICATED_SUBJECT: + return new JsAuthenticatedUser(getWrapped().getSubject()); + case FrameworkConstants.JSAttributes.JS_LAST_AUTHENTICATED_USER: + return new JsAuthenticatedUser(getWrapped().getLastAuthenticatedUser()); + case FrameworkConstants.JSAttributes.JS_TENANT_DOMAIN: + return getWrapped().getTenantDomain(); + case FrameworkConstants.JSAttributes.JS_REQUEST: + return new JsServletRequest((TransientObjectWrapper) getWrapped() + .getParameter(FrameworkConstants.RequestAttribute.HTTP_REQUEST)); + case FrameworkConstants.JSAttributes.JS_RESPONSE: + return new JsServletResponse((TransientObjectWrapper) getWrapped() + .getParameter(FrameworkConstants.RequestAttribute.HTTP_REQUEST)); + default: + return super.getMember(name); } } @@ -68,22 +70,20 @@ public Object getMember(String name) { public boolean hasMember(String name) { switch (name) { - case FrameworkConstants.JSAttributes.JS_REQUESTED_ACR: - return getWrapped().getRequestedAcr() != null; - case FrameworkConstants.JSAttributes.JS_AUTHENTICATED_SUBJECT: - return getWrapped().getSubject() != null; - case FrameworkConstants.JSAttributes.JS_LAST_AUTHENTICATED_USER: - return getWrapped().getLastAuthenticatedUser() != null; - case FrameworkConstants.JSAttributes.JS_TENANT_DOMAIN: - return getWrapped().getTenantDomain() != null; - case FrameworkConstants.JSAttributes.JS_INITIAL_REQUEST: - return getWrapped().getInitialRequest() != null; - case FrameworkConstants.JSAttributes.JS_REQUEST: - return getWrapped().getRequest() != null; - case FrameworkConstants.JSAttributes.JS_RESPONSE: - return getWrapped().getResponse() != null; - default: - return super.hasMember(name); + case FrameworkConstants.JSAttributes.JS_REQUESTED_ACR: + return getWrapped().getRequestedAcr() != null; + case FrameworkConstants.JSAttributes.JS_AUTHENTICATED_SUBJECT: + return getWrapped().getSubject() != null; + case FrameworkConstants.JSAttributes.JS_LAST_AUTHENTICATED_USER: + return getWrapped().getLastAuthenticatedUser() != null; + case FrameworkConstants.JSAttributes.JS_TENANT_DOMAIN: + return getWrapped().getTenantDomain() != null; + case FrameworkConstants.JSAttributes.JS_REQUEST: + return hasTransientValueInParameters(FrameworkConstants.RequestAttribute.HTTP_REQUEST); + case FrameworkConstants.JSAttributes.JS_RESPONSE: + return hasTransientValueInParameters(FrameworkConstants.RequestAttribute.HTTP_RESPONSE); + default: + return super.hasMember(name); } } @@ -91,11 +91,11 @@ public boolean hasMember(String name) { public void removeMember(String name) { switch (name) { - case FrameworkConstants.JSAttributes.JS_SELECTED_ACR: - getWrapped().setSelectedAcr(null); - break; - default: - super.removeMember(name); + case FrameworkConstants.JSAttributes.JS_SELECTED_ACR: + getWrapped().setSelectedAcr(null); + break; + default: + super.removeMember(name); } } @@ -103,11 +103,17 @@ public void removeMember(String name) { public void setMember(String name, Object value) { switch (name) { - case FrameworkConstants.JSAttributes.JS_SELECTED_ACR: - getWrapped().setSelectedAcr(String.valueOf(value)); - break; - default: - super.setMember(name, value); + case FrameworkConstants.JSAttributes.JS_SELECTED_ACR: + getWrapped().setSelectedAcr(String.valueOf(value)); + break; + default: + super.setMember(name, value); } } + + private boolean hasTransientValueInParameters(String key) { + + TransientObjectWrapper transientObjectWrapper = (TransientObjectWrapper) getWrapped().getParameter(key); + return transientObjectWrapper != null && transientObjectWrapper.getWrapped() != null; + } } diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/config/model/graph/js/JsServletRequest.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/config/model/graph/js/JsServletRequest.java index fca358d80e12..fb513656a16b 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/config/model/graph/js/JsServletRequest.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/config/model/graph/js/JsServletRequest.java @@ -18,13 +18,14 @@ package org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js; +import org.wso2.carbon.identity.application.authentication.framework.context.TransientObjectWrapper; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; /** * Javascript wrapper for Java level HTTPServletRequest. @@ -37,9 +38,10 @@ *

* Also it prevents writing an arbitrary values to the respective fields, keeping consistency on runtime HTTPServletRequest. */ -public class JsServletRequest extends AbstractJSObjectWrapper { +public class JsServletRequest extends AbstractJSObjectWrapper> { + + public JsServletRequest(TransientObjectWrapper wrapped) { - public JsServletRequest(HttpServletRequest wrapped) { super(wrapped); } @@ -47,44 +49,56 @@ public JsServletRequest(HttpServletRequest wrapped) { public Object getMember(String name) { switch (name) { - case FrameworkConstants.JSAttributes.JS_HEADERS: - Map headers = new HashMap(); - Enumeration headerNames = getWrapped().getHeaderNames(); - if (headerNames != null) { - while (headerNames.hasMoreElements()) { - String headerName = headerNames.nextElement(); - headers.put(headerName, getWrapped().getHeader(headerName)); - } + case FrameworkConstants.JSAttributes.JS_HEADERS: + Map headers = new HashMap(); + Enumeration headerNames = getRequest().getHeaderNames(); + if (headerNames != null) { + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + headers.put(headerName, getRequest().getHeader(headerName)); } - return new JsParameters(headers); - case FrameworkConstants.JSAttributes.JS_PARAMS: - return new JsParameters(getWrapped().getParameterMap()); - case FrameworkConstants.JSAttributes.JS_COOKIES: - Map cookies = new HashMap(); - Cookie[] cookieArr = getWrapped().getCookies(); - if(cookieArr != null) { - for (Cookie cookie : cookieArr) { - cookies.put(cookie.getName(), new JsCookie(cookie)); - } + } + return new JsParameters(headers); + case FrameworkConstants.JSAttributes.JS_PARAMS: + return new JsParameters(getRequest().getParameterMap()); + case FrameworkConstants.JSAttributes.JS_COOKIES: + Map cookies = new HashMap(); + Cookie[] cookieArr = getRequest().getCookies(); + if (cookieArr != null) { + for (Cookie cookie : cookieArr) { + cookies.put(cookie.getName(), new JsCookie(cookie)); } - return new JsParameters(cookies); - default: - return super.getMember(name); + } + return new JsParameters(cookies); + default: + return super.getMember(name); } } @Override public boolean hasMember(String name) { + + if (getRequest() == null) { + //Transient Object is null, hence no member access is possible. + return false; + } + switch (name) { - case FrameworkConstants.JSAttributes.JS_HEADERS: - return getWrapped().getHeaderNames() != null; - case FrameworkConstants.JSAttributes.JS_PARAMS: - return getWrapped().getParameterMap() != null; - case FrameworkConstants.JSAttributes.JS_COOKIES: - return getWrapped().getCookies() != null; - default: - return super.hasMember(name); + case FrameworkConstants.JSAttributes.JS_HEADERS: + return getRequest().getHeaderNames() != null; + case FrameworkConstants.JSAttributes.JS_PARAMS: + return getRequest().getParameterMap() != null; + case FrameworkConstants.JSAttributes.JS_COOKIES: + return getRequest().getCookies() != null; + default: + return super.hasMember(name); } } + + private HttpServletRequest getRequest() { + + TransientObjectWrapper transientObjectWrapper = getWrapped(); + return transientObjectWrapper.getWrapped(); + } } diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/config/model/graph/js/JsServletResponse.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/config/model/graph/js/JsServletResponse.java index 96e3dfddfeb3..b38d741f9f51 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/config/model/graph/js/JsServletResponse.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/config/model/graph/js/JsServletResponse.java @@ -18,12 +18,13 @@ package org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js; +import org.wso2.carbon.identity.application.authentication.framework.context.TransientObjectWrapper; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; -import javax.servlet.http.HttpServletResponse; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import javax.servlet.http.HttpServletResponse; /** * Javascript wrapper for Java level HttpServletResponse. @@ -36,9 +37,10 @@ *

* Also it prevents writing an arbitrary values to the respective fields, keeping consistency on runtime HttpServletResponse. */ -public class JsServletResponse extends AbstractJSObjectWrapper { +public class JsServletResponse extends AbstractJSObjectWrapper> { + + public JsServletResponse(TransientObjectWrapper wrapped) { - public JsServletResponse(HttpServletResponse wrapped) { super(wrapped); } @@ -46,28 +48,39 @@ public JsServletResponse(HttpServletResponse wrapped) { public Object getMember(String name) { switch (name) { - case FrameworkConstants.JSAttributes.JS_HEADERS: - Map headers = new HashMap(); - Collection headerNames = getWrapped().getHeaderNames(); - if (headerNames != null) { - for (String element : headerNames) { - headers.put(element, getWrapped().getHeader(element)); - } + case FrameworkConstants.JSAttributes.JS_HEADERS: + Map headers = new HashMap(); + Collection headerNames = getResponse().getHeaderNames(); + if (headerNames != null) { + for (String element : headerNames) { + headers.put(element, getResponse().getHeader(element)); } - return new JsHeaders(headers, getWrapped()); - default: - return super.getMember(name); + } + return new JsHeaders(headers, getResponse()); + default: + return super.getMember(name); } } @Override public boolean hasMember(String name) { + if (getResponse() == null) { + //Transient Object is null, hence no member access is possible. + return false; + } + switch (name) { - case FrameworkConstants.JSAttributes.JS_HEADERS: - return getWrapped().getHeaderNames() != null; - default: - return super.hasMember(name); + case FrameworkConstants.JSAttributes.JS_HEADERS: + return getResponse().getHeaderNames() != null; + default: + return super.hasMember(name); } } + + private HttpServletResponse getResponse() { + + TransientObjectWrapper transientObjectWrapper = getWrapped(); + return transientObjectWrapper.getWrapped(); + } } diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/context/AuthenticationContext.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/context/AuthenticationContext.java index 3d22b1d58b12..ba1d115f8a47 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/context/AuthenticationContext.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/context/AuthenticationContext.java @@ -32,8 +32,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; /** * This class is used for holding data about the @@ -53,7 +51,6 @@ public class AuthenticationContext extends MessageContext implements Serializabl private boolean isLogoutRequest; private int currentStep; private SequenceConfig sequenceConfig; - private HttpServletRequest currentRequest; private ExternalIdPConfig externalIdP; private boolean rememberMe; private String tenantDomain; @@ -99,9 +96,6 @@ public class AuthenticationContext extends MessageContext implements Serializabl */ private AuthenticatorStateInfo stateInfo; - private transient HttpServletRequest request; - private transient HttpServletResponse response; - private transient HttpServletRequest initialRequest; private List executedPostAuthHandlers = new ArrayList<>(); public String getCallerPath() { @@ -183,14 +177,6 @@ public void setContextIdentifier(String contextIdentifier) { this.contextIdentifier = contextIdentifier; } - public HttpServletRequest getCurrentRequest() { - return currentRequest; - } - - public void setCurrentRequest(HttpServletRequest currentRequest) { - this.currentRequest = currentRequest; - } - public boolean isRequestAuthenticated() { return requestAuthenticated; } @@ -425,43 +411,13 @@ public void addRequestedAcr(String acr) { /** * Returns the Authenticated user who is known as at the moment. * Use this to get the user details for any multi-factor authenticator which depends on previously known subject. - * + * * @return AuthenticatedUser which is assigned to the context last. Null if no previous step could find a user. */ public AuthenticatedUser getLastAuthenticatedUser() { return lastAuthenticatedUser; } - public void setRequest(HttpServletRequest request) { - - this.request = request; - } - - public HttpServletRequest getRequest() { - - return this.request; - } - - public void setInitialRequest(HttpServletRequest request) { - - this.initialRequest = request; - } - - public HttpServletRequest getInitialRequest() { - - return this.initialRequest; - } - - public void setResponse(HttpServletResponse response) { - - this.response = response; - } - - public HttpServletResponse getResponse() { - - return this.response; - } - /** * Returns current post authentication handler index which is in execution. * diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/context/TransientObjectWrapper.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/context/TransientObjectWrapper.java new file mode 100644 index 000000000000..20d97ebaf820 --- /dev/null +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/context/TransientObjectWrapper.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.application.authentication.framework.context; + +import java.io.Serializable; +import java.lang.ref.WeakReference; + +/** + * A non-serializable object to be carried across the authentication context. + * Authentication context is a serializable object. Some objects should not be serialized as they are valid only to the current request. + * e.g. HTTP Request object. + * The data is held only for the lifetime of the current request. After that GC will remove the data freely. + */ +public class TransientObjectWrapper implements Serializable { + + private transient WeakReference wrapped; + + public TransientObjectWrapper(T wrapped) { + + this.wrapped = new WeakReference<>(wrapped); + } + + public T getWrapped() { + + return wrapped.get(); + } +} diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/DefaultRequestCoordinator.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/DefaultRequestCoordinator.java index a21b4676ef16..6f7f898a6912 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/DefaultRequestCoordinator.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/DefaultRequestCoordinator.java @@ -33,6 +33,7 @@ import org.wso2.carbon.identity.application.authentication.framework.config.model.SequenceConfig; import org.wso2.carbon.identity.application.authentication.framework.context.AuthenticationContext; import org.wso2.carbon.identity.application.authentication.framework.context.SessionContext; +import org.wso2.carbon.identity.application.authentication.framework.context.TransientObjectWrapper; import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; import org.wso2.carbon.identity.application.authentication.framework.exception.PostAuthenticationFailedException; import org.wso2.carbon.identity.application.authentication.framework.handler.request.RequestCoordinator; @@ -143,11 +144,7 @@ public void handle(HttpServletRequest request, HttpServletResponse response) thr } else { returning = true; context = FrameworkUtils.getContextData(request); - if (context != null) { - // set current request and response to the authentication context. - context.setRequest(request); - context.setResponse(response); - } + associateTransientRequestData(request, response, context); } if (context != null) { @@ -200,6 +197,21 @@ public void handle(HttpServletRequest request, HttpServletResponse response) thr } } + /** + * Associates the transient request data to the Authentication Context. + * + * @param request + * @param response + * @param context + */ + private void associateTransientRequestData(HttpServletRequest request, HttpServletResponse response, + AuthenticationContext context) { + + // set current request and response to the authentication context. + context.setProperty(FrameworkConstants.RequestAttribute.HTTP_REQUEST, new TransientObjectWrapper(request)); + context.setProperty(FrameworkConstants.RequestAttribute.HTTP_RESPONSE, new TransientObjectWrapper(response)); + } + /** * Returns true if the request is a CommonAuth logout request. * @param request @@ -272,9 +284,6 @@ protected AuthenticationContext initializeFlow(HttpServletRequest request, // generate a new key to hold the context data object String contextId = UUIDGenerator.generateUUID(); context.setContextIdentifier(contextId); - context.setInitialRequest(request); - context.setRequest(request); - context.setResponse(response); if (log.isDebugEnabled()) { log.debug("Framework contextId: " + contextId); @@ -310,6 +319,7 @@ protected AuthenticationContext initializeFlow(HttpServletRequest request, } } + associateTransientRequestData(request, response, context); findPreviousAuthenticatedSession(request, context); buildOutboundQueryString(request, context); diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkConstants.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkConstants.java index 34a682265455..a6e792d58068 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkConstants.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkConstants.java @@ -215,6 +215,8 @@ public static class RequestAttribute { public static final String SESSION_DATA = "sessionData"; public static final String AUTH_RESULT = "authResult"; public static final String AUTH_REQUEST = "authRequest"; + public static final String HTTP_REQUEST = "HttpServletRequest"; + public static final String HTTP_RESPONSE = "HttpServletResponse"; private RequestAttribute() { } @@ -246,7 +248,6 @@ public static class JSAttributes { public static final String JS_SELECTED_ACR = "selectedAcr"; public static final String JS_REQUEST = "request"; public static final String JS_RESPONSE = "response"; - public static final String JS_INITIAL_REQUEST = "initialRequest"; public static final String JS_HEADERS = "headers"; public static final String JS_PARAMS = "params"; public static final String JS_COOKIES = "cookies";