Repository: cxf-fediz Updated Branches: refs/heads/master e344688ff -> e24966d39
More work on SAML SSO Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/e24966d3 Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/e24966d3 Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/e24966d3 Branch: refs/heads/master Commit: e24966d395349c99044a3bd2fa3c878416eae8cf Parents: e344688 Author: Colm O hEigeartaigh <cohei...@apache.org> Authored: Thu Jul 10 14:28:14 2014 +0100 Committer: Colm O hEigeartaigh <cohei...@apache.org> Committed: Thu Jul 10 14:28:14 2014 +0100 ---------------------------------------------------------------------- .../cxf/fediz/core/config/SAMLProtocol.java | 37 ++++++++++++++ .../core/processor/FederationProcessorImpl.java | 16 ++++-- .../fediz/core/processor/FedizProcessor.java | 8 ++- .../core/processor/RedirectionResponse.java | 51 ++++++++++++++++++++ .../src/main/resources/schemas/FedizConfig.xsd | 9 +++- .../fediz/jetty/FederationAuthenticator.java | 24 +++++++-- .../web/FederationAuthenticationEntryPoint.java | 15 +++++- .../web/FederationLogoutSuccessHandler.java | 14 +++++- .../web/FederationAuthenticationEntryPoint.java | 29 ++++++++++- .../fediz/tomcat/FederationAuthenticator.java | 24 +++++++-- 10 files changed, 205 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e24966d3/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java index b334537..adf6862 100644 --- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java @@ -20,6 +20,7 @@ package org.apache.cxf.fediz.core.config; import org.apache.cxf.fediz.core.config.jaxb.ProtocolType; +import org.apache.cxf.fediz.core.config.jaxb.SamlProtocolType; public class SAMLProtocol extends Protocol { @@ -56,6 +57,42 @@ public class SAMLProtocol extends Protocol { //SAMLTokenValidator validator = new SAMLTokenValidator(); //validators.add(validators.size(), validator); } + + protected SamlProtocolType getSAMLProtocol() { + return (SamlProtocolType)super.getProtocolType(); + } + + protected void setSAMLProtocol(SamlProtocolType samlProtocol) { + super.setProtocolType(samlProtocol); + } + + public boolean isSignRequest() { + return getSAMLProtocol().isSignRequest(); + } + + public void setSignRequest(boolean signRequest) { + getSAMLProtocol().setSignRequest(signRequest); + } + + public String getWebAppDomain() { + return getSAMLProtocol().getWebAppDomain(); + } + + public void setWebAppDomain(String webAppDomain) { + getSAMLProtocol().setWebAppDomain(webAppDomain); + } + + public long getStateTimeToLive() { + long ttl = getSAMLProtocol().getStateTimeToLive(); + if (ttl > 0) { + return ttl; + } + return 2L * 60L * 1000L; + } + + public void setStateTimeToLive(long stateTimeToLive) { + getSAMLProtocol().setStateTimeToLive(stateTimeToLive); + } } http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e24966d3/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java index 12f4669..58a186a 100644 --- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java @@ -347,7 +347,7 @@ public class FederationProcessorImpl implements FedizProcessor { } @Override - public String createSignInRequest(HttpServletRequest request, FedizContext config) + public RedirectionResponse createSignInRequest(HttpServletRequest request, FedizContext config) throws ProcessingException { String redirectURL = null; @@ -448,12 +448,15 @@ public class FederationProcessorImpl implements FedizProcessor { } catch (Exception ex) { LOG.error("Failed to create SignInRequest", ex); throw new ProcessingException("Failed to create SignInRequest"); - } - return redirectURL; + } + + RedirectionResponse response = new RedirectionResponse(); + response.setRedirectionURL(redirectURL); + return response; } @Override - public String createSignOutRequest(HttpServletRequest request, FedizContext config) + public RedirectionResponse createSignOutRequest(HttpServletRequest request, FedizContext config) throws ProcessingException { String redirectURL = null; @@ -492,7 +495,10 @@ public class FederationProcessorImpl implements FedizProcessor { LOG.error("Failed to create SignInRequest", ex); throw new ProcessingException("Failed to create SignInRequest"); } - return redirectURL; + + RedirectionResponse response = new RedirectionResponse(); + response.setRedirectionURL(redirectURL); + return response; } private String resolveSignInQuery(HttpServletRequest request, FedizContext config) http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e24966d3/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizProcessor.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizProcessor.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizProcessor.java index 1081f05..0f7af91 100644 --- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizProcessor.java +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizProcessor.java @@ -29,9 +29,13 @@ public interface FedizProcessor { FedizResponse processRequest(FedizRequest request, FedizContext config) throws ProcessingException; - String createSignInRequest(HttpServletRequest request, FedizContext config) throws ProcessingException; + RedirectionResponse createSignInRequest( + HttpServletRequest request, FedizContext config + ) throws ProcessingException; - String createSignOutRequest(HttpServletRequest request, FedizContext config) throws ProcessingException; + RedirectionResponse createSignOutRequest( + HttpServletRequest request, FedizContext config + ) throws ProcessingException; Document getMetaData(FedizContext config) throws ProcessingException; http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e24966d3/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/RedirectionResponse.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/RedirectionResponse.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/RedirectionResponse.java new file mode 100644 index 0000000..81d3787 --- /dev/null +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/RedirectionResponse.java @@ -0,0 +1,51 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.cxf.fediz.core.processor; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +/** + * Some parameters to redirect to a token issuer (either SignIn or SignOut) + */ +public class RedirectionResponse implements Serializable { + + private static final long serialVersionUID = 3182350165552249151L; + + private String redirectionURL; + private Map<String, String> headers = new HashMap<String, String>(); + + public String getRedirectionURL() { + return redirectionURL; + } + + public void setRedirectionURL(String redirectionURL) { + this.redirectionURL = redirectionURL; + } + + public Map<String, String> getHeaders() { + return headers; + } + + public void addHeader(String headerName, String headerValue) { + headers.put(headerName, headerValue); + } +} http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e24966d3/plugins/core/src/main/resources/schemas/FedizConfig.xsd ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/resources/schemas/FedizConfig.xsd b/plugins/core/src/main/resources/schemas/FedizConfig.xsd index 72f19f2..984b8a6 100644 --- a/plugins/core/src/main/resources/schemas/FedizConfig.xsd +++ b/plugins/core/src/main/resources/schemas/FedizConfig.xsd @@ -113,7 +113,9 @@ <xs:complexContent> <xs:extension base="protocolType"> <xs:sequence> - <xs:element ref="realm" /> + <xs:element ref="signRequest" /> + <xs:element ref="stateTimeToLive" /> + <xs:element ref="webAppDomain" /> </xs:sequence> <xs:attribute name="version" use="required" type="xs:string" /> </xs:extension> @@ -124,7 +126,10 @@ <xs:element name="roleURI" type="xs:string" /> <xs:element name="realm" type="CallbackType" /> <xs:element name="applicationServiceURL" type="xs:string" /> - + + <xs:element name="signRequest" type="xs:boolean" /> + <xs:element name="stateTimeToLive" type="xs:long" default="120000" /> + <xs:element name="webAppDomain" type="xs:string" /> <xs:complexType name="protocolType" abstract="true"> <xs:sequence> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e24966d3/plugins/jetty/src/main/java/org/apache/cxf/fediz/jetty/FederationAuthenticator.java ---------------------------------------------------------------------- diff --git a/plugins/jetty/src/main/java/org/apache/cxf/fediz/jetty/FederationAuthenticator.java b/plugins/jetty/src/main/java/org/apache/cxf/fediz/jetty/FederationAuthenticator.java index 635d375..8cb9923 100644 --- a/plugins/jetty/src/main/java/org/apache/cxf/fediz/jetty/FederationAuthenticator.java +++ b/plugins/jetty/src/main/java/org/apache/cxf/fediz/jetty/FederationAuthenticator.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.security.cert.X509Certificate; +import java.util.Map; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequest; @@ -41,6 +42,7 @@ import org.apache.cxf.fediz.core.processor.FederationProcessorImpl; import org.apache.cxf.fediz.core.processor.FedizProcessor; import org.apache.cxf.fediz.core.processor.FedizRequest; import org.apache.cxf.fediz.core.processor.FedizResponse; +import org.apache.cxf.fediz.core.processor.RedirectionResponse; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.security.ServerAuthException; @@ -404,10 +406,17 @@ public class FederationAuthenticator extends LoginAuthenticator { contextName = "/"; } FedizContext fedCtx = this.configurator.getFedizContext(contextName); - String redirectURL = null; try { - redirectURL = processor.createSignInRequest(request, fedCtx); + RedirectionResponse redirectionResponse = processor.createSignInRequest(request, fedCtx); + String redirectURL = redirectionResponse.getRedirectionURL(); if (redirectURL != null) { + Map<String, String> headers = redirectionResponse.getHeaders(); + if (!headers.isEmpty()) { + for (String headerName : headers.keySet()) { + response.addHeader(headerName, headers.get(headerName)); + } + } + response.sendRedirect(redirectURL); } else { LOG.warn("Failed to create SignInRequest."); @@ -432,10 +441,17 @@ public class FederationAuthenticator extends LoginAuthenticator { contextName = "/"; } FedizContext fedCtx = this.configurator.getFedizContext(contextName); - String redirectURL = null; try { - redirectURL = processor.createSignOutRequest(request, fedCtx); + RedirectionResponse redirectionResponse = processor.createSignOutRequest(request, fedCtx); + String redirectURL = redirectionResponse.getRedirectionURL(); if (redirectURL != null) { + Map<String, String> headers = redirectionResponse.getHeaders(); + if (!headers.isEmpty()) { + for (String headerName : headers.keySet()) { + response.addHeader(headerName, headers.get(headerName)); + } + } + response.sendRedirect(redirectURL); } else { LOG.warn("Failed to create SignOutRequest."); http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e24966d3/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationEntryPoint.java ---------------------------------------------------------------------- diff --git a/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationEntryPoint.java b/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationEntryPoint.java index 096ec5a..d30fb58 100644 --- a/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationEntryPoint.java +++ b/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationEntryPoint.java @@ -20,6 +20,7 @@ package org.apache.cxf.fediz.spring.web; import java.io.IOException; +import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -29,6 +30,7 @@ import org.apache.cxf.fediz.core.config.FedizContext; import org.apache.cxf.fediz.core.exception.ProcessingException; import org.apache.cxf.fediz.core.processor.FederationProcessorImpl; import org.apache.cxf.fediz.core.processor.FedizProcessor; +import org.apache.cxf.fediz.core.processor.RedirectionResponse; import org.apache.cxf.fediz.spring.FederationConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -77,11 +79,22 @@ public class FederationAuthenticationEntryPoint implements AuthenticationEntryPo LOG.debug("Federation context: {}", fedContext); try { FedizProcessor wfProc = new FederationProcessorImpl(); - redirectUrl = wfProc.createSignInRequest(servletRequest, fedContext); + RedirectionResponse redirectionResponse = + wfProc.createSignInRequest(servletRequest, fedContext); + redirectUrl = redirectionResponse.getRedirectionURL(); + if (redirectUrl == null) { LOG.warn("Failed to create SignInRequest. Redirect URL null"); throw new ServletException("Failed to create SignInRequest. Redirect URL null"); } + + Map<String, String> headers = redirectionResponse.getHeaders(); + if (!headers.isEmpty()) { + for (String headerName : headers.keySet()) { + response.addHeader(headerName, headers.get(headerName)); + } + } + } catch (ProcessingException ex) { LOG.warn("Failed to create SignInRequest", ex); throw new ServletException("Failed to create SignInRequest: " + ex.getMessage()); http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e24966d3/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationLogoutSuccessHandler.java ---------------------------------------------------------------------- diff --git a/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationLogoutSuccessHandler.java b/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationLogoutSuccessHandler.java index 5ef4b6d..466d989 100644 --- a/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationLogoutSuccessHandler.java +++ b/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationLogoutSuccessHandler.java @@ -19,6 +19,7 @@ package org.apache.cxf.fediz.spring.web; import java.io.IOException; +import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -28,6 +29,7 @@ import org.apache.cxf.fediz.core.config.FedizContext; import org.apache.cxf.fediz.core.exception.ProcessingException; import org.apache.cxf.fediz.core.processor.FederationProcessorImpl; import org.apache.cxf.fediz.core.processor.FedizProcessor; +import org.apache.cxf.fediz.core.processor.RedirectionResponse; import org.apache.cxf.fediz.spring.FederationConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,10 +57,18 @@ public class FederationLogoutSuccessHandler implements LogoutSuccessHandler { contextName = "/"; } FedizContext fedCtx = federationConfig.getFedizContext(contextName); - String redirectURL; try { - redirectURL = processor.createSignOutRequest(request, fedCtx); + RedirectionResponse redirectionResponse = + processor.createSignOutRequest(request, fedCtx); + String redirectURL = redirectionResponse.getRedirectionURL(); if (redirectURL != null) { + Map<String, String> headers = redirectionResponse.getHeaders(); + if (!headers.isEmpty()) { + for (String headerName : headers.keySet()) { + response.addHeader(headerName, headers.get(headerName)); + } + } + response.sendRedirect(redirectURL); } else { LOG.warn("Failed to create SignOutRequest."); http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e24966d3/plugins/spring2/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationEntryPoint.java ---------------------------------------------------------------------- diff --git a/plugins/spring2/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationEntryPoint.java b/plugins/spring2/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationEntryPoint.java index c6e2a02..9bb3482 100644 --- a/plugins/spring2/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationEntryPoint.java +++ b/plugins/spring2/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationEntryPoint.java @@ -20,6 +20,7 @@ package org.apache.cxf.fediz.spring.web; import java.io.IOException; +import java.util.Map; import javax.servlet.ServletException; import javax.servlet.ServletRequest; @@ -31,6 +32,7 @@ import org.apache.cxf.fediz.core.config.FedizContext; import org.apache.cxf.fediz.core.exception.ProcessingException; import org.apache.cxf.fediz.core.processor.FederationProcessorImpl; import org.apache.cxf.fediz.core.processor.FedizProcessor; +import org.apache.cxf.fediz.core.processor.RedirectionResponse; import org.apache.cxf.fediz.spring.FederationConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -80,11 +82,22 @@ public class FederationAuthenticationEntryPoint implements AuthenticationEntryPo LOG.debug("Federation context: {}", fedContext); try { FedizProcessor wfProc = new FederationProcessorImpl(); - redirectUrl = wfProc.createSignInRequest(servletRequest, fedContext); + RedirectionResponse redirectionResponse = + wfProc.createSignInRequest(servletRequest, fedContext); + redirectUrl = redirectionResponse.getRedirectionURL(); + if (redirectUrl == null) { LOG.warn("Failed to create SignInRequest. Redirect URL null"); throw new ServletException("Failed to create SignInRequest. Redirect URL null"); } + + Map<String, String> headers = redirectionResponse.getHeaders(); + if (!headers.isEmpty()) { + for (String headerName : headers.keySet()) { + response.addHeader(headerName, headers.get(headerName)); + } + } + } catch (ProcessingException ex) { LOG.warn("Failed to create SignInRequest", ex); throw new ServletException("Failed to create SignInRequest: " + ex.getMessage()); @@ -124,12 +137,24 @@ public class FederationAuthenticationEntryPoint implements AuthenticationEntryPo LOG.debug("Federation context: {}", fedContext); try { FedizProcessor wfProc = new FederationProcessorImpl(); - redirectUrl = wfProc.createSignInRequest(hrequest, fedContext); + + RedirectionResponse redirectionResponse = + wfProc.createSignInRequest(hrequest, fedContext); + redirectUrl = redirectionResponse.getRedirectionURL(); + if (redirectUrl == null) { LOG.warn("Failed to create SignInRequest."); hresponse.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to create SignInRequest."); } + + Map<String, String> headers = redirectionResponse.getHeaders(); + if (!headers.isEmpty()) { + for (String headerName : headers.keySet()) { + hresponse.addHeader(headerName, headers.get(headerName)); + } + } + } catch (ProcessingException ex) { System.err.println("Failed to create SignInRequest: " + ex.getMessage()); LOG.warn("Failed to create SignInRequest: " + ex.getMessage()); http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/e24966d3/plugins/tomcat/src/main/java/org/apache/cxf/fediz/tomcat/FederationAuthenticator.java ---------------------------------------------------------------------- diff --git a/plugins/tomcat/src/main/java/org/apache/cxf/fediz/tomcat/FederationAuthenticator.java b/plugins/tomcat/src/main/java/org/apache/cxf/fediz/tomcat/FederationAuthenticator.java index 83a4630..8028c03 100644 --- a/plugins/tomcat/src/main/java/org/apache/cxf/fediz/tomcat/FederationAuthenticator.java +++ b/plugins/tomcat/src/main/java/org/apache/cxf/fediz/tomcat/FederationAuthenticator.java @@ -28,6 +28,7 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; @@ -52,6 +53,7 @@ import org.apache.cxf.fediz.core.processor.FedizProcessor; import org.apache.cxf.fediz.core.processor.FedizProcessorFactory; import org.apache.cxf.fediz.core.processor.FedizRequest; import org.apache.cxf.fediz.core.processor.FedizResponse; +import org.apache.cxf.fediz.core.processor.RedirectionResponse; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.wss4j.common.util.DOM2Writer; @@ -593,10 +595,17 @@ public class FederationAuthenticator extends FormAuthenticator { contextName = "/"; } FedizContext fedCtx = this.configurator.getFedizContext(contextName); - String redirectURL = null; try { - redirectURL = processor.createSignInRequest(request, fedCtx); + RedirectionResponse redirectionResponse = processor.createSignInRequest(request, fedCtx); + String redirectURL = redirectionResponse.getRedirectionURL(); if (redirectURL != null) { + Map<String, String> headers = redirectionResponse.getHeaders(); + if (!headers.isEmpty()) { + for (String headerName : headers.keySet()) { + response.addHeader(headerName, headers.get(headerName)); + } + } + response.sendRedirect(redirectURL); } else { LOG.warn("Failed to create SignInRequest."); @@ -619,10 +628,17 @@ public class FederationAuthenticator extends FormAuthenticator { contextName = "/"; } FedizContext fedCtx = this.configurator.getFedizContext(contextName); - String redirectURL = null; try { - redirectURL = processor.createSignOutRequest(request, fedCtx); + RedirectionResponse redirectionResponse = processor.createSignOutRequest(request, fedCtx); + String redirectURL = redirectionResponse.getRedirectionURL(); if (redirectURL != null) { + Map<String, String> headers = redirectionResponse.getHeaders(); + if (!headers.isEmpty()) { + for (String headerName : headers.keySet()) { + response.addHeader(headerName, headers.get(headerName)); + } + } + response.sendRedirect(redirectURL); } else { LOG.warn("Failed to create SignOutRequest.");