Context path configuration

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Context path configuration

Jon Stockdill
I am working w/ a web server that forwards the requests to an
application server context (ProxyPass /
ajp://localhost:8009/domain.com/)  I overrode
HTTPRedirectDeflateDecoder to remove the context path in
getActualReceiverEndpointURI() and now the request has been forwarded
to /domain.com/Authn/UserPassword

How should I remove the context path here?

Also, Is it possible to download the sources for maven projects?

Thanks for the help and wonderful project,

--jon
Reply | Threaded
Open this post in threaded view
|

Re: Context path configuration

Peter Schober
* Jon Stockdill <[hidden email]> [2009-01-13 18:33]:
> I am working w/ a web server that forwards the requests to an
> application server context (ProxyPass /
> ajp://localhost:8009/domain.com/)  I overrode
> HTTPRedirectDeflateDecoder to remove the context path in
> getActualReceiverEndpointURI() and now the request has been forwarded
> to /domain.com/Authn/UserPassword
>
> How should I remove the context path here?

Since the application will be visible in / to the webbrowser (from the
ProxyPass above) why not simply run the IdP in the /domain.com/
context in Tomcat?

> Also, Is it possible to download the sources for maven projects?

Maybe this page helps, maybe not (I don't know a thing about maven):
https://spaces.internet2.edu/display/SHIB2/SourceAccess

Cheers,
-peter

--
[hidden email] - vienna university computer center
Universitaetsstrasse 7, A-1010 Wien, Austria/Europe
Tel. +43-1-4277-14155, Fax. +43-1-4277-9140
Reply | Threaded
Open this post in threaded view
|

Re: Context path configuration

Jon Stockdill
On Tue, Jan 13, 2009 at 12:40 PM, Peter Schober
<[hidden email]> wrote:

> * Jon Stockdill <[hidden email]> [2009-01-13 18:33]:
>> I am working w/ a web server that forwards the requests to an
>> application server context (ProxyPass /
>> ajp://localhost:8009/domain.com/)  I overrode
>> HTTPRedirectDeflateDecoder to remove the context path in
>> getActualReceiverEndpointURI() and now the request has been forwarded
>> to /domain.com/Authn/UserPassword
>>
>> How should I remove the context path here?
>
> Since the application will be visible in / to the webbrowser (from the
> ProxyPass above) why not simply run the IdP in the /domain.com/
> context in Tomcat?
>
>> Also, Is it possible to download the sources for maven projects?
>
> Maybe this page helps, maybe not (I don't know a thing about maven):
> https://spaces.internet2.edu/display/SHIB2/SourceAccess


Thanks Peter.  I had tried the SVN url from the browser and was
prompted for a username/password, so I assumed I couldn't check it
out.  I will checkout the code and reference the project in eclipse.

I am running the IdP in the context, and it is initializing fine, but
first it failed because the received endpoint uri did not match, which
I solved by subclassing the decoder.  I am now looking into the source
to figure out how the request is forwarded to the /Authn/UserPassword
to override it.  Hopefully w/ the source, I will be able to find it
quickly.

--jon
Reply | Threaded
Open this post in threaded view
|

Re: Context path configuration

Peter Schober
* Jon Stockdill <[hidden email]> [2009-01-13 18:54]:
> Thanks Peter.  I had tried the SVN url from the browser and was
> prompted for a username/password, so I assumed I couldn't check it
> out.

This only happens if you try to checkout the repositories root,
instead you need to checkout a certain project, e.g. java-idp-main

> I am running the IdP in the context, and it is initializing fine, but
> first it failed because the received endpoint uri did not match, which
> I solved by subclassing the decoder.

Could you be a bit more explicit with the error message (what's the
expected endpoint, what's the actual one)? I would guess this can be
configured somehow?

Cheers,
-peter

--
[hidden email] - vienna university computer center
Universitaetsstrasse 7, A-1010 Wien, Austria/Europe
Tel. +43-1-4277-14155, Fax. +43-1-4277-9140
Reply | Threaded
Open this post in threaded view
|

Re: Context path configuration

Jon Stockdill
On Tue, Jan 13, 2009 at 1:10 PM, Peter Schober
<[hidden email]> wrote:
> Could you be a bit more explicit with the error message (what's the
> expected endpoint, what's the actual one)? I would guess this can be
> configured somehow?

Expected:  https://jon077.testdomain.com/profile/shibboleth
Actual:  https://jon077.testdomain.com:80/jon077.testdomain.com/profile/shibboleth

I overrode HTTPRedirectDeflateDecoder to remove the context path in
getActualReceiverEndpointURI() and now the request has been forwarded
to /jon077.testdomain.com/Authn/UserPassword.

Thanks again for your help.

--jon
Reply | Threaded
Open this post in threaded view
|

Re: Context path configuration

Peter Schober
* Jon Stockdill <[hidden email]> [2009-01-13 19:37]:

> On Tue, Jan 13, 2009 at 1:10 PM, <[hidden email]> wrote:
> > Could you be a bit more explicit with the error message (what's the
> > expected endpoint, what's the actual one)? I would guess this can be
> > configured somehow?
>
> Expected:  https://jon077.testdomain.com/profile/shibboleth
> Actual:  https://jon077.testdomain.com:80/jon077.testdomain.com/profile/shibboleth
>
> I overrode HTTPRedirectDeflateDecoder to remove the context path in
> getActualReceiverEndpointURI() and now the request has been forwarded
> to /jon077.testdomain.com/Authn/UserPassword.

Btw, also note that the port is wrong (https on port 80) which happend
to me recently when I was offloading SSL to some content switch.
Even though the Apache httpd vhost had it's ServerName directive set
to https://hostname.example.org.443 it came out wrong via
mod_proxy_ajp on the servlet container (which might be a bug in
mod_proxy_ajp -- as Scott suggested -- which I have not checked
against the most recent release and hence not yet submitted).

With Tomcat you can fix this by adding the proxyPort="443" attribute
to Tomcat's AJP Connector, for BEA Weblogic you'd have to ask someone
else. Or see if dumping mod_proxy_ajp in favor of mod_jk fixes the
wrong port.

For the context path issue: do you use a context deployment fragment
and what's it's filename and content?

Cheers,
-peter

--
[hidden email] - vienna university computer center
Universitaetsstrasse 7, A-1010 Wien, Austria/Europe
Tel. +43-1-4277-14155, Fax. +43-1-4277-9140
Reply | Threaded
Open this post in threaded view
|

Re: Context path configuration

Jon Stockdill
On Tue, Jan 13, 2009 at 1:59 PM, Peter Schober
<[hidden email]> wrote:

> Btw, also note that the port is wrong (https on port 80) which happend
> to me recently when I was offloading SSL to some content switch.
> Even though the Apache httpd vhost had it's ServerName directive set
> to https://hostname.example.org.443 it came out wrong via
> mod_proxy_ajp on the servlet container (which might be a bug in
> mod_proxy_ajp -- as Scott suggested -- which I have not checked
> against the most recent release and hence not yet submitted).
>
> With Tomcat you can fix this by adding the proxyPort="443" attribute
> to Tomcat's AJP Connector, for BEA Weblogic you'd have to ask someone
> else. Or see if dumping mod_proxy_ajp in favor of mod_jk fixes the
> wrong port.
>
> For the context path issue: do you use a context deployment fragment
> and what's it's filename and content?

Ooops.  my bad.  I added the :80.  My dev env has SSL, but my prod env
is not yet setup.
Expected:  https://jon077.testdomain.com/profile/shibboleth
Actual:  https://jon077.testdomain.com/jon077.testdomain.com/profile/shibboleth

Is the correct.  I mocked the issue w/ apache/tomcat, but our prod
environment is WL and iPlanet.  I am currently trying to create a new
LoginHandler to remove line 63:
pathBuilder.append(httpRequest.getContextPath());

of UsernamePasswordLoginHandler, which I hope will solve the problem.
I am using https://spaces.internet2.edu/display/SHIB2/IdPDevExtLoginHandler
as a reference.

--jon
Reply | Threaded
Open this post in threaded view
|

RE: Context path configuration

Cantor, Scott E.
> environment is WL and iPlanet.  I am currently trying to create a new
> LoginHandler to remove line 63:
> pathBuilder.append(httpRequest.getContextPath());
>
> of UsernamePasswordLoginHandler, which I hope will solve the problem.
> I am using
https://spaces.internet2.edu/display/SHIB2/IdPDevExtLoginHandler
> as a reference.

I think what Peter was trying to say, and in which I concur, is that it is a
doomed approach to modify code for this.

There either is a bug in the IdP or not (I'm implying nothing either way),
but the IdP, indeed any application, needs to be carefully relying on the
right APIs from the container to generate self-referential URLs.

This comes up with the SP all the time, and the worst platform for it is IIS
because there is in fact no API to do it safely.

It's a losing proposition to hack this into submission.

-- Scott


Reply | Threaded
Open this post in threaded view
|

Re: Context path configuration

Brent Putman


Scott Cantor wrote:
environment is WL and iPlanet.  I am currently trying to create a new
LoginHandler to remove line 63:
pathBuilder.append(httpRequest.getContextPath());

of UsernamePasswordLoginHandler, which I hope will solve the problem.
I am using
    
https://spaces.internet2.edu/display/SHIB2/IdPDevExtLoginHandler
  
as a reference.
    

I think what Peter was trying to say, and in which I concur, is that it is a
doomed approach to modify code for this.
  

I'd just chime in and say, that I also agree with this, you're doomed.  There's lots of things in the IdP and/or the container that might generated self-referential URL's, depending on what  you're doing exactly, and they generally rely on the app's reported context path for that.  Trying to hack up the app code is probably just never going to work. 

Why are you trying to reverse proxy path "/"  to the container at "/domain.com/" anyway?  Is that a strict requirement?  I tried to do this recently for another app.  I wanted to vhost the Java app as the root context vis-a-vis Apache, but run it within a Tomcat as a non-ROOT app along with other apps (to avoid running multiple instances), and handle the domain path rewrite in the Apache config with various ProxyPass and mod_rewrite directives.  I ran into lots of similar problems with container managed security generating self-referential URL's.  I didn't run it into the ground, so maybe it's doable, but I did eventually just give up and run the app in a separate Tomcat as the ROOT context.

I think the only sane and really workable approach is to do as others have suggested and use a servlet filter or some other approach to virtualize the info that the container supplies about the context, similar to the way that the AJP connector virtualizes the port via proxyPort.

There either is a bug in the IdP or not (I'm implying nothing either way),
but the IdP, indeed any application, needs to be carefully relying on the
right APIs from the container to generate self-referential URLs.
  

I guess it depends on the point of view, but the way the IdP decoders work currently, it does rely on the container to supply the right info.  I considered options to allow that to be overridden with user-specified values for cases like these, but haven't implemented anything yet.  I think a servlet filter, etc might be a better approach.

Also, ideally this code would move out of the decoders and into a security policy rule, making this issue easier to address.


It's a losing proposition to hack this into submission.

  

Yes, absolutely agreed.

--Brent
Reply | Threaded
Open this post in threaded view
|

Re: Context path configuration

Jon Stockdill
Thanks for the suggestions.   So far adding this filter is doing the trick.

--jon


package com.domain.filters;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ContextPathRemovalFilter implements Filter {

  public class ContextPathRemovalHttpServletRequest
          extends
            HttpServletRequestWrapper {

    public ContextPathRemovalHttpServletRequest(HttpServletRequest request) {
      super(request);
    }

    public String getContextPath() {
      return removeContext(super.getContextPath(), "contextPath");
    }

    public String getPathInfo() {
      return removeContext(super.getPathInfo(), "pathInfo");
    }

    public String getRealPath(String path) {
      return removeContext(super.getRealPath(path), "getRealPath");
    }

    public String getRequestURI() {
      return removeContext(super.getRequestURI(), "requestURI");
    }

    public StringBuffer getRequestURL() {
      return new StringBuffer(removeContext(super.getRequestURL().toString(),
              "getRequestURL"));
    }

    public String getServletPath() {
      String contextPath = removeContext(super.getServletPath(), "servletPath");
      return contextPath;
    }

  }
  public class ContextPathRemovalHttpServletResponse
          extends
            HttpServletResponseWrapper {

    public ContextPathRemovalHttpServletResponse(HttpServletResponse response) {
      super(response);
    }

    public void sendRedirect(String location) throws IOException {
      super.sendRedirect(removeContext(location, "sendRedirect"));
    }
  }

  private static final Logger logger = LoggerFactory
          .getLogger(ContextPathRemovalFilter.class);

  private static final String CONTEXT_PATH = "/domains.com";

  private static final String PORT = ":80";

  protected static String removeContext(String orig, String methodName) {
    logger.debug("{} orig: {}", methodName, orig);

    if (orig == null) {
      return null;
    }

    String txt = orig;

    if (txt.contains(CONTEXT_PATH)) {
      txt = txt.replace(CONTEXT_PATH, "");
    }

    if (txt.contains(PORT)) {
      txt = txt.replace(PORT, "");
    }

    logger.debug("{} replaced: {}", methodName, txt);

    return txt;
  }

  public void destroy() {

  }

  public void doFilter(ServletRequest request, ServletResponse response,
          FilterChain chain) throws IOException, ServletException {

    HttpServletRequest httpRequest = (HttpServletRequest) request;

    logger.debug("ContextRemoval starting");
    logger.debug("  - servletPath: {}", httpRequest.getServletPath());
    logger.debug("  - requestURI:  {}", httpRequest.getRequestURI());

    chain.doFilter(new ContextPathRemovalHttpServletRequest(httpRequest),
            new ContextPathRemovalHttpServletResponse(
                    (HttpServletResponse) response));

  }

  public void init(FilterConfig filterConfig) throws ServletException {
    logger.debug("ContextRemoval init.");
  }
}