2ec5938d8e9317c8f160b094931bbab9dd3468a0
[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
27 import javax.servlet.Filter;
28 import javax.servlet.FilterChain;
29 import javax.servlet.FilterConfig;
30 import javax.servlet.ServletException;
31 import javax.servlet.ServletRequest;
32 import javax.servlet.ServletResponse;
33 import javax.servlet.http.Cookie;
34 import javax.servlet.http.HttpServletRequest;
35 import javax.servlet.http.HttpServletResponse;
36
37 import org.onap.portalsdk.core.onboarding.util.PortalApiConstants;
38 import org.onap.portalsdk.core.onboarding.util.PortalApiProperties;
39 import org.onap.portalsdk.core.restful.domain.EcompUser;
40 import org.oransc.ric.portal.dashboard.DashboardConstants;
41 import org.oransc.ric.portal.dashboard.model.EcompUserDetails;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.springframework.security.core.context.SecurityContextHolder;
45 import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
46
47 /**
48  * This filter checks every request for the cookie set by the ONAP Portal single
49  * sign on process. The possible paths and actions:
50  * <OL>
51  * <LI>User starts at an app page via a bookmark. No Portal cookie is set.
52  * Redirect there to get one; then continue as below.
53  * <LI>User starts at Portal and goes to app. Alternately, the user's session
54  * times out and the user hits refresh. The Portal cookie is set, but there is
55  * no valid session. Create one and publish info.
56  * <LI>User has valid Portal cookie and session. Reset the max idle in that
57  * session.
58  * </OL>
59  * <P>
60  * Notes:
61  * <UL>
62  * <LI>While redirecting, the cookie "redirectUrl" should also be set so that
63  * Portal knows where to forward the request to once the Portal Session is
64  * created and EPService cookie is set.
65  * </UL>
66  * 
67  * TODO: What about sessions? Will this be stateless?
68  * 
69  * This filter uses no annotations to avoid Spring's automatic registration,
70  * which add this filter in the chain in the wrong order.
71  */
72 public class PortalAuthenticationFilter implements Filter {
73
74         private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
75
76         public static final String REDIRECT_URL_KEY = "redirectUrl";
77
78         private final PortalAuthManager authManager;
79
80         private final DashboardUserManager userManager;
81
82         public PortalAuthenticationFilter(PortalAuthManager authManager, DashboardUserManager userManager) {
83                 this.authManager = authManager;
84                 this.userManager = userManager;
85         }
86
87         @Override
88         public void init(FilterConfig filterConfig) throws ServletException {
89                 // complain loudly if this key property is missing
90                 String url = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
91                 logger.debug("init: Portal redirect URL {}", url);
92                 if (url == null)
93                         logger.error(
94                                         "init: Failed to find property in portal.properties: " + PortalApiConstants.ECOMP_REDIRECT_URL);
95         }
96
97         @Override
98         public void destroy() {
99                 // No resources to release
100         }
101
102         /**
103          * Checks for valid cookies and allows request to be served if found; redirects
104          * to Portal otherwise. Requests for pages ignored in the web security config do
105          * not hit this filter.
106          */
107         @Override
108         public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
109                         throws IOException, ServletException {
110                 logger.debug("doFilter {}", req);
111                 HttpServletRequest request = (HttpServletRequest) req;
112                 HttpServletResponse response = (HttpServletResponse) res;
113                 // Need to authenticate the request
114                 final String userId = authManager.valdiateEcompSso(request);
115                 final EcompUser ecompUser = (userId == null ? null : userManager.getUser(userId));
116                 if (userId == null || ecompUser == null) {
117                         String redirectURL = buildLoginPageUrl(request);
118                         logger.trace("doFilter: unauthorized, redirecting to {}", redirectURL);
119                         response.sendRedirect(redirectURL);
120                 } else {
121                         EcompUserDetails userDetails = new EcompUserDetails(ecompUser);
122                         // Using portal session as credentials is a hack
123                         PreAuthenticatedAuthenticationToken authToken = new PreAuthenticatedAuthenticationToken(userDetails,
124                                         getPortalSessionId(request), userDetails.getAuthorities());
125                         SecurityContextHolder.getContext().setAuthentication(authToken);
126                         // Pass request back down the filter chain
127                         chain.doFilter(request, response);
128                 }
129         }
130
131         private String buildLoginPageUrl(HttpServletRequest request) {
132                 logger.trace("buildLoginPageUrl");
133                 // Why so much work to recover the original request?
134                 final StringBuffer sb = request.getRequestURL();
135                 sb.append(request.getQueryString() == null ? "" : "?" + request.getQueryString());
136                 final String requestedUrl = sb.toString();
137                 String encodedUrl = null;
138                 try {
139                         encodedUrl = URLEncoder.encode(requestedUrl, "UTF-8");
140                 } catch (UnsupportedEncodingException ex) {
141                         logger.error("buildLoginPageUrl: Failed to encode {}", requestedUrl);
142                 }
143                 return DashboardConstants.LOGIN_PAGE + "?" + REDIRECT_URL_KEY + "=" + encodedUrl;
144         }
145
146         /**
147          * Searches the request for a cookie with the specified name.
148          *
149          * @param request
150          *                       HttpServletRequest
151          * @param cookieName
152          *                       Cookie name
153          * @return Cookie, or null if not found.
154          */
155         private Cookie getCookie(HttpServletRequest request, String cookieName) {
156                 Cookie[] cookies = request.getCookies();
157                 if (cookies != null)
158                         for (Cookie cookie : cookies)
159                                 if (cookie.getName().equals(cookieName))
160                                         return cookie;
161                 return null;
162         }
163
164         /**
165          * Gets the ECOMP Portal service cookie value.
166          * 
167          * @param request
168          * @return Cookie value, or null if not found.
169          */
170         private String getPortalSessionId(HttpServletRequest request) {
171                 Cookie ep = getCookie(request, PortalApiConstants.EP_SERVICE);
172                 if (ep == null)
173                         return null;
174                 return ep.getValue();
175         }
176
177 }