2 * ========================LICENSE_START=================================
5 * Copyright (C) 2019 AT&T Intellectual Property and Nokia
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===================================
20 package org.oransc.ric.portal.dashboard.portalapi;
22 import java.io.IOException;
23 import java.io.UnsupportedEncodingException;
24 import java.lang.invoke.MethodHandles;
25 import java.net.URLEncoder;
26 import java.util.HashSet;
28 import javax.servlet.Filter;
29 import javax.servlet.FilterChain;
30 import javax.servlet.FilterConfig;
31 import javax.servlet.ServletException;
32 import javax.servlet.ServletRequest;
33 import javax.servlet.ServletResponse;
34 import javax.servlet.http.Cookie;
35 import javax.servlet.http.HttpServletRequest;
36 import javax.servlet.http.HttpServletResponse;
38 import org.onap.portalsdk.core.onboarding.util.PortalApiConstants;
39 import org.onap.portalsdk.core.onboarding.util.PortalApiProperties;
40 import org.onap.portalsdk.core.restful.domain.EcompRole;
41 import org.onap.portalsdk.core.restful.domain.EcompUser;
42 import org.oransc.ric.portal.dashboard.DashboardConstants;
43 import org.oransc.ric.portal.dashboard.model.EcompUserDetails;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46 import org.springframework.security.core.Authentication;
47 import org.springframework.security.core.context.SecurityContextHolder;
48 import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
51 * This filter checks every request for the cookie set by the ONAP Portal single
52 * sign on process. The possible paths and actions:
54 * <LI>User starts at an app page via a bookmark. No Portal cookie is set.
55 * Redirect there to get one; then continue as below.
56 * <LI>User starts at Portal and goes to app. Alternately, the user's session
57 * times out and the user hits refresh. The Portal cookie is set, but there is
58 * no valid session. Create one and publish info.
59 * <LI>User has valid Portal cookie and session. Reset the max idle in that
65 * <LI>While redirecting, the cookie "redirectUrl" should also be set so that
66 * Portal knows where to forward the request to once the Portal Session is
67 * created and EPService cookie is set.
70 * TODO: What about sessions? Will this be stateless?
72 * This filter uses no annotations to avoid Spring's automatic registration,
73 * which add this filter in the chain in the wrong order.
75 public class PortalAuthenticationFilter implements Filter {
77 private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
79 public static final String REDIRECT_URL_KEY = "redirectUrl";
81 private final PortalAuthManager authManager;
83 private final DashboardUserManager userManager;
85 public PortalAuthenticationFilter(PortalAuthManager authManager, DashboardUserManager userManager) {
86 this.authManager = authManager;
87 this.userManager = userManager;
91 public void init(FilterConfig filterConfig) throws ServletException {
92 // complain loudly if this key property is missing
93 String url = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
94 logger.debug("init: Portal redirect URL {}", url);
97 "init: Failed to find property in portal.properties: " + PortalApiConstants.ECOMP_REDIRECT_URL);
101 public void destroy() {
102 // No resources to release
106 * Populates security context with a mock user in the admin role.
111 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
112 throws IOException, ServletException {
113 Authentication auth = SecurityContextHolder.getContext().getAuthentication();
114 if (auth == null || auth.getAuthorities().isEmpty()) {
115 logger.debug("doFilter adding auth to request {}", req);
116 EcompRole admin = new EcompRole();
118 admin.setName(DashboardConstants.ROLE_ADMIN);
119 HashSet<EcompRole> roles = new HashSet<>();
121 EcompUser user = new EcompUser();
122 user.setLoginId("fakeLoginId");
123 user.setRoles(roles);
124 user.setActive(true);
125 EcompUserDetails userDetails = new EcompUserDetails(user);
126 PreAuthenticatedAuthenticationToken authToken = new PreAuthenticatedAuthenticationToken(userDetails,
127 "fakeCredentials", userDetails.getAuthorities());
128 SecurityContextHolder.getContext().setAuthentication(authToken);
131 logger.debug("doFilter: authorities {}", auth.getAuthorities());
133 chain.doFilter(req, res);
137 * Checks for valid cookies and allows request to be served if found; redirects
138 * to Portal otherwise. Requests for pages ignored in the web security config do
139 * not hit this filter.
143 public void doFilter_EPSDKFW(ServletRequest req, ServletResponse res, FilterChain chain)
144 throws IOException, ServletException {
145 logger.debug("doFilter {}", req);
146 HttpServletRequest request = (HttpServletRequest) req;
147 HttpServletResponse response = (HttpServletResponse) res;
148 // Need to authenticate the request
149 final String userId = authManager.valdiateEcompSso(request);
150 final EcompUser ecompUser = (userId == null ? null : userManager.getUser(userId));
151 if (userId == null || ecompUser == null) {
152 String redirectURL = buildLoginPageUrl(request);
153 logger.trace("doFilter: unauthorized, redirecting to {}", redirectURL);
154 response.sendRedirect(redirectURL);
156 EcompUserDetails userDetails = new EcompUserDetails(ecompUser);
157 // Using portal session as credentials is a hack
158 PreAuthenticatedAuthenticationToken authToken = new PreAuthenticatedAuthenticationToken(userDetails,
159 getPortalSessionId(request), userDetails.getAuthorities());
160 SecurityContextHolder.getContext().setAuthentication(authToken);
161 // Pass request back down the filter chain
162 chain.doFilter(request, response);
166 private String buildLoginPageUrl(HttpServletRequest request) {
167 logger.trace("buildLoginPageUrl");
168 // Why so much work to recover the original request?
169 final StringBuffer sb = request.getRequestURL();
170 sb.append(request.getQueryString() == null ? "" : "?" + request.getQueryString());
171 final String requestedUrl = sb.toString();
172 String encodedUrl = null;
174 encodedUrl = URLEncoder.encode(requestedUrl, "UTF-8");
175 } catch (UnsupportedEncodingException ex) {
176 logger.error("buildLoginPageUrl: Failed to encode {}", requestedUrl);
178 return DashboardConstants.LOGIN_PAGE + "?" + REDIRECT_URL_KEY + "=" + encodedUrl;
182 * Searches the request for a cookie with the specified name.
188 * @return Cookie, or null if not found.
190 private Cookie getCookie(HttpServletRequest request, String cookieName) {
191 Cookie[] cookies = request.getCookies();
193 for (Cookie cookie : cookies)
194 if (cookie.getName().equals(cookieName))
200 * Gets the ECOMP Portal service cookie value.
203 * @return Cookie value, or null if not found.
205 private String getPortalSessionId(HttpServletRequest request) {
206 Cookie ep = getCookie(request, PortalApiConstants.EP_SERVICE);
209 return ep.getValue();