Skip to content

Commit 6deca13

Browse files
committed
Merge pull request #335 from arjantijms/master
Added test to see if authentication propagates from JASPIC to JACC
2 parents 07cad23 + 24b94df commit 6deca13

File tree

13 files changed

+458
-1
lines changed

13 files changed

+458
-1
lines changed

jaspic/jacc-propagation/pom.xml

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<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">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<parent>
6+
<groupId>org.javaee7</groupId>
7+
<artifactId>jaspic</artifactId>
8+
<version>1.0-SNAPSHOT</version>
9+
<relativePath>../pom.xml</relativePath>
10+
</parent>
11+
12+
<artifactId>jaspic-jacc-propagation</artifactId>
13+
<packaging>war</packaging>
14+
<name>Java EE 7 Sample: jaspic - jacc-propagation</name>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>org.javaee7</groupId>
19+
<artifactId>jaspic-common</artifactId>
20+
<version>1.0-SNAPSHOT</version>
21+
</dependency>
22+
</dependencies>
23+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package org.javaee7.jaspic.jaccpropagation.jacc;
2+
3+
import static java.security.Policy.getPolicy;
4+
import static java.util.logging.Level.SEVERE;
5+
6+
import java.security.CodeSource;
7+
import java.security.Principal;
8+
import java.security.ProtectionDomain;
9+
import java.security.cert.Certificate;
10+
import java.util.logging.Logger;
11+
12+
import javax.security.auth.Subject;
13+
import javax.security.jacc.PolicyContext;
14+
import javax.security.jacc.WebResourcePermission;
15+
16+
/**
17+
*
18+
* @author Arjan Tijms
19+
*
20+
*/
21+
public class JACC {
22+
23+
private final static Logger logger = Logger.getLogger(JACC.class.getName());
24+
25+
public static Subject getSubject() {
26+
try {
27+
return (Subject) PolicyContext.getContext("javax.security.auth.Subject.container");
28+
} catch (Exception e) {
29+
logger.log(SEVERE, "", e);
30+
}
31+
32+
return null;
33+
}
34+
35+
public static boolean hasAccess(String uri, Subject subject) {
36+
return getPolicy().implies(
37+
new ProtectionDomain(
38+
new CodeSource(null, (Certificate[]) null),
39+
null, null,
40+
subject.getPrincipals().toArray(new Principal[subject.getPrincipals().size()])
41+
),
42+
new WebResourcePermission(uri, "GET")
43+
);
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.javaee7.jaspic.jaccpropagation.sam;
2+
3+
import javax.servlet.ServletContextEvent;
4+
import javax.servlet.annotation.WebListener;
5+
6+
import org.javaee7.jaspic.common.BaseServletContextListener;
7+
import org.javaee7.jaspic.common.JaspicUtils;
8+
9+
/**
10+
*
11+
* @author Arjan Tijms
12+
*
13+
*/
14+
@WebListener
15+
public class SamAutoRegistrationListener extends BaseServletContextListener {
16+
17+
@Override
18+
public void contextInitialized(ServletContextEvent sce) {
19+
JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
20+
}
21+
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package org.javaee7.jaspic.jaccpropagation.sam;
2+
3+
import static javax.security.auth.message.AuthStatus.SUCCESS;
4+
5+
import java.io.IOException;
6+
import java.security.Principal;
7+
import java.util.Map;
8+
9+
import javax.security.auth.Subject;
10+
import javax.security.auth.callback.Callback;
11+
import javax.security.auth.callback.CallbackHandler;
12+
import javax.security.auth.callback.UnsupportedCallbackException;
13+
import javax.security.auth.message.AuthException;
14+
import javax.security.auth.message.AuthStatus;
15+
import javax.security.auth.message.MessageInfo;
16+
import javax.security.auth.message.MessagePolicy;
17+
import javax.security.auth.message.callback.CallerPrincipalCallback;
18+
import javax.security.auth.message.callback.GroupPrincipalCallback;
19+
import javax.security.auth.message.module.ServerAuthModule;
20+
import javax.servlet.http.HttpServletRequest;
21+
import javax.servlet.http.HttpServletResponse;
22+
23+
/**
24+
* Very basic SAM that returns a single hardcoded user named "test" with role "architect" when the request parameter
25+
* <code>doLogin</code> is present.
26+
*
27+
* @author Arjan Tijms
28+
*
29+
*/
30+
public class TestServerAuthModule implements ServerAuthModule {
31+
32+
private CallbackHandler handler;
33+
private Class<?>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
34+
35+
@Override
36+
public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
37+
@SuppressWarnings("rawtypes") Map options) throws AuthException {
38+
this.handler = handler;
39+
}
40+
41+
@Override
42+
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
43+
throws AuthException {
44+
45+
HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
46+
47+
Callback[] callbacks;
48+
49+
if (request.getParameter("doLogin") != null) {
50+
51+
callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, "test"),
52+
new GroupPrincipalCallback(clientSubject, new String[] { "architect" }) };
53+
} else {
54+
55+
// The JASPIC protocol for "do nothing"
56+
callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) };
57+
}
58+
59+
try {
60+
handler.handle(callbacks);
61+
} catch (IOException | UnsupportedCallbackException e) {
62+
throw (AuthException) new AuthException().initCause(e);
63+
}
64+
65+
return SUCCESS;
66+
}
67+
68+
@Override
69+
public Class<?>[] getSupportedMessageTypes() {
70+
return supportedMessageTypes;
71+
}
72+
73+
@Override
74+
public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
75+
return AuthStatus.SEND_SUCCESS;
76+
}
77+
78+
@Override
79+
public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
80+
81+
}
82+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.javaee7.jaspic.jaccpropagation.servlet;
2+
3+
import static org.javaee7.jaspic.jaccpropagation.jacc.JACC.getSubject;
4+
import static org.javaee7.jaspic.jaccpropagation.jacc.JACC.hasAccess;
5+
6+
import java.io.IOException;
7+
8+
import javax.security.auth.Subject;
9+
import javax.servlet.ServletException;
10+
import javax.servlet.annotation.WebServlet;
11+
import javax.servlet.http.HttpServlet;
12+
import javax.servlet.http.HttpServletRequest;
13+
import javax.servlet.http.HttpServletResponse;
14+
15+
/**
16+
*
17+
* @author Arjan Tijms
18+
*
19+
*/
20+
@WebServlet(urlPatterns = "/protected/servlet")
21+
public class ProtectedServlet extends HttpServlet {
22+
23+
private static final long serialVersionUID = 1L;
24+
25+
@Override
26+
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
27+
28+
// Obtain the active subject via a JACC policy handler
29+
Subject subject = getSubject();
30+
31+
if (subject == null) {
32+
response.getWriter().write("Can't get Subject. JACC doesn't seem to be available.");
33+
return;
34+
}
35+
36+
// Check with JACC if the caller has access to this Servlet. As we're
37+
// currently in this very Servlet the answer can't be anything than "true" if
38+
// JASPIC, JACC and role propagation all work correctly.
39+
response.getWriter().write("Has access to /protected/servlet: " + hasAccess("/protected/servlet", subject));
40+
}
41+
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package org.javaee7.jaspic.jaccpropagation.servlet;
2+
3+
import static org.javaee7.jaspic.jaccpropagation.jacc.JACC.getSubject;
4+
import static org.javaee7.jaspic.jaccpropagation.jacc.JACC.hasAccess;
5+
6+
import java.io.IOException;
7+
8+
import javax.security.auth.Subject;
9+
import javax.servlet.ServletException;
10+
import javax.servlet.annotation.WebServlet;
11+
import javax.servlet.http.HttpServlet;
12+
import javax.servlet.http.HttpServletRequest;
13+
import javax.servlet.http.HttpServletResponse;
14+
15+
/**
16+
*
17+
* @author Arjan Tijms
18+
*
19+
*/
20+
@WebServlet(urlPatterns = "/public/servlet")
21+
public class PublicServlet extends HttpServlet {
22+
23+
private static final long serialVersionUID = 1L;
24+
25+
@Override
26+
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
27+
28+
// Obtain the active subject via a JACC policy handler
29+
Subject subject = getSubject();
30+
31+
if (subject == null) {
32+
response.getWriter().write("Can't get Subject. JACC doesn't seem to be available.");
33+
return;
34+
}
35+
36+
// Check with JACC if the caller has access to this Servlet. As we're
37+
// currently in this very Servlet and it's a public Servlet,the answer can't be anything
38+
// than "true".
39+
40+
response.getWriter().write("Has access to /public/servlet: " + hasAccess("/public/servlet", subject));
41+
42+
// Check with JACC if the caller has access to another (protected) Servlet. If JACC
43+
// works correctly and we're authenticated this should be true.
44+
45+
response.getWriter().write(
46+
"\nHas access to /protected/servlet: " + hasAccess("/protected/servlet", subject));
47+
}
48+
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!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">
3+
<glassfish-web-app>
4+
5+
<security-role-mapping>
6+
<role-name>architect</role-name>
7+
<group-name>architect</group-name>
8+
</security-role-mapping>
9+
10+
<parameter-encoding default-charset="UTF-8" />
11+
12+
</glassfish-web-app>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<application-bnd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-application-bnd_1_2.xsd"
4+
xmlns="http://websphere.ibm.com/xml/ns/javaee"
5+
version="1.2">
6+
7+
<security-role name="architect">
8+
<group name="architect" />
9+
</security-role>
10+
11+
</application-bnd>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0"?>
2+
3+
<jboss-web>
4+
<security-domain>jaspitest</security-domain>
5+
</jboss-web>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
3+
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"
4+
version="3.0">
5+
6+
<security-constraint>
7+
<web-resource-collection>
8+
<web-resource-name>Test</web-resource-name>
9+
<url-pattern>/protected/*</url-pattern>
10+
</web-resource-collection>
11+
<auth-constraint>
12+
<role-name>architect</role-name>
13+
</auth-constraint>
14+
</security-constraint>
15+
16+
<security-role>
17+
<role-name>architect</role-name>
18+
</security-role>
19+
20+
</web-app>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package org.javaee7.jaspic.jaccpropagation;
2+
3+
import static org.junit.Assert.assertFalse;
4+
import static org.junit.Assert.assertTrue;
5+
6+
import org.javaee7.jaspic.common.ArquillianBase;
7+
import org.jboss.arquillian.container.test.api.Deployment;
8+
import org.jboss.arquillian.junit.Arquillian;
9+
import org.jboss.shrinkwrap.api.Archive;
10+
import org.junit.Test;
11+
import org.junit.runner.RunWith;
12+
13+
/**
14+
* This tests that the established authenticated identity set from JASPIC propagates correctly
15+
* to a JACC provider.
16+
*
17+
* @author Arjan Tijms
18+
*
19+
*/
20+
@RunWith(Arquillian.class)
21+
public class JACCPropagationProtectedTest extends ArquillianBase {
22+
23+
@Deployment(testable = false)
24+
public static Archive<?> createDeployment() {
25+
return defaultArchive();
26+
}
27+
28+
@Test
29+
public void callingJACCWhenAuthenticated() {
30+
31+
String response = getFromServerPath("protected/servlet?doLogin=true");
32+
33+
// This can basically only fail if JACC itself somehow doesn't work.
34+
// Unfortunately this is the case for a bunch of certified servers, which
35+
// either demand some activation of JACC, or don't ship with a default
36+
// provider at all (which are both spec violations)
37+
assertFalse(
38+
"JACC doesn't seem to be available.",
39+
response.contains("JACC doesn't seem to be available.")
40+
);
41+
42+
// Test if we have access to protected/servlet from within that servlet.
43+
// If this fails role propagation and/or JACC failed, since this is obviously
44+
// impossible.
45+
assertTrue(
46+
"Did not have access to protected servlet from within that Servlet. " +
47+
" Perhaps the roles did not propogate from JASPIC to JACC and the" +
48+
" server didn't use JACC to grant access to invoking said Servlet?",
49+
response.contains("Has access to /protected/servlet: true")
50+
);
51+
}
52+
53+
}

0 commit comments

Comments
 (0)