AMAuthNFilter.java revision ac5abaa43bb3f660295d002e94650a1770dc1c68
640b2adac05bb7f5e9fba064434c91852c3a72e6nd/*
8e34905974b7a442a55adac3b3fdb196c389e807takashi * The contents of this file are subject to the terms of the Common Development and
640b2adac05bb7f5e9fba064434c91852c3a72e6nd * Distribution License (the License). You may not use this file except in compliance with the
640b2adac05bb7f5e9fba064434c91852c3a72e6nd * License.
8e34905974b7a442a55adac3b3fdb196c389e807takashi *
640b2adac05bb7f5e9fba064434c91852c3a72e6nd * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
640b2adac05bb7f5e9fba064434c91852c3a72e6nd * specific language governing permission and limitations under the License.
8e34905974b7a442a55adac3b3fdb196c389e807takashi *
640b2adac05bb7f5e9fba064434c91852c3a72e6nd * When distributing Covered Software, include this CDDL Header Notice in each file and include
640b2adac05bb7f5e9fba064434c91852c3a72e6nd * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
640b2adac05bb7f5e9fba064434c91852c3a72e6nd * Header, with the fields enclosed by brackets [] replaced by your own identifying
640b2adac05bb7f5e9fba064434c91852c3a72e6nd * information: "Portions copyright [year] [name of copyright owner]".
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive *
8e34905974b7a442a55adac3b3fdb196c389e807takashi * Copyright 2013 ForgeRock AS.
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive */
ef685e00a47967e27d89709461728a229d762172nd
ef685e00a47967e27d89709461728a229d762172ndpackage org.forgerock.openam.jaspi.config;
ef685e00a47967e27d89709461728a229d762172nd
a27e9e05958bc51ea09edb8d8d862fe8b125313bsliveimport com.sun.identity.shared.debug.Debug;
a27e9e05958bc51ea09edb8d8d862fe8b125313bsliveimport org.forgerock.jaspi.filter.AuthNFilter;
51853aa2ebfdf9903a094467e1d02099f143639daaron
a27e9e05958bc51ea09edb8d8d862fe8b125313bsliveimport javax.servlet.FilterChain;
a27e9e05958bc51ea09edb8d8d862fe8b125313bsliveimport javax.servlet.FilterConfig;
a27e9e05958bc51ea09edb8d8d862fe8b125313bsliveimport javax.servlet.ServletException;
a27e9e05958bc51ea09edb8d8d862fe8b125313bsliveimport javax.servlet.ServletRequest;
a27e9e05958bc51ea09edb8d8d862fe8b125313bsliveimport javax.servlet.ServletResponse;
8e34905974b7a442a55adac3b3fdb196c389e807takashiimport javax.servlet.http.HttpServletRequest;
a27e9e05958bc51ea09edb8d8d862fe8b125313bsliveimport javax.ws.rs.HttpMethod;
ef685e00a47967e27d89709461728a229d762172ndimport java.io.IOException;
ef685e00a47967e27d89709461728a229d762172ndimport java.util.HashSet;
a27e9e05958bc51ea09edb8d8d862fe8b125313bsliveimport java.util.Set;
222f0f03c2f9ee6343c18f80f0cb6e9aad21bc58slive
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive/**
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive * Adds a check to see if the REST endpoint being hit is the authentication endpoint and if is then will skip
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive * the authentication check. All other REST endpoints will be protected resulting in the request requiring a
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive * SSOToken cookie set.
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive *
d7a419db04e3affddabed19294a548a5a4f4122crbowen * @author Phill Cunnington
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive */
17ca00f92106c825382359ebf0a754f8df21e316rbowenpublic class AMAuthNFilter extends AuthNFilter {
d7a419db04e3affddabed19294a548a5a4f4122crbowen
d7a419db04e3affddabed19294a548a5a4f4122crbowen private static final Debug DEBUG = Debug.getInstance("amIdentityServices");
17ca00f92106c825382359ebf0a754f8df21e316rbowen
17ca00f92106c825382359ebf0a754f8df21e316rbowen private final static Set<UnprotectedEndpoint> unprotectedRestEndpoints = new HashSet<UnprotectedEndpoint>();
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive /**
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive * Only the REST Authentication Endpoint is unprotected. Other endpoints that don't need to be authenticated
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive * as a "real" user can use the anonymous use to authenticate first, then use an Authorization Filter to
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive * allow the anonymous user access.
8e34905974b7a442a55adac3b3fdb196c389e807takashi */
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive static {
ef685e00a47967e27d89709461728a229d762172nd unprotectedRestEndpoints.add(new UnprotectedEndpoint("/json/auth/1/authenticate", HttpMethod.GET));
ef685e00a47967e27d89709461728a229d762172nd unprotectedRestEndpoints.add(new UnprotectedEndpoint("/json/auth/1/authenticate", HttpMethod.POST));
ef685e00a47967e27d89709461728a229d762172nd }
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive
222f0f03c2f9ee6343c18f80f0cb6e9aad21bc58slive /**
45220913988eb2543fff442282c4aaa6b20559a8rbowen * Models an UnprotectedEndpoint.
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive */
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive private static class UnprotectedEndpoint {
a27e9e05958bc51ea09edb8d8d862fe8b125313bslive
222f0f03c2f9ee6343c18f80f0cb6e9aad21bc58slive private final String uri;
95e8cab14596a61826fa52477dcaebc07bfbad00colm private final String httpMethod;
8e34905974b7a442a55adac3b3fdb196c389e807takashi
95e8cab14596a61826fa52477dcaebc07bfbad00colm /**
95e8cab14596a61826fa52477dcaebc07bfbad00colm * Constructs an instance of an UnprotectedEndpoint.
95e8cab14596a61826fa52477dcaebc07bfbad00colm *
95e8cab14596a61826fa52477dcaebc07bfbad00colm * @param uri The Uri of the unprotected endpoint.
95e8cab14596a61826fa52477dcaebc07bfbad00colm * @param httpMethod The Http method allowed for the unprotected endpoint.
95e8cab14596a61826fa52477dcaebc07bfbad00colm */
95e8cab14596a61826fa52477dcaebc07bfbad00colm public UnprotectedEndpoint(String uri, String httpMethod) {
95e8cab14596a61826fa52477dcaebc07bfbad00colm this.uri = uri;
95e8cab14596a61826fa52477dcaebc07bfbad00colm this.httpMethod = httpMethod;
95e8cab14596a61826fa52477dcaebc07bfbad00colm }
17efa6b5344b7574597eec03f02ef28103e19265nd
8e34905974b7a442a55adac3b3fdb196c389e807takashi /**
17efa6b5344b7574597eec03f02ef28103e19265nd * Determines if two unprotected endpoints are equal.
17efa6b5344b7574597eec03f02ef28103e19265nd *
17efa6b5344b7574597eec03f02ef28103e19265nd * @param o {@inheritDoc}
17efa6b5344b7574597eec03f02ef28103e19265nd * @return {@inheritDoc}
17efa6b5344b7574597eec03f02ef28103e19265nd */
17efa6b5344b7574597eec03f02ef28103e19265nd @Override
17efa6b5344b7574597eec03f02ef28103e19265nd public boolean equals(Object o) {
17efa6b5344b7574597eec03f02ef28103e19265nd if (this == o) return true;
17efa6b5344b7574597eec03f02ef28103e19265nd if (o == null || getClass() != o.getClass()) return false;
17efa6b5344b7574597eec03f02ef28103e19265nd
86bb9693d63dfc1be14519a5b444467e4b0cdaf8kawai UnprotectedEndpoint that = (UnprotectedEndpoint) o;
8e34905974b7a442a55adac3b3fdb196c389e807takashi
86bb9693d63dfc1be14519a5b444467e4b0cdaf8kawai if (!httpMethod.equals(that.httpMethod)) return false;
86bb9693d63dfc1be14519a5b444467e4b0cdaf8kawai if (!uri.equals(that.uri)) return false;
86bb9693d63dfc1be14519a5b444467e4b0cdaf8kawai
86bb9693d63dfc1be14519a5b444467e4b0cdaf8kawai return true;
86bb9693d63dfc1be14519a5b444467e4b0cdaf8kawai }
8e34905974b7a442a55adac3b3fdb196c389e807takashi
86bb9693d63dfc1be14519a5b444467e4b0cdaf8kawai /**
86bb9693d63dfc1be14519a5b444467e4b0cdaf8kawai * Determines the hash code for this unprotected endpoint.
86bb9693d63dfc1be14519a5b444467e4b0cdaf8kawai *
86bb9693d63dfc1be14519a5b444467e4b0cdaf8kawai * @return {@inheritDoc}
17efa6b5344b7574597eec03f02ef28103e19265nd */
8e34905974b7a442a55adac3b3fdb196c389e807takashi @Override
17efa6b5344b7574597eec03f02ef28103e19265nd public int hashCode() {
17efa6b5344b7574597eec03f02ef28103e19265nd int result = uri.hashCode();
8e34905974b7a442a55adac3b3fdb196c389e807takashi result = 31 * result + httpMethod.hashCode();
17efa6b5344b7574597eec03f02ef28103e19265nd return result;
17efa6b5344b7574597eec03f02ef28103e19265nd }
8e34905974b7a442a55adac3b3fdb196c389e807takashi }
17efa6b5344b7574597eec03f02ef28103e19265nd
17efa6b5344b7574597eec03f02ef28103e19265nd /**
17efa6b5344b7574597eec03f02ef28103e19265nd * {@inheritDoc}
17efa6b5344b7574597eec03f02ef28103e19265nd */
cd51960ffc0f49d7a9e702162ed49b3eb0909276dirkx public void init(FilterConfig filterConfig) throws ServletException {
8e34905974b7a442a55adac3b3fdb196c389e807takashi super.init(filterConfig);
cd51960ffc0f49d7a9e702162ed49b3eb0909276dirkx }
ef685e00a47967e27d89709461728a229d762172nd
ef685e00a47967e27d89709461728a229d762172nd /**
ef685e00a47967e27d89709461728a229d762172nd * Parses the URI and request method from the request and creates an UnprotectedEndpoint object and compares it
cd51960ffc0f49d7a9e702162ed49b3eb0909276dirkx * against the set of valid UnprotectedEndpoints. If it matches then the request is passed down the filter chain,
cd51960ffc0f49d7a9e702162ed49b3eb0909276dirkx * if it doesn't match then the Commons Authentication Filter is given the request to authenticate it first.
cd51960ffc0f49d7a9e702162ed49b3eb0909276dirkx *
cd51960ffc0f49d7a9e702162ed49b3eb0909276dirkx * @param servletRequest {@inheritDoc}
cd51960ffc0f49d7a9e702162ed49b3eb0909276dirkx * @param servletResponse {@inheritDoc}
cd51960ffc0f49d7a9e702162ed49b3eb0909276dirkx * @param filterChain {@inheritDoc}
94abf1cc80072ea31506946ac6595631ca6d2c14rbowen * @throws IOException {@inheritDoc}
94abf1cc80072ea31506946ac6595631ca6d2c14rbowen * @throws ServletException {@inheritDoc}
94abf1cc80072ea31506946ac6595631ca6d2c14rbowen */
94abf1cc80072ea31506946ac6595631ca6d2c14rbowen public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
94abf1cc80072ea31506946ac6595631ca6d2c14rbowen throws IOException, ServletException {
94abf1cc80072ea31506946ac6595631ca6d2c14rbowen
94abf1cc80072ea31506946ac6595631ca6d2c14rbowen HttpServletRequest request = (HttpServletRequest) servletRequest;
94abf1cc80072ea31506946ac6595631ca6d2c14rbowen
94abf1cc80072ea31506946ac6595631ca6d2c14rbowen String contextPath = request.getContextPath();
94abf1cc80072ea31506946ac6595631ca6d2c14rbowen
94abf1cc80072ea31506946ac6595631ca6d2c14rbowen String requestURI = request.getRequestURI();
94abf1cc80072ea31506946ac6595631ca6d2c14rbowen
94abf1cc80072ea31506946ac6595631ca6d2c14rbowen String path = requestURI.substring(contextPath.length());
b5468eddc0cb1691af19ddc70a6e205daf00a94ctrawick
8e34905974b7a442a55adac3b3fdb196c389e807takashi if (unprotectedRestEndpoints.contains(new UnprotectedEndpoint(path, request.getMethod()))) {
b5468eddc0cb1691af19ddc70a6e205daf00a94ctrawick DEBUG.message("Path: " + path + " Method: " + request.getMethod() + " Added as exception. Not protected.");
1b3225113bb6fcf326cf16af9023e381ae0ac083nd filterChain.doFilter(servletRequest, servletResponse);
1f666f93c91dbb492dc7706573b369cd03b84265poirier } else {
b5468eddc0cb1691af19ddc70a6e205daf00a94ctrawick DEBUG.message("Path: " + path + " Method: " + request.getMethod() + " Protected resource.");
b5468eddc0cb1691af19ddc70a6e205daf00a94ctrawick super.doFilter(servletRequest, servletResponse, filterChain);
1f666f93c91dbb492dc7706573b369cd03b84265poirier }
b5468eddc0cb1691af19ddc70a6e205daf00a94ctrawick }
b5468eddc0cb1691af19ddc70a6e205daf00a94ctrawick}
b5468eddc0cb1691af19ddc70a6e205daf00a94ctrawick