Show AC app data visualization in new metrics tab
[portal/ric-dashboard.git] / webapp-backend / src / main / java / org / oransc / ric / portal / dashboard / portalapi / PortalAuthenticationFilter.java
1 /*-
2  * ========================LICENSE_START=================================
3  * O-RAN-SC
4  * %%
5  * Copyright (C) 2019 AT&T Intellectual Property and Nokia
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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===================================
19  */
20 package org.oransc.ric.portal.dashboard.portalapi;
21
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;
27
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;
37
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;
49
50 /**
51  * This filter checks every request for the cookie set by the ONAP Portal single
52  * sign on process. The possible paths and actions:
53  * <OL>
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
60  * session.
61  * </OL>
62  * <P>
63  * Notes:
64  * <UL>
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.
68  * </UL>
69  * 
70  * TODO: What about sessions? Will this be stateless?
71  * 
72  * This filter uses no annotations to avoid Spring's automatic registration,
73  * which add this filter in the chain in the wrong order.
74  */
75 public class PortalAuthenticationFilter implements Filter {
76
77         private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
78
79         public static final String REDIRECT_URL_KEY = "redirectUrl";
80
81         private final PortalAuthManager authManager;
82
83         private final DashboardUserManager userManager;
84
85         public PortalAuthenticationFilter(PortalAuthManager authManager, DashboardUserManager userManager) {
86                 this.authManager = authManager;
87                 this.userManager = userManager;
88         }
89
90         @Override
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);
95                 if (url == null)
96                         logger.error(
97                                         "init: Failed to find property in portal.properties: " + PortalApiConstants.ECOMP_REDIRECT_URL);
98         }
99
100         @Override
101         public void destroy() {
102                 // No resources to release
103         }
104
105         /*
106          * Populates security context with a mock user in the admin role.
107          * 
108          * TODO: AUTH
109          */
110         @Override
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();
117                         admin.setId(1L);
118                         admin.setName(DashboardConstants.ROLE_ADMIN);
119                         HashSet<EcompRole> roles = new HashSet<>();
120                         roles.add(admin);
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);
129                 } else {
130                         logger.debug("doFilter: authorities {}", auth.getAuthorities());
131                 }
132                 chain.doFilter(req, res);
133         }
134
135         /*
136          * Checks for valid cookies and allows request to be served if found; redirects
137          * to Portal otherwise. Requests for pages ignored in the web security config do
138          * not hit this filter.
139          * 
140          * TODO: AUTH
141          */
142         public void doFilter_EPSDKFW(ServletRequest req, ServletResponse res, FilterChain chain)
143                         throws IOException, ServletException {
144                 logger.debug("doFilter {}", req);
145                 HttpServletRequest request = (HttpServletRequest) req;
146                 HttpServletResponse response = (HttpServletResponse) res;
147                 // Need to authenticate the request
148                 final String userId = authManager.valdiateEcompSso(request);
149                 final EcompUser ecompUser = (userId == null ? null : userManager.getUser(userId));
150                 if (userId == null || ecompUser == null) {
151                         String redirectURL = buildLoginPageUrl(request);
152                         logger.trace("doFilter: unauthorized, redirecting to {}", redirectURL);
153                         response.sendRedirect(redirectURL);
154                 } else {
155                         EcompUserDetails userDetails = new EcompUserDetails(ecompUser);
156                         // Using portal session as credentials is a hack
157                         PreAuthenticatedAuthenticationToken authToken = new PreAuthenticatedAuthenticationToken(userDetails,
158                                         getPortalSessionId(request), userDetails.getAuthorities());
159                         SecurityContextHolder.getContext().setAuthentication(authToken);
160                         // Pass request back down the filter chain
161                         chain.doFilter(request, response);
162                 }
163         }
164
165         private String buildLoginPageUrl(HttpServletRequest request) {
166                 logger.trace("buildLoginPageUrl");
167                 // Why so much work to recover the original request?
168                 final StringBuffer sb = request.getRequestURL();
169                 sb.append(request.getQueryString() == null ? "" : "?" + request.getQueryString());
170                 final String requestedUrl = sb.toString();
171                 String encodedUrl = null;
172                 try {
173                         encodedUrl = URLEncoder.encode(requestedUrl, "UTF-8");
174                 } catch (UnsupportedEncodingException ex) {
175                         logger.error("buildLoginPageUrl: Failed to encode {}", requestedUrl);
176                 }
177                 return DashboardConstants.LOGIN_PAGE + "?" + REDIRECT_URL_KEY + "=" + encodedUrl;
178         }
179
180         /**
181          * Searches the request for a cookie with the specified name.
182          *
183          * @param request
184          *                       HttpServletRequest
185          * @param cookieName
186          *                       Cookie name
187          * @return Cookie, or null if not found.
188          */
189         private Cookie getCookie(HttpServletRequest request, String cookieName) {
190                 Cookie[] cookies = request.getCookies();
191                 if (cookies != null)
192                         for (Cookie cookie : cookies)
193                                 if (cookie.getName().equals(cookieName))
194                                         return cookie;
195                 return null;
196         }
197
198         /**
199          * Gets the ECOMP Portal service cookie value.
200          * 
201          * @param request
202          * @return Cookie value, or null if not found.
203          */
204         private String getPortalSessionId(HttpServletRequest request) {
205                 Cookie ep = getCookie(request, PortalApiConstants.EP_SERVICE);
206                 if (ep == null)
207                         return null;
208                 return ep.getValue();
209         }
210
211 }