X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=webapp-backend%2Fsrc%2Fmain%2Fjava%2Forg%2Foransc%2Fric%2Fportal%2Fdashboard%2Fportalapi%2FPortalAuthenticationFilter.java;h=50f5b8942c80c3cff3bd101ad33e7972ebd7da6f;hb=9fef9615bd5889eacbe8ddad454b7ff4b4c195c0;hp=d69d816a8dcd1f52163905325e18957a1aeb97c9;hpb=6b79976523018d41b3643b15deeb6706ad4daa6e;p=portal%2Fric-dashboard.git diff --git a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/portalapi/PortalAuthenticationFilter.java b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/portalapi/PortalAuthenticationFilter.java index d69d816a..50f5b894 100644 --- a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/portalapi/PortalAuthenticationFilter.java +++ b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/portalapi/PortalAuthenticationFilter.java @@ -20,6 +20,7 @@ package org.oransc.ric.portal.dashboard.portalapi; import java.io.IOException; +import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.lang.invoke.MethodHandles; import java.net.URLEncoder; @@ -43,6 +44,7 @@ import org.oransc.ric.portal.dashboard.DashboardConstants; import org.oransc.ric.portal.dashboard.model.EcompUserDetails; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; @@ -76,15 +78,39 @@ public class PortalAuthenticationFilter implements Filter { private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + // Unfortunately these names are not available as constants + private static final String[] securityPropertyFiles = { "ESAPI.properties", "key.properties", "portal.properties", + "validation.properties" }; + public static final String REDIRECT_URL_KEY = "redirectUrl"; + private final boolean enforcePortalSecurity; private final PortalAuthManager authManager; private final DashboardUserManager userManager; - public PortalAuthenticationFilter(PortalAuthManager authManager, DashboardUserManager userManager) { + public PortalAuthenticationFilter(boolean portalSecurity, PortalAuthManager authManager, + DashboardUserManager userManager) { + this.enforcePortalSecurity = portalSecurity; this.authManager = authManager; this.userManager = userManager; + if (portalSecurity) { + // Throw if security is requested and prerequisites are not met + for (String pf : securityPropertyFiles) { + InputStream in = MethodHandles.lookup().lookupClass().getClassLoader().getResourceAsStream(pf); + if (in == null) { + String msg = "Failed to find property file on classpath: " + pf; + logger.error(msg); + throw new RuntimeException(msg); + } else { + try { + in.close(); + } catch (IOException ex) { + logger.warn("Failed to close stream", ex); + } + } + } + } } @Override @@ -102,17 +128,30 @@ public class PortalAuthenticationFilter implements Filter { // No resources to release } + /** + * Requests for pages ignored in the web security config do not hit this filter. + */ + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) + throws IOException, ServletException { + if (enforcePortalSecurity) + doFilterEPSDKFW(req, res, chain); + else + doFilterMockUserAdminRole(req, res, chain); + } + /* * Populates security context with a mock user in the admin role. * - * TODO: AUTH */ - @Override - public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) + private void doFilterMockUserAdminRole(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth == null || auth.getAuthorities().isEmpty()) { - logger.debug("doFilter adding auth to request {}", req); + if (logger.isDebugEnabled()) { + logger.debug("doFilter adding auth to request URI {}", + (req instanceof HttpServletRequest) ? ((HttpServletRequest) req).getRequestURL() : req); + } EcompRole admin = new EcompRole(); admin.setId(1L); admin.setName(DashboardConstants.ROLE_ADMIN); @@ -134,23 +173,25 @@ public class PortalAuthenticationFilter implements Filter { /* * Checks for valid cookies and allows request to be served if found; redirects - * to Portal otherwise. Requests for pages ignored in the web security config do - * not hit this filter. - * - * TODO: AUTH + * to Portal otherwise. */ - public void doFilter_EPSDKFW(ServletRequest req, ServletResponse res, FilterChain chain) + private void doFilterEPSDKFW(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { - logger.debug("doFilter {}", req); HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; + if (logger.isTraceEnabled()) + logger.trace("doFilter: req {}", request.getRequestURI()); // Need to authenticate the request final String userId = authManager.valdiateEcompSso(request); final EcompUser ecompUser = (userId == null ? null : userManager.getUser(userId)); if (userId == null || ecompUser == null) { - String redirectURL = buildLoginPageUrl(request); - logger.trace("doFilter: unauthorized, redirecting to {}", redirectURL); - response.sendRedirect(redirectURL); + logger.debug("doFilter: unauthorized user requests URI {}, serving login page", request.getRequestURI()); + StringBuffer sb = request.getRequestURL(); + sb.append(request.getQueryString() == null ? "" : "?" + request.getQueryString()); + String body = generateLoginRedirectPage(sb.toString()); + response.setContentType(MediaType.TEXT_HTML_VALUE); + response.getWriter().print(body); + response.getWriter().flush(); } else { EcompUserDetails userDetails = new EcompUserDetails(ecompUser); // Using portal session as credentials is a hack @@ -162,19 +203,44 @@ public class PortalAuthenticationFilter implements Filter { } } - private String buildLoginPageUrl(HttpServletRequest request) { - logger.trace("buildLoginPageUrl"); - // Why so much work to recover the original request? - final StringBuffer sb = request.getRequestURL(); - sb.append(request.getQueryString() == null ? "" : "?" + request.getQueryString()); - final String requestedUrl = sb.toString(); - String encodedUrl = null; - try { - encodedUrl = URLEncoder.encode(requestedUrl, "UTF-8"); - } catch (UnsupportedEncodingException ex) { - logger.error("buildLoginPageUrl: Failed to encode {}", requestedUrl); - } - return DashboardConstants.LOGIN_PAGE + "?" + REDIRECT_URL_KEY + "=" + encodedUrl; + /** + * Generates a page with text only, absolutely no references to any webapp + * resources, so this can be served to an unauthenticated user without + * triggering a new authentication attempt. The page has a link to the Portal + * URL from configuration, with a return URL that is the original request. + * + * @param appUrl + * Original requested URL + * @return HTML + * @throws UnsupportedEncodingException + * On error + */ + private static String generateLoginRedirectPage(String appUrl) throws UnsupportedEncodingException { + String encodedAppUrl = URLEncoder.encode(appUrl, "UTF-8"); + String portalBaseUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL); + String redirectUrl = portalBaseUrl + "?" + PortalAuthenticationFilter.REDIRECT_URL_KEY + "=" + encodedAppUrl; + String aHref = ""; + // If only Java had "here" documents. + String body = String.join(// + System.getProperty("line.separator"), // + "", // + "", // + "RIC Dashboard", // + "", // + "", // + "", // + "

RIC Dashboard

", // + "

Please log in.

", // + "

", // + aHref, "Click here to authenticate at the ONAP Portal", // + "

", // + "", // + ""); + return body; } /**