Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JASPIC ServerAuthModule and ServerAuthContext spec compliance fixes #375

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class SamAutoRegistrationListener extends BaseServletContextListener {

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class SamAutoRegistrationListener extends BaseServletContextListener {

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
import static javax.security.auth.message.AuthStatus.SUCCESS;
import static javax.security.auth.message.AuthStatus.SEND_CONTINUE;
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;

import java.io.IOException;
import java.security.Principal;
Expand Down Expand Up @@ -44,6 +46,7 @@ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject
throws AuthException {

HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();

Callback[] callbacks;

Expand All @@ -58,8 +61,12 @@ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject
// the roles of the authenticated user
new GroupPrincipalCallback(clientSubject, new String[] { "architect" })
};
} else if(messageInfo.getMap().get("javax.security.auth.message.MessagePolicy.isMandatory").equals("true")) {

// Must set error code is authentication is mandatory, but unsuccessful
response.setStatus(SC_UNAUTHORIZED);
return SEND_CONTINUE;
} else {

// The JASPIC protocol for "do nothing"
callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) };
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ private JaspicUtils() {
*
* @param serverAuthModule
*/
public static void registerSAM(ServletContext context, ServerAuthModule serverAuthModule) {
AuthConfigFactory.getFactory().registerConfigProvider(new TestAuthConfigProvider(serverAuthModule), "HttpServlet",
public static void registerSAM(ServletContext context, Class<? extends ServerAuthModule> serverAuthModuleClass) {
AuthConfigFactory.getFactory().registerConfigProvider(new TestAuthConfigProvider(serverAuthModuleClass), "HttpServlet",
getAppContextID(context), "Test authentication config provider");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ public class TestAuthConfigProvider implements AuthConfigProvider {
private static final String CALLBACK_HANDLER_PROPERTY_NAME = "authconfigprovider.client.callbackhandler";

private Map<String, String> providerProperties;
private ServerAuthModule serverAuthModule;
private Class<? extends ServerAuthModule> serverAuthModuleClass;

public TestAuthConfigProvider(ServerAuthModule serverAuthModule) {
this.serverAuthModule = serverAuthModule;
public TestAuthConfigProvider(Class<? extends ServerAuthModule> serverAuthModuleClass) {
this.serverAuthModuleClass = serverAuthModuleClass;
}

/**
Expand Down Expand Up @@ -53,7 +53,7 @@ public TestAuthConfigProvider(Map<String, String> properties, AuthConfigFactory
public ServerAuthConfig getServerAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException,
SecurityException {
return new TestServerAuthConfig(layer, appContext, handler == null ? createDefaultCallbackHandler() : handler,
providerProperties, serverAuthModule);
providerProperties, serverAuthModuleClass);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,21 @@ public class TestServerAuthConfig implements ServerAuthConfig {
private String appContext;
private CallbackHandler handler;
private Map<String, String> providerProperties;
private ServerAuthModule serverAuthModule;
private Class<? extends ServerAuthModule> serverAuthModuleClass;

public TestServerAuthConfig(String layer, String appContext, CallbackHandler handler,
Map<String, String> providerProperties, ServerAuthModule serverAuthModule) {
Map<String, String> providerProperties, Class<? extends ServerAuthModule> serverAuthModuleClass) {
this.layer = layer;
this.appContext = appContext;
this.handler = handler;
this.providerProperties = providerProperties;
this.serverAuthModule = serverAuthModule;
this.serverAuthModuleClass = serverAuthModuleClass;
}

@Override
public ServerAuthContext getAuthContext(String authContextID, Subject serviceSubject,
@SuppressWarnings("rawtypes") Map properties) throws AuthException {
return new TestServerAuthContext(handler, serverAuthModule);
return new TestServerAuthContext(handler, serverAuthModuleClass);
}

// ### The methods below mostly just return what has been passed into the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package org.javaee7.jaspic.common;

import java.lang.reflect.InvocationTargetException;
import java.util.Collections;

import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
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.MessagePolicy.TargetPolicy;
import javax.security.auth.message.MessagePolicy.ProtectionPolicy;
import javax.security.auth.message.ServerAuth;
import javax.security.auth.message.config.ServerAuthContext;
import javax.security.auth.message.module.ServerAuthModule;
Expand All @@ -22,28 +26,60 @@
* @author Arjan Tijms
*/
public class TestServerAuthContext implements ServerAuthContext {

private static TargetPolicy[] targetPolicyArr = { new TargetPolicy(null, new ProtectionPolicy() {
public String getID() {
return ProtectionPolicy.AUTHENTICATE_SENDER;
}
}) };

private static MessagePolicy mandatoryRequestPolicy = new MessagePolicy(targetPolicyArr, true);
private static MessagePolicy optionalRequestPolicy = new MessagePolicy(targetPolicyArr, false);

private final ServerAuthModule serverAuthModule;
private ServerAuthModule mandatoryServerAuthModule;
private ServerAuthModule optionalServerAuthModule;

private ServerAuthModule chooseModule(MessageInfo messageInfo){
if("true".equals(messageInfo.getMap().get("javax.security.auth.message.MessagePolicy.isMandatory"))) {
return mandatoryServerAuthModule;
} else {
return optionalServerAuthModule;
}
}

public TestServerAuthContext(CallbackHandler handler, Class<? extends ServerAuthModule> serverAuthModuleClass) throws AuthException {

//The spec requires that the mandatory authentication parameter can be accessed from the requestPolicy,
//even though it is not really useful, as the same information is available from the messageInfo map.
//To satisfy this requirement two SAM objects are constructed, and they are initialized with the appropriate requestPolicies.

try {
mandatoryServerAuthModule = serverAuthModuleClass.getConstructor().newInstance();
mandatoryServerAuthModule.initialize(mandatoryRequestPolicy, null, handler, Collections.<String, String> emptyMap());

optionalServerAuthModule = serverAuthModuleClass.getConstructor().newInstance();
optionalServerAuthModule.initialize(optionalRequestPolicy, null, handler, Collections.<String, String> emptyMap());
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
throw new AuthException();
}

public TestServerAuthContext(CallbackHandler handler, ServerAuthModule serverAuthModule) throws AuthException {
this.serverAuthModule = serverAuthModule;
serverAuthModule.initialize(null, null, handler, Collections.<String, String> emptyMap());
}

@Override
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
throws AuthException {
return serverAuthModule.validateRequest(messageInfo, clientSubject, serviceSubject);
return chooseModule(messageInfo).validateRequest(messageInfo, clientSubject, serviceSubject);
}

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

@Override
public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
serverAuthModule.cleanSubject(messageInfo, subject);
chooseModule(messageInfo).cleanSubject(messageInfo, subject);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class SamAutoRegistrationListener extends BaseServletContextListener {

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
import static javax.security.auth.message.AuthStatus.SUCCESS;
import static javax.security.auth.message.AuthStatus.SEND_CONTINUE;
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;

import java.io.IOException;
import java.security.Principal;
Expand Down Expand Up @@ -44,6 +46,7 @@ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject
throws AuthException {

HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();

Callback[] callbacks;

Expand All @@ -59,8 +62,12 @@ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject
// the roles of the authenticated user
new GroupPrincipalCallback(clientSubject, new String[] { "architect" })
};
} else if(messageInfo.getMap().get("javax.security.auth.message.MessagePolicy.isMandatory").equals("true")) {

// Must set error code if authentication is mandatory, but unsuccessful
response.setStatus(SC_UNAUTHORIZED);
return SEND_CONTINUE;
} else {

// The JASPIC protocol for "do nothing"
callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) };
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class SamAutoRegistrationListener extends BaseServletContextListener {

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static javax.security.auth.message.AuthStatus.SEND_CONTINUE;
import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
import static javax.security.auth.message.AuthStatus.SUCCESS;
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;

import java.io.IOException;
import java.security.Principal;
Expand Down Expand Up @@ -44,26 +45,34 @@ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject
try {
HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();

if ("include".equals(request.getParameter("dispatch"))) {

String target = "/includedServlet";
if ("jsf".equals(request.getParameter("tech"))) {
target = "/include.jsf";
} else if ("jsfcdi".equals(request.getParameter("tech"))) {
target = "/include-cdi.jsf";
if(messageInfo.getMap().get("javax.security.auth.message.MessagePolicy.isMandatory").equals("true")) {
//Since we do not set a principal, authentication is unsuccessful

response.setStatus(SC_UNAUTHORIZED);
return SEND_CONTINUE;
} else {

String target = "/includedServlet";
if ("jsf".equals(request.getParameter("tech"))) {
target = "/include.jsf";
} else if ("jsfcdi".equals(request.getParameter("tech"))) {
target = "/include-cdi.jsf";
}

request.getRequestDispatcher(target)
.include(request, response);

// "Do nothing", required protocol when returning SUCCESS
handler.handle(new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) });

// When using includes, the response stays open and the main
// resource can also
// write to the response
return SUCCESS;
}

request.getRequestDispatcher(target)
.include(request, response);

// "Do nothing", required protocol when returning SUCCESS
handler.handle(new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) });

// When using includes, the response stays open and the main
// resource can also
// write to the response
return SUCCESS;

} else {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class SamAutoRegistrationListener extends BaseServletContextListener {

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static javax.security.auth.message.AuthStatus.SEND_CONTINUE;
import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
import static javax.security.auth.message.AuthStatus.SUCCESS;
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;

import java.io.IOException;
import java.security.Principal;
Expand Down Expand Up @@ -42,19 +43,27 @@ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
try {
HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();

HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
if ("include".equals(request.getParameter("dispatch"))) {
request.getRequestDispatcher("/includedServlet")
.include(request, response);

// "Do nothing", required protocol when returning SUCCESS
handler.handle(new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) });

// When using includes, the response stays open and the main
// resource can also write to the response
return SUCCESS;


if(messageInfo.getMap().get("javax.security.auth.message.MessagePolicy.isMandatory").equals("true")) {
//Since we do not set a principal, authentication is unsuccessful

response.setStatus(SC_UNAUTHORIZED);
return SEND_CONTINUE;
} else {

request.getRequestDispatcher("/includedServlet")
.include(request, response);

// "Do nothing", required protocol when returning SUCCESS
handler.handle(new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) });

// When using includes, the response stays open and the main
// resource can also write to the response
return SUCCESS;
}
} else {
request.getRequestDispatcher("/forwardedServlet")
.forward(request, response);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class SamAutoRegistrationListener extends BaseServletContextListener {

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

}
Loading