/** * */ package org.minnal.security.filter; import java.io.IOException; import java.util.Map; import javax.annotation.Priority; import javax.ws.rs.Priorities; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.NewCookie; import javax.ws.rs.core.Response; import org.glassfish.jersey.message.internal.OutboundMessageContext; import org.minnal.security.auth.JaxrsWebContext; import org.minnal.security.auth.User; import org.minnal.security.config.SecurityConfiguration; import org.minnal.security.session.Session; import org.minnal.utils.reflection.Generics; import org.minnal.utils.serializer.Serializer; import org.pac4j.core.client.Client; import org.pac4j.core.client.Clients; import org.pac4j.core.exception.RequiresHttpAction; import org.pac4j.core.exception.TechnicalException; import org.pac4j.core.profile.UserProfile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Strings; /** * @author ganeshs * */ @Priority(Priorities.AUTHENTICATION) public class AuthenticationFilter extends AbstractSecurityFilter implements ContainerRequestFilter, ContainerResponseFilter { private Clients clients; public static final String PRINCIPAL = "principal"; protected AuthenticationListener listener; private static final Logger logger = LoggerFactory.getLogger(AuthenticationFilter.class); /** * @param clients * @param configuration */ public AuthenticationFilter(Clients clients, SecurityConfiguration configuration) { super(configuration); this.clients = clients; } /** * @return the clients */ public Clients getClients() { return clients; } @Override public void filter(ContainerRequestContext request) { Session session = getSession(request, true); request.setProperty(SESSION, session); if (isWhiteListed(request)) { logger.debug("Request path {} is in whitelisted set of urls. Skipping authentication", request.getUriInfo()); return; } if (isAuthenticated(session)) { logger.debug("Session is already authenticated. Skipping authentication"); return; } JaxrsWebContext context = getContext(request, session); Client client = getClient(context); if (client != null) { session.addAttribute(Clients.DEFAULT_CLIENT_NAME_PARAMETER, client.getName()); getConfiguration().getSessionStore().save(session); try { client.redirect(context, false, false); } catch (RequiresHttpAction e) { logger.error("Failed while redirecting the request", e); context.setResponseStatus(e.getCode()); } } else { context.setResponseStatus(Response.Status.UNAUTHORIZED.getStatusCode()); } context.setResponseHeader(HttpHeaders.SET_COOKIE, createSessionCookie(session).toString()); request.abortWith(context.getResponse()); } @Override public void filter(ContainerRequestContext request, ContainerResponseContext response) throws IOException { Session session = getSession(request, true); response.getHeaders().add(HttpHeaders.SET_COOKIE, createSessionCookie(session).toString()); } /** * Creates a session cookie * * @param session * @return */ private NewCookie createSessionCookie(Session session) { return new NewCookie(AUTH_COOKIE, session.getId(), "/", null, null, NewCookie.DEFAULT_MAX_AGE, false); } /** * Checks if the session is already authenticated * * @param session * @return */ protected boolean isAuthenticated(Session session) { return retrieveProfile(session) != null; } protected JaxrsWebContext getContext(ContainerRequestContext request, Session session) { return new JaxrsWebContext(request, new OutboundMessageContext(), session); } protected boolean isWhiteListed(ContainerRequestContext request) { for (String url : getConfiguration().getWhiteListedUrls()) { if (request.getUriInfo().getPath().startsWith(url)) { return true; } } return false; } @SuppressWarnings("rawtypes") protected User retrieveProfile(Session session) { Object profile = session.getAttribute(PRINCIPAL); if (profile == null) { return null; } Client client = getClient(session); Class<UserProfile> type = Generics.getTypeParameter(client.getClass(), UserProfile.class); if (type.isAssignableFrom(profile.getClass())) { return new User((UserProfile) profile); } if (profile instanceof Map) { String buffer = Serializer.DEFAULT_JSON_SERIALIZER.serialize(profile); profile = Serializer.DEFAULT_JSON_SERIALIZER.deserialize(buffer, type); User user = new User((UserProfile) profile); session.addAttribute(PRINCIPAL, profile); return user; } // Can't come here return null; } protected Client getClient(Session session) { String clientName = session.getAttribute(Clients.DEFAULT_CLIENT_NAME_PARAMETER); if (Strings.isNullOrEmpty(clientName)) { return null; } return clients.findClient(clientName); } protected Client getClient(JaxrsWebContext context) { try { return clients.findClient(context); } catch (TechnicalException e) { logger.debug("Error while getting the client from the context", e); return null; } } /** * Registers the authentication listener * * @param listener */ public void registerListener(AuthenticationListener listener) { this.listener = listener; } }