2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.be.filters;
23 import com.google.gson.Gson;
24 import com.google.gson.GsonBuilder;
25 import fj.data.Either;
26 import org.apache.commons.codec.binary.Base64;
27 import org.openecomp.sdc.be.components.impl.ConsumerBusinessLogic;
28 import org.openecomp.sdc.be.dao.api.ActionStatus;
29 import org.openecomp.sdc.be.impl.ComponentsUtils;
30 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
31 import org.openecomp.sdc.be.model.ConsumerDefinition;
32 import org.openecomp.sdc.common.api.Constants;
33 import org.openecomp.sdc.common.log.enums.LogLevel;
34 import org.openecomp.sdc.common.log.enums.Severity;
35 import org.openecomp.sdc.common.log.wrappers.Logger;
36 import org.openecomp.sdc.common.log.wrappers.LoggerSdcAudit;
37 import org.openecomp.sdc.exception.ResponseFormat;
38 import org.openecomp.sdc.security.Passwords;
39 import org.springframework.web.context.WebApplicationContext;
41 import javax.annotation.Priority;
42 import javax.servlet.ServletContext;
43 import javax.servlet.http.HttpServletRequest;
44 import javax.ws.rs.container.ContainerRequestContext;
45 import javax.ws.rs.container.ContainerRequestFilter;
46 import javax.ws.rs.core.Context;
47 import javax.ws.rs.core.Response;
48 import javax.ws.rs.core.Response.ResponseBuilder;
49 import javax.ws.rs.core.Response.Status;
50 import java.io.IOException;
51 import java.io.UnsupportedEncodingException;
52 import java.util.StringTokenizer;
55 public class BasicAuthenticationFilter implements ContainerRequestFilter {
57 private static LoggerSdcAudit audit = new LoggerSdcAudit(BasicAuthenticationFilter.class);
58 private static final Logger log = Logger.getLogger(BasicAuthenticationFilter.class);
59 private static final String COMPONENT_UTILS_FAILED = "Authentication Filter Failed to get component utils.";
60 private static final String CONSUMER_BL_FAILED = "Authentication Filter Failed to get consumerBL.";
63 private HttpServletRequest sr;
65 protected Gson gson = new GsonBuilder().setPrettyPrinting().create();
67 private String realm = "ASDC";
71 public void filter(ContainerRequestContext requestContext) throws IOException {
73 audit.startLog(requestContext);
75 String authHeader = requestContext.getHeaderString(Constants.AUTHORIZATION_HEADER);
76 if (authHeader != null) {
77 StringTokenizer st = new StringTokenizer(authHeader);
78 String failedToRetrieveAuthErrorMsg = "Authentication Filter Failed Couldn't retrieve authentication, no basic authentication.";
79 if (st.hasMoreTokens()) {
80 String basic = st.nextToken();
82 if ("Basic".equalsIgnoreCase(basic)) {
84 String credentials = new String(Base64.decodeBase64(st.nextToken()), "UTF-8");
85 log.debug("Credentials: {}", credentials);
86 checkUserCredentials(requestContext, credentials);
87 } catch (UnsupportedEncodingException e) {
88 log.error("Authentication Filter Failed Couldn't retrieve authentication", e);
89 authInvalidHeaderError(requestContext);
92 log.error(failedToRetrieveAuthErrorMsg);
93 authInvalidHeaderError(requestContext);
96 log.error(failedToRetrieveAuthErrorMsg);
97 authInvalidHeaderError(requestContext);
101 log.error("Authentication Filter Failed no authorization header");
102 authRequiredError(requestContext);
106 private void checkUserCredentials(ContainerRequestContext requestContext, String credentials) {
107 int p = credentials.indexOf(':');
109 String userName = credentials.substring(0, p).trim();
110 String password = credentials.substring(p + 1).trim();
112 ConsumerBusinessLogic consumerBL = getConsumerBusinessLogic();
113 if (consumerBL == null) {
114 abortWith(requestContext, CONSUMER_BL_FAILED, Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build());
116 Either<ConsumerDefinition, ResponseFormat> result = consumerBL.getConsumer(userName);
117 validatePassword(requestContext, userName, password, result);
120 log.error("Authentication Filter Failed Couldn't retrieve authentication, no basic authentication.");
121 authInvalidHeaderError(requestContext);
126 private void validatePassword(ContainerRequestContext requestContext, String userName, String password, Either<ConsumerDefinition, ResponseFormat> result) {
127 if (result.isRight()) {
128 Integer status = result.right().value().getStatus();
129 if (status == Status.NOT_FOUND.getStatusCode()) {
130 log.error("Authentication Filter Failed Couldn't find user");
131 authUserNotFoundError(requestContext, userName);
133 abortWith(requestContext, CONSUMER_BL_FAILED, Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build());
136 ConsumerDefinition consumerCredentials = result.left().value();
137 if (!Passwords.isExpectedPassword(password, consumerCredentials.getConsumerSalt(), consumerCredentials.getConsumerPassword())) {
138 log.error("Authentication Filter Failed invalid password");
139 authInvalidPasswordError(requestContext, userName);
141 authSuccessful(requestContext, userName);
146 private void authSuccessful(ContainerRequestContext requestContext, String userName) {
147 ComponentsUtils componentUtils = getComponentsUtils();
148 if (componentUtils == null) {
149 abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
151 componentUtils.auditAuthEvent(requestContext.getUriInfo().getPath(), userName, AuthStatus.AUTH_SUCCESS.toString(), realm);
154 private void authInvalidPasswordError(ContainerRequestContext requestContext, String userName) {
155 ComponentsUtils componentUtils = getComponentsUtils();
156 if (componentUtils == null) {
157 abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
159 componentUtils.auditAuthEvent(requestContext.getUriInfo().getPath(), userName, AuthStatus.AUTH_FAILED_INVALID_PASSWORD.toString(), realm);
160 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_FAILED);
161 abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, false));
164 private void authUserNotFoundError(ContainerRequestContext requestContext, String userName) {
165 ComponentsUtils componentUtils = getComponentsUtils();
166 if (componentUtils == null) {
167 abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
169 getComponentsUtils().auditAuthEvent(requestContext.getUriInfo().getPath(), userName, AuthStatus.AUTH_FAILED_USER_NOT_FOUND.toString(), realm);
170 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_FAILED);
171 abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, false));
174 private void authInvalidHeaderError(ContainerRequestContext requestContext) {
175 ComponentsUtils componentUtils = getComponentsUtils();
176 if (componentUtils == null) {
177 abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
179 getComponentsUtils().auditAuthEvent(requestContext.getUriInfo().getPath(), "", AuthStatus.AUTH_FAILED_INVALID_AUTHENTICATION_HEADER.toString(), realm);
180 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_FAILED_INVALIDE_HEADER);
181 abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, false));
184 private void authRequiredError(ContainerRequestContext requestContext) {
185 ComponentsUtils componentUtils = getComponentsUtils();
186 if (componentUtils == null) {
187 abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
189 getComponentsUtils().auditAuthEvent(requestContext.getUriInfo().getPath(), "", AuthStatus.AUTH_REQUIRED.toString(), realm);
190 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_REQUIRED);
191 abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, true));
194 private ComponentsUtils getComponentsUtils() {
195 ServletContext context = sr.getSession().getServletContext();
196 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
197 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
198 return webApplicationContext.getBean(ComponentsUtils.class);
201 private ConsumerBusinessLogic getConsumerBusinessLogic() {
202 ServletContext context = sr.getSession().getServletContext();
203 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
204 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
205 return webApplicationContext.getBean(ConsumerBusinessLogic.class);
208 public enum AuthStatus {
209 AUTH_REQUIRED, AUTH_FAILED_USER_NOT_FOUND, AUTH_FAILED_INVALID_PASSWORD, AUTH_FAILED_INVALID_AUTHENTICATION_HEADER, AUTH_SUCCESS
212 protected Response buildErrorResponse(ResponseFormat requestErrorWrapper, boolean addWwwAuthenticationHeader) {
213 ResponseBuilder responseBuilder = Response.status(requestErrorWrapper.getStatus());
214 if (addWwwAuthenticationHeader) {
215 responseBuilder = responseBuilder.header("WWW-Authenticate", "Basic realm=\"" + realm + "\"");
217 return responseBuilder.entity(gson.toJson(requestErrorWrapper.getRequestError())).build();
220 private void abortWith(ContainerRequestContext requestContext, String message, Response response) {
222 audit.log(sr.getRemoteAddr(),
224 response.getStatusInfo(),
231 requestContext.abortWith(response);