Skip to content

Commit

Permalink
Merge pull request javaee-samples#335 from arjantijms/master
Browse files Browse the repository at this point in the history
Added test to see if authentication propagates from JASPIC to JACC
  • Loading branch information
arjantijms committed Dec 1, 2015
2 parents 07cad23 + 24b94df commit 6deca13
Show file tree
Hide file tree
Showing 13 changed files with 458 additions and 1 deletion.
23 changes: 23 additions & 0 deletions jaspic/jacc-propagation/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.javaee7</groupId>
<artifactId>jaspic</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>jaspic-jacc-propagation</artifactId>
<packaging>war</packaging>
<name>Java EE 7 Sample: jaspic - jacc-propagation</name>

<dependencies>
<dependency>
<groupId>org.javaee7</groupId>
<artifactId>jaspic-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.javaee7.jaspic.jaccpropagation.jacc;

import static java.security.Policy.getPolicy;
import static java.util.logging.Level.SEVERE;

import java.security.CodeSource;
import java.security.Principal;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.util.logging.Logger;

import javax.security.auth.Subject;
import javax.security.jacc.PolicyContext;
import javax.security.jacc.WebResourcePermission;

/**
*
* @author Arjan Tijms
*
*/
public class JACC {

private final static Logger logger = Logger.getLogger(JACC.class.getName());

public static Subject getSubject() {
try {
return (Subject) PolicyContext.getContext("javax.security.auth.Subject.container");
} catch (Exception e) {
logger.log(SEVERE, "", e);
}

return null;
}

public static boolean hasAccess(String uri, Subject subject) {
return getPolicy().implies(
new ProtectionDomain(
new CodeSource(null, (Certificate[]) null),
null, null,
subject.getPrincipals().toArray(new Principal[subject.getPrincipals().size()])
),
new WebResourcePermission(uri, "GET")
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.javaee7.jaspic.jaccpropagation.sam;

import javax.servlet.ServletContextEvent;
import javax.servlet.annotation.WebListener;

import org.javaee7.jaspic.common.BaseServletContextListener;
import org.javaee7.jaspic.common.JaspicUtils;

/**
*
* @author Arjan Tijms
*
*/
@WebListener
public class SamAutoRegistrationListener extends BaseServletContextListener {

@Override
public void contextInitialized(ServletContextEvent sce) {
JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package org.javaee7.jaspic.jaccpropagation.sam;

import static javax.security.auth.message.AuthStatus.SUCCESS;

import java.io.IOException;
import java.security.Principal;
import java.util.Map;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.message.AuthException;
import javax.security.auth.message.AuthStatus;
import javax.security.auth.message.MessageInfo;
import javax.security.auth.message.MessagePolicy;
import javax.security.auth.message.callback.CallerPrincipalCallback;
import javax.security.auth.message.callback.GroupPrincipalCallback;
import javax.security.auth.message.module.ServerAuthModule;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Very basic SAM that returns a single hardcoded user named "test" with role "architect" when the request parameter
* <code>doLogin</code> is present.
*
* @author Arjan Tijms
*
*/
public class TestServerAuthModule implements ServerAuthModule {

private CallbackHandler handler;
private Class<?>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };

@Override
public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
@SuppressWarnings("rawtypes") Map options) throws AuthException {
this.handler = handler;
}

@Override
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
throws AuthException {

HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();

Callback[] callbacks;

if (request.getParameter("doLogin") != null) {

callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, "test"),
new GroupPrincipalCallback(clientSubject, new String[] { "architect" }) };
} else {

// The JASPIC protocol for "do nothing"
callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) };
}

try {
handler.handle(callbacks);
} catch (IOException | UnsupportedCallbackException e) {
throw (AuthException) new AuthException().initCause(e);
}

return SUCCESS;
}

@Override
public Class<?>[] getSupportedMessageTypes() {
return supportedMessageTypes;
}

@Override
public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
return AuthStatus.SEND_SUCCESS;
}

@Override
public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.javaee7.jaspic.jaccpropagation.servlet;

import static org.javaee7.jaspic.jaccpropagation.jacc.JACC.getSubject;
import static org.javaee7.jaspic.jaccpropagation.jacc.JACC.hasAccess;

import java.io.IOException;

import javax.security.auth.Subject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
*
* @author Arjan Tijms
*
*/
@WebServlet(urlPatterns = "/protected/servlet")
public class ProtectedServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// Obtain the active subject via a JACC policy handler
Subject subject = getSubject();

if (subject == null) {
response.getWriter().write("Can't get Subject. JACC doesn't seem to be available.");
return;
}

// Check with JACC if the caller has access to this Servlet. As we're
// currently in this very Servlet the answer can't be anything than "true" if
// JASPIC, JACC and role propagation all work correctly.
response.getWriter().write("Has access to /protected/servlet: " + hasAccess("/protected/servlet", subject));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.javaee7.jaspic.jaccpropagation.servlet;

import static org.javaee7.jaspic.jaccpropagation.jacc.JACC.getSubject;
import static org.javaee7.jaspic.jaccpropagation.jacc.JACC.hasAccess;

import java.io.IOException;

import javax.security.auth.Subject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
*
* @author Arjan Tijms
*
*/
@WebServlet(urlPatterns = "/public/servlet")
public class PublicServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// Obtain the active subject via a JACC policy handler
Subject subject = getSubject();

if (subject == null) {
response.getWriter().write("Can't get Subject. JACC doesn't seem to be available.");
return;
}

// Check with JACC if the caller has access to this Servlet. As we're
// currently in this very Servlet and it's a public Servlet,the answer can't be anything
// than "true".

response.getWriter().write("Has access to /public/servlet: " + hasAccess("/public/servlet", subject));

// Check with JACC if the caller has access to another (protected) Servlet. If JACC
// works correctly and we're authenticated this should be true.

response.getWriter().write(
"\nHas access to /protected/servlet: " + hasAccess("/protected/servlet", subject));
}

}
12 changes: 12 additions & 0 deletions jaspic/jacc-propagation/src/main/webapp/WEB-INF/glassfish-web.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app>

<security-role-mapping>
<role-name>architect</role-name>
<group-name>architect</group-name>
</security-role-mapping>

<parameter-encoding default-charset="UTF-8" />

</glassfish-web-app>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<application-bnd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-application-bnd_1_2.xsd"
xmlns="http://websphere.ibm.com/xml/ns/javaee"
version="1.2">

<security-role name="architect">
<group name="architect" />
</security-role>

</application-bnd>
5 changes: 5 additions & 0 deletions jaspic/jacc-propagation/src/main/webapp/WEB-INF/jboss-web.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0"?>

<jboss-web>
<security-domain>jaspitest</security-domain>
</jboss-web>
20 changes: 20 additions & 0 deletions jaspic/jacc-propagation/src/main/webapp/WEB-INF/web.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">

<security-constraint>
<web-resource-collection>
<web-resource-name>Test</web-resource-name>
<url-pattern>/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>architect</role-name>
</auth-constraint>
</security-constraint>

<security-role>
<role-name>architect</role-name>
</security-role>

</web-app>
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.javaee7.jaspic.jaccpropagation;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.javaee7.jaspic.common.ArquillianBase;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.Archive;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
* This tests that the established authenticated identity set from JASPIC propagates correctly
* to a JACC provider.
*
* @author Arjan Tijms
*
*/
@RunWith(Arquillian.class)
public class JACCPropagationProtectedTest extends ArquillianBase {

@Deployment(testable = false)
public static Archive<?> createDeployment() {
return defaultArchive();
}

@Test
public void callingJACCWhenAuthenticated() {

String response = getFromServerPath("protected/servlet?doLogin=true");

// This can basically only fail if JACC itself somehow doesn't work.
// Unfortunately this is the case for a bunch of certified servers, which
// either demand some activation of JACC, or don't ship with a default
// provider at all (which are both spec violations)
assertFalse(
"JACC doesn't seem to be available.",
response.contains("JACC doesn't seem to be available.")
);

// Test if we have access to protected/servlet from within that servlet.
// If this fails role propagation and/or JACC failed, since this is obviously
// impossible.
assertTrue(
"Did not have access to protected servlet from within that Servlet. " +
" Perhaps the roles did not propogate from JASPIC to JACC and the" +
" server didn't use JACC to grant access to invoking said Servlet?",
response.contains("Has access to /protected/servlet: true")
);
}

}
Loading

0 comments on commit 6deca13

Please sign in to comment.