/* * Copyright (c) 2014, 2015 Hewlett-Packard Development Company, L.P. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.aaa.sts; import com.sun.jersey.spi.container.ContainerRequest; import com.sun.jersey.spi.container.ContainerRequestFilter; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import org.apache.oltu.oauth2.common.exception.OAuthProblemException; import org.apache.oltu.oauth2.common.exception.OAuthSystemException; import org.apache.oltu.oauth2.common.message.types.ParameterStyle; import org.apache.oltu.oauth2.rs.request.OAuthAccessResourceRequest; import org.opendaylight.aaa.api.Authentication; import org.opendaylight.aaa.api.AuthenticationException; import org.opendaylight.aaa.api.TokenAuth; /** * A token-based authentication filter for resource providers. * * Deprecated: Use AAAFilter instead. * * @author liemmn * */ @Deprecated public class TokenAuthFilter implements ContainerRequestFilter { private final String OPTIONS = "OPTIONS"; private final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers"; private final String AUTHORIZATION = "authorization"; @Context private HttpServletRequest httpRequest; @Override public ContainerRequest filter(ContainerRequest request) { // Do the CORS check first if (checkCORSOptionRequest(request)) { return request; } // Are we up yet? if (ServiceLocator.getInstance().getAuthenticationService() == null) { throw new WebApplicationException( Response.status(Status.SERVICE_UNAVAILABLE).type(MediaType.APPLICATION_JSON) .entity("{\"error\":\"Authentication service unavailable\"}").build()); } // Are we doing authentication or not? if (ServiceLocator.getInstance().getAuthenticationService().isAuthEnabled()) { Map> headers = request.getRequestHeaders(); // Go through and invoke other TokenAuth first... List tokenAuthCollection = ServiceLocator.getInstance() .getTokenAuthCollection(); for (TokenAuth ta : tokenAuthCollection) { try { Authentication auth = ta.validate(headers); if (auth != null) { ServiceLocator.getInstance().getAuthenticationService().set(auth); return request; } } catch (AuthenticationException ae) { throw unauthorized(); } } // OK, last chance to validate token... try { OAuthAccessResourceRequest or = new OAuthAccessResourceRequest(httpRequest, ParameterStyle.HEADER); validate(or.getAccessToken()); } catch (OAuthSystemException | OAuthProblemException e) { throw unauthorized(); } } return request; } /** * CORS access control : when browser sends cross-origin request, it first * sends the OPTIONS method with a list of access control request headers, * which has a list of custom headers and access control method such as GET. * POST etc. You custom header "Authorization will not be present in request * header, instead it will be present as a value inside * Access-Control-Request-Headers. We should not do any authorization * against such request. for more details : * https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS */ private boolean checkCORSOptionRequest(ContainerRequest request) { if (OPTIONS.equals(request.getMethod())) { List headerList = request.getRequestHeader(ACCESS_CONTROL_REQUEST_HEADERS); if (headerList != null && !headerList.isEmpty()) { String header = headerList.get(0); if (header != null && header.toLowerCase().contains(AUTHORIZATION)) { return true; } } } return false; } // Validate an ODL token... private Authentication validate(final String token) { Authentication auth = ServiceLocator.getInstance().getTokenStore().get(token); if (auth == null) { throw unauthorized(); } else { ServiceLocator.getInstance().getAuthenticationService().set(auth); } return auth; } // Houston, we got a problem! private static final WebApplicationException unauthorized() { ServiceLocator.getInstance().getAuthenticationService().clear(); return new UnauthorizedException(); } // A custom 401 web exception that handles http basic response as well static final class UnauthorizedException extends WebApplicationException { private static final long serialVersionUID = -1732363804773027793L; static final String WWW_AUTHENTICATE = "WWW-Authenticate"; static final Object OPENDAYLIGHT = "Basic realm=\"opendaylight\""; private static final Response response = Response.status(Status.UNAUTHORIZED) .header(WWW_AUTHENTICATE, OPENDAYLIGHT) .build(); public UnauthorizedException() { super(response); } } }