/*
* This is eMonocot, a global online biodiversity information resource.
*
* Copyright © 2011–2015 The Board of Trustees of the Royal Botanic Gardens, Kew and The University of Oxford
*
* eMonocot is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* eMonocot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* The complete text of the GNU Affero General Public License is in the source repository as the file
* ‘COPYING’. It is also available from <http://www.gnu.org/licenses/>.
*/
package org.emonocot.portal.auth;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
public class RestAPIKeyAuthenticationFilter extends
AbstractAuthenticationProcessingFilter {
private static final String API_KEY_PARAMETER_NAME = "apikey";
private static Logger logger = LoggerFactory.getLogger(RestAPIKeyAuthenticationFilter.class);
protected RestAPIKeyAuthenticationFilter(String defaultFilterProcessesUrl) {
super(defaultFilterProcessesUrl);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException,
IOException, ServletException {
String apiKeyValue = decodeParameterValue(request, API_KEY_PARAMETER_NAME);
logger.debug("attemptAuthentication " + apiKeyValue);
AbstractAuthenticationToken authRequest = createAuthenticationToken(
apiKeyValue, new RestCredentials());
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, authResult);
chain.doFilter(request, response);
}
private String decodeParameterValue(HttpServletRequest request,
String requestParameterName) throws UnsupportedEncodingException {
// This is basically to avoid the weird RFC spec when it comes to spaces
// in the URL and how they are encoded
return URLDecoder.decode(
getParameterValue(request, requestParameterName),
request.getCharacterEncoding()).replaceAll(" ", "+");
}
private String getParameterValue(HttpServletRequest request,
String requestParameterName) {
return (request.getParameter(requestParameterName) != null) ? request
.getParameter(requestParameterName) : "";
}
/**
* Provided so that subclasses may configure what is put into the
* authentication request's details property.
*
* @param request
* that an authentication request is being created for
* @param authRequest
* the authentication request object that should have its details
* set
*/
protected void setDetails(HttpServletRequest request,
AbstractAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource
.buildDetails(request));
}
private AbstractAuthenticationToken createAuthenticationToken(
String apiKeyValue, RestCredentials restCredentials) {
return new RestAuthenticationToken(apiKeyValue, restCredentials);
}
@Override
protected boolean requiresAuthentication(HttpServletRequest request,
HttpServletResponse response) {
logger.debug("Requires Authentication " + (request.getParameter(API_KEY_PARAMETER_NAME) != null));
return request.getParameter(API_KEY_PARAMETER_NAME) != null;
}
}