/* * Copyright (c) 2010 Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.ovirt.engine.api.common.security.auth; import java.util.List; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.ext.Provider; import org.jboss.resteasy.annotations.interception.Precedence; import org.jboss.resteasy.annotations.interception.ServerInterceptor; import org.jboss.resteasy.core.ResourceMethod; import org.jboss.resteasy.core.ServerResponse; import org.jboss.resteasy.spi.Failure; import org.jboss.resteasy.spi.HttpRequest; import org.jboss.resteasy.spi.interception.PreProcessInterceptor; import org.ovirt.engine.api.common.invocation.Current; @Provider @ServerInterceptor @Precedence("SECURITY") public class Challenger implements PreProcessInterceptor { private String realm; private Scheme scheme; private Validator validator; private Current current; public void setRealm(String realm) { this.realm = realm; } public void setScheme(Scheme scheme) { this.scheme = scheme; } public void setValidator(Validator validator) { this.validator = validator; } public void setCurrent(Current current) { this.current = current; } /** * Issue 401 challenge on missing or invalid credentials. * May be called further up the call-stack if supplied credentials are * found to be invalid. * * @return ServerResponse containing challenge */ public Response getChallenge() { return Response.status(Status.UNAUTHORIZED) .header(HttpHeaders.WWW_AUTHENTICATE, scheme.getChallenge(realm)) .build(); } @Override public ServerResponse preProcess(HttpRequest request, ResourceMethod method) throws Failure, WebApplicationException { ServerResponse response = null; HttpHeaders headers = request.getHttpHeaders(); List<String> auth = headers.getRequestHeader(HttpHeaders.AUTHORIZATION); if (auth == null || auth.size() == 0) { response = challenge(); } else { Principal principal = scheme.decode(headers); if (validator == null || validator.validate(principal)) { current.set(principal); current.set(this); } else { response = challenge(); } } return response; } /** * By default principal validation is lazy, with the assumption that this * will be initiated by the resource later on the dispatch path. This method * allows subclasses to pursue an alternate strategy based on eager validation. * * @param principal the decoded principal * @return true iff dispatch should continue */ protected boolean validate(Principal principal) { return true; } /** * Helper method to copy the challenge response */ private ServerResponse challenge() { return ServerResponse.copyIfNotServerResponse(getChallenge()); } }