All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.holonplatform.vaadin.flow.spring.internal.SecuredRouteServiceInitListener Maven / Gradle / Ivy

/*
 * Copyright 2016-2018 Axioma srl.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.holonplatform.vaadin.flow.spring.internal;

import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;

import com.holonplatform.core.internal.Logger;
import com.holonplatform.core.internal.utils.AnnotationUtils;
import com.holonplatform.vaadin.flow.i18n.LocalizationProvider;
import com.holonplatform.vaadin.flow.internal.VaadinLogger;
import com.holonplatform.vaadin.flow.navigator.exceptions.ForbiddenNavigationException;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterListener;
import com.vaadin.flow.server.ServiceInitEvent;
import com.vaadin.flow.server.VaadinServiceInitListener;

/**
 * A {@link VaadinServiceInitListener} to register a {@link BeforeEnterListener} to check Secured annotated
 * navigation targets authorization.
 *
 * @since 5.2.0
 */
public class SecuredRouteServiceInitListener implements VaadinServiceInitListener {

	private static final long serialVersionUID = 6581058594162355308L;

	private static final Logger LOGGER = VaadinLogger.create();

	/*
	 * (non-Javadoc)
	 * @see com.vaadin.flow.server.VaadinServiceInitListener#serviceInit(com.vaadin.flow.server.ServiceInitEvent)
	 */
	@Override
	public void serviceInit(ServiceInitEvent event) {
		event.getSource().addUIInitListener(e -> {
			e.getUI().addBeforeEnterListener(new SecuredRouteBeforeEnterListener());
			LOGGER.debug(() -> "Secured route before enter listener setted up");
		});
	}

	static class SecuredRouteBeforeEnterListener implements BeforeEnterListener {

		private static final long serialVersionUID = 1577627862173954401L;

		/*
		 * (non-Javadoc)
		 * @see com.vaadin.flow.router.internal.BeforeEnterHandler#beforeEnter(com.vaadin.flow.router.BeforeEnterEvent)
		 */
		@Override
		public void beforeEnter(BeforeEnterEvent event) {
			final Class navigationTarget = event.getNavigationTarget();
			if (navigationTarget != null) {
				String[] roles = AnnotationUtils.getAnnotation(navigationTarget, Secured.class)
						.map(s -> (s.value() != null) ? s.value() : new String[0]).orElse(null);
				if (roles != null) {
					if (!isAccessGranted(roles)) {
						// redirect to error
						event.rerouteToError(ForbiddenNavigationException.class,
								LocalizationProvider.localize(ForbiddenNavigationException.DEFAULT_MESSAGE,
										ForbiddenNavigationException.DEFAULT_MESSAGE_CODE));
					}
				}
			}
		}

		/**
		 * Checks if the current user is granted any explicitly provided security attributes.
		 * @param securityConfigAttributes list of security configuration attributes (e.g. ROLE_USER, ROLE_ADMIN).
		 * @return true if the access is granted or the view is not secured, false otherwise
		 */
		private static boolean isAccessGranted(String[] securityConfigAttributes) {
			SecurityContext context = SecurityContextHolder.getContext();
			Authentication authentication = context.getAuthentication();
			if (authentication == null) {
				return false;
			}
			Set authorities = authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority)
					.collect(Collectors.toSet());
			return Stream.of(securityConfigAttributes).anyMatch(authorities::contains);
		}

	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy