Commit 7cbc62a8 authored by Brian Major's avatar Brian Major
Browse files

issue-19 - WhoAmIServlet supports different AuthMethods

parent 11a5869e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@ repositories {
sourceCompatibility = 1.7
group = 'org.opencadc'

version = '1.1.2'
version = '1.1.3'

dependencies {
    compile 'log4j:log4j:1.2.+'
+44 −15
Original line number Diff line number Diff line
@@ -71,9 +71,10 @@ package ca.nrc.cadc.ac.server.web;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.Set;
import java.security.Principal;

import javax.security.auth.Subject;
import javax.security.auth.x500.X500Principal;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@@ -84,6 +85,7 @@ import org.apache.log4j.Logger;
import ca.nrc.cadc.auth.AuthMethod;
import ca.nrc.cadc.auth.AuthenticationUtil;
import ca.nrc.cadc.auth.HttpPrincipal;
import ca.nrc.cadc.auth.NumericPrincipal;
import ca.nrc.cadc.log.ServletLogInfo;
import ca.nrc.cadc.reg.Standards;
import ca.nrc.cadc.reg.client.LocalAuthority;
@@ -99,7 +101,7 @@ public class WhoAmIServlet extends HttpServlet
{
    private static final Logger log = Logger.getLogger(WhoAmIServlet.class);

    static final String USER_GET_PATH = "/%s?idType=HTTP";
    static final String USER_GET_PATH = "/%s?idType=%s";

    /**
     * Handle a /whoami GET operation.
@@ -119,19 +121,23 @@ public class WhoAmIServlet extends HttpServlet
        log.info(logInfo.start());
        try
        {
            final Subject currentSubject = getSubject(request);
            final Set<HttpPrincipal> currentWebPrincipals =
                    currentSubject.getPrincipals(HttpPrincipal.class);

            if (currentWebPrincipals.isEmpty())
            final Subject subject = getSubject(request);
            AuthMethod authMethod = getAuthMethod(subject);
            if (AuthMethod.ANON.equals(authMethod))
            {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                return;
            }
            else

            Principal principal = getPrincipalForRestCall(subject);
            if (principal == null)
            {
                redirect(response, currentWebPrincipals.toArray(
                        new HttpPrincipal[1])[0], request.getScheme());
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().print("No supported identities for /whoami");
                return;
            }

            redirect(response, principal, authMethod);
        }
        catch (IllegalArgumentException e)
        {
@@ -154,12 +160,37 @@ public class WhoAmIServlet extends HttpServlet
        }
    }

    private Principal getPrincipalForRestCall(Subject s)
    {
        // TODO: Would be better to add this type of checking to AuthenticationUtil.
        //       But: a better fix would probably be to remove the userid and
        //            authentication type from the get user REST call.  Only the
        //            calling user is allowed to get that user, so the information
        //            is already available.

        if (!s.getPrincipals(HttpPrincipal.class).isEmpty())
            return s.getPrincipals(HttpPrincipal.class).iterator().next();

        if (!s.getPrincipals(X500Principal.class).isEmpty())
            return s.getPrincipals(X500Principal.class).iterator().next();

        if (!s.getPrincipals(NumericPrincipal.class).isEmpty())
            return s.getPrincipals(NumericPrincipal.class).iterator().next();

        return null;
    }

    public URI getServiceURI(URI standard)
    {
        LocalAuthority localAuthority = new LocalAuthority();
        return localAuthority.getServiceURI(standard.toString());
    }

    public AuthMethod getAuthMethod(Subject subject)
    {
        return AuthenticationUtil.getAuthMethod(subject);
    }

    /**
     * Forward on to the Service's user endpoint.
     *
@@ -167,21 +198,19 @@ public class WhoAmIServlet extends HttpServlet
     * @param webPrincipal The HttpPrincipal instance.
     * @param scheme       The scheme
     */
    void redirect(final HttpServletResponse response,
                  final HttpPrincipal webPrincipal,
                  final String scheme) throws IOException
    void redirect(HttpServletResponse response, Principal principal, AuthMethod authMethod) throws IOException
    {
        final RegistryClient registryClient = getRegistryClient();

        URI umsServiceURI = getServiceURI(Standards.UMS_WHOAMI_01);
        log.debug("ums service uri: " + umsServiceURI);

        final URL serviceURL = registryClient.getServiceURL(umsServiceURI, Standards.UMS_USERS_01, AuthMethod.CERT);
        final URL serviceURL = registryClient.getServiceURL(umsServiceURI, Standards.UMS_USERS_01, authMethod);
        final URL redirectURL = new URL(serviceURL.toExternalForm() + USER_GET_PATH);

        // Take the first one.
        final String redirectUrl =
            String.format(redirectURL.toString(), webPrincipal.getName());
            String.format(redirectURL.toString(), principal.getName(), AuthenticationUtil.getPrincipalType(principal));
        final URI redirectURI = URI.create(redirectUrl);

        log.debug("redirecting to " + redirectURI.toASCIIString());
+1 −1
Original line number Diff line number Diff line
@@ -131,7 +131,7 @@ public class AbstractLdapDAOTest
    public static void setUpBeforeClass()
        throws Exception
    {
        Log4jInit.setLevel("ca.nrc.cadc.ac", Level.DEBUG);
        Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO);

        System.setProperty(PropertiesReader.class.getName() + ".dir", "src/test/resources");

+25 −4
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ import java.net.URL;
import java.security.PrivilegedExceptionAction;

import javax.security.auth.Subject;
import javax.security.auth.x500.X500Principal;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@@ -114,10 +115,23 @@ public class WhoAmIServletTest
    }

    @Test
    public void doGet() throws Exception
    public void doGetWithHttpPrincipal() throws Exception
    {
        final Subject subject = new Subject();
        subject.getPrincipals().add(new HttpPrincipal("CADCtest"));
        doGet(subject, AuthMethod.PASSWORD, "CADCtest", "http");
    }

    @Test
    public void doGetWithCert() throws Exception
    {
        final Subject subject = new Subject();
        subject.getPrincipals().add(new X500Principal("CN=cadcauthtest1_24c,OU=cadc,O=hia,C=ca"));
        doGet(subject, AuthMethod.CERT, "CN=cadcauthtest1_24c,OU=cadc,O=hia,C=ca", "x500");
    }

    public void doGet(final Subject subject, final AuthMethod authMethod, final String restUserid, final String restType) throws Exception
    {

        final RegistryClient mockRegistry = createMock(RegistryClient.class);
        final WhoAmIServlet testSubject = new WhoAmIServlet()
@@ -145,6 +159,12 @@ public class WhoAmIServletTest
            {
                return URI.create("ivo://example.org/ums");
            }

            @Override
            public AuthMethod getAuthMethod(Subject subject)
            {
                return authMethod;
            }
        };

        final HttpServletRequest mockRequest =
@@ -155,9 +175,10 @@ public class WhoAmIServletTest
        expect(mockRequest.getPathInfo()).andReturn("users/CADCtest").once();
        expect(mockRequest.getMethod()).andReturn("GET").once();
        expect(mockRequest.getRemoteAddr()).andReturn("mysite.com").once();
        expect(mockRequest.getScheme()).andReturn("http");

        mockResponse.sendRedirect("/ac/users/CADCtest?idType=HTTP");
        String redirect = "/ac/users/" + restUserid + "?idType=" + restType;
        log.debug("expected redirect: " + redirect);
        mockResponse.sendRedirect(redirect);
        expectLastCall().once();

        URI umsServiceURI = URI.create("ivo://example.org/ums");
@@ -166,7 +187,7 @@ public class WhoAmIServletTest
//                                          "http", "/%s?idType=HTTP")).
//                andReturn(new URL("http://mysite.com/ac/users/CADCtest?idType=HTTP")).once();

        expect(mockRegistry.getServiceURL(umsServiceURI, Standards.UMS_USERS_01, AuthMethod.CERT))
        expect(mockRegistry.getServiceURL(umsServiceURI, Standards.UMS_USERS_01, authMethod))
            .andReturn(new URL("http://mysite.com/ac/users")).once();

        replay(mockRequest, mockResponse, mockRegistry);
+1 −1
Original line number Diff line number Diff line
@@ -96,7 +96,7 @@ public class RemoveGroupMemberActionTest
    @BeforeClass
    public static void setUpClass()
    {
        Log4jInit.setLevel("ca.nrc.cadc.ac", Level.DEBUG);
        Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO);
    }

    @Test