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.onap.sdc.security.Passwords;
28 import org.openecomp.sdc.be.components.impl.ConsumerBusinessLogic;
29 import org.openecomp.sdc.be.dao.api.ActionStatus;
30 import org.openecomp.sdc.be.impl.ComponentsUtils;
31 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
32 import org.openecomp.sdc.be.model.ConsumerDefinition;
33 import org.openecomp.sdc.common.api.Constants;
34 import org.openecomp.sdc.common.log.enums.LogLevel;
35 import org.openecomp.sdc.common.log.enums.Severity;
36 import org.openecomp.sdc.common.log.wrappers.Logger;
37 import org.openecomp.sdc.common.log.wrappers.LoggerSdcAudit;
38 import org.openecomp.sdc.exception.ResponseFormat;
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 {
58 private static LoggerSdcAudit audit = new LoggerSdcAudit(BasicAuthenticationFilter.class);
59 private static final Logger log = Logger.getLogger(BasicAuthenticationFilter.class);
60 private static final String COMPONENT_UTILS_FAILED = "Authentication Filter Failed to get component utils.";
61 private static final String CONSUMER_BL_FAILED = "Authentication Filter Failed to get consumerBL.";
64 private HttpServletRequest sr;
66 protected Gson gson = new GsonBuilder().setPrettyPrinting().create();
68 private String realm = "ASDC";
72 public void filter(ContainerRequestContext requestContext) throws IOException {
74 audit.startLog(requestContext);
76 String authHeader = requestContext.getHeaderString(Constants.AUTHORIZATION_HEADER);
77 if (authHeader != null) {
78 StringTokenizer st = new StringTokenizer(authHeader);
79 String failedToRetrieveAuthErrorMsg = "Authentication Filter Failed Couldn't retrieve authentication, no basic authentication.";
80 if (st.hasMoreTokens()) {
81 String basic = st.nextToken();
83 if ("Basic".equalsIgnoreCase(basic)) {
85 String credentials = new String(Base64.decodeBase64(st.nextToken()), "UTF-8");
86 log.debug("Credentials: {}", credentials);
87 checkUserCredentials(requestContext, credentials);
88 } catch (UnsupportedEncodingException e) {
89 log.error("Authentication Filter Failed Couldn't retrieve authentication", e);
90 authInvalidHeaderError(requestContext);
93 log.error(failedToRetrieveAuthErrorMsg);
94 authInvalidHeaderError(requestContext);
97 log.error(failedToRetrieveAuthErrorMsg);
98 authInvalidHeaderError(requestContext);
102 log.error("Authentication Filter Failed no authorization header");
103 authRequiredError(requestContext);
107 private void checkUserCredentials(ContainerRequestContext requestContext, String credentials) {
108 int p = credentials.indexOf(':');
110 String userName = credentials.substring(0, p).trim();
111 String password = credentials.substring(p + 1).trim();
113 ConsumerBusinessLogic consumerBL = getConsumerBusinessLogic();
114 if (consumerBL == null) {
115 abortWith(requestContext, CONSUMER_BL_FAILED, Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build());
117 Either<ConsumerDefinition, ResponseFormat> result = consumerBL.getConsumer(userName);
118 validatePassword(requestContext, userName, password, result);
121 log.error("Authentication Filter Failed Couldn't retrieve authentication, no basic authentication.");
122 authInvalidHeaderError(requestContext);
127 private void validatePassword(ContainerRequestContext requestContext, String userName, String password, Either<ConsumerDefinition, ResponseFormat> result) {
128 if (result.isRight()) {
129 Integer status = result.right().value().getStatus();
130 if (status == Status.NOT_FOUND.getStatusCode()) {
131 log.error("Authentication Filter Failed Couldn't find user");
132 authUserNotFoundError(requestContext, userName);
134 abortWith(requestContext, CONSUMER_BL_FAILED, Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build());
137 ConsumerDefinition consumerCredentials = result.left().value();
138 if (!Passwords.isExpectedPassword(password, consumerCredentials.getConsumerSalt(), consumerCredentials.getConsumerPassword())) {
139 log.error("Authentication Filter Failed invalid password");
140 authInvalidPasswordError(requestContext, userName);
142 authSuccessful(requestContext, userName);
147 private void authSuccessful(ContainerRequestContext requestContext, String userName) {
148 ComponentsUtils componentUtils = getComponentsUtils();
149 if (componentUtils == null) {
150 abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
152 componentUtils.auditAuthEvent(requestContext.getUriInfo().getPath(), userName, AuthStatus.AUTH_SUCCESS.toString(), realm);
155 private void authInvalidPasswordError(ContainerRequestContext requestContext, String userName) {
156 ComponentsUtils componentUtils = getComponentsUtils();
157 if (componentUtils == null) {
158 abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
160 componentUtils.auditAuthEvent(requestContext.getUriInfo().getPath(), userName, AuthStatus.AUTH_FAILED_INVALID_PASSWORD.toString(), realm);
161 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_FAILED);
162 abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, false));
165 private void authUserNotFoundError(ContainerRequestContext requestContext, String userName) {
166 ComponentsUtils componentUtils = getComponentsUtils();
167 if (componentUtils == null) {
168 abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
170 getComponentsUtils().auditAuthEvent(requestContext.getUriInfo().getPath(), userName, AuthStatus.AUTH_FAILED_USER_NOT_FOUND.toString(), realm);
171 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_FAILED);
172 abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, false));
175 private void authInvalidHeaderError(ContainerRequestContext requestContext) {
176 ComponentsUtils componentUtils = getComponentsUtils();
177 if (componentUtils == null) {
178 abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
180 getComponentsUtils().auditAuthEvent(requestContext.getUriInfo().getPath(), "", AuthStatus.AUTH_FAILED_INVALID_AUTHENTICATION_HEADER.toString(), realm);
181 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_FAILED_INVALIDE_HEADER);
182 abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, false));
185 private void authRequiredError(ContainerRequestContext requestContext) {
186 ComponentsUtils componentUtils = getComponentsUtils();
187 if (componentUtils == null) {
188 abortWith(requestContext, COMPONENT_UTILS_FAILED, Response.status(Status.INTERNAL_SERVER_ERROR).build());
190 getComponentsUtils().auditAuthEvent(requestContext.getUriInfo().getPath(), "", AuthStatus.AUTH_REQUIRED.toString(), realm);
191 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_REQUIRED);
192 abortWith(requestContext, responseFormat.getFormattedMessage(), buildErrorResponse(responseFormat, true));
195 private ComponentsUtils getComponentsUtils() {
196 ServletContext context = sr.getSession().getServletContext();
197 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
198 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
199 return webApplicationContext.getBean(ComponentsUtils.class);
202 private ConsumerBusinessLogic getConsumerBusinessLogic() {
203 ServletContext context = sr.getSession().getServletContext();
204 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
205 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
206 return webApplicationContext.getBean(ConsumerBusinessLogic.class);
209 public enum AuthStatus {
210 AUTH_REQUIRED, AUTH_FAILED_USER_NOT_FOUND, AUTH_FAILED_INVALID_PASSWORD, AUTH_FAILED_INVALID_AUTHENTICATION_HEADER, AUTH_SUCCESS
213 protected Response buildErrorResponse(ResponseFormat requestErrorWrapper, boolean addWwwAuthenticationHeader) {
214 ResponseBuilder responseBuilder = Response.status(requestErrorWrapper.getStatus());
215 if (addWwwAuthenticationHeader) {
216 responseBuilder = responseBuilder.header("WWW-Authenticate", "Basic realm=\"" + realm + "\"");
218 return responseBuilder.entity(gson.toJson(requestErrorWrapper.getRequestError())).build();
221 private void abortWith(ContainerRequestContext requestContext, String message, Response response) {
223 audit.logEntry(sr.getRemoteAddr(),
225 // response.getStatusInfo(),
232 requestContext.abortWith(response);