/* * Copyright (c) 2016-2020 Michael Zhang <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package net.devh.boot.grpc.examples.security.server; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import net.devh.boot.grpc.server.security.authentication.BasicGrpcAuthenticationReader; import net.devh.boot.grpc.server.security.authentication.GrpcAuthenticationReader; /** * The security configuration. If you use spring security for web applications most of the stuff is already configured. * * @author Daniel Theuke ([email protected]) */ @Configuration // proxyTargetClass is required, if you use annotation driven security! // However, you will receive a warning that GrpcServerService#bindService() method is final. // You cannot avoid that warning (without massive amount of work), but it is safe to ignore it. // The #bindService() method uses a reference to 'this', which will be used to invoke the methods. // If the method is not final it will delegate to the original instance and thus it will bypass any security layer that // you intend to add, unless you re-implement the #bindService() method on the outermost layer (which Spring does not). @EnableGlobalMethodSecurity(securedEnabled = true, proxyTargetClass = true) public class SecurityConfiguration { private static final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class); @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(10); } @Bean // This could be your database lookup. There are some complete implementations in spring-security-web. UserDetailsService userDetailsService() { return username -> { log.debug("Searching user: {}", username); switch (username) { case "guest": { return new User(username, passwordEncoder().encode(username + "Password"), Collections.emptyList()); } case "user": { final List<SimpleGrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority("ROLE_GREET")); return new User(username, passwordEncoder().encode(username + "Password"), authorities); } default: { throw new UsernameNotFoundException("Could not find user!"); } } }; } @Bean // One of your authentication providers. // They ensure that the credentials are valid and populate the user's authorities. DaoAuthenticationProvider daoAuthenticationProvider() { final DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(userDetailsService()); provider.setPasswordEncoder(passwordEncoder()); return provider; } @Bean // Add the authentication providers to the manager. AuthenticationManager authenticationManager() { final List<AuthenticationProvider> providers = new ArrayList<>(); providers.add(daoAuthenticationProvider()); return new ProviderManager(providers); } @Bean // Configure which authentication types you support. GrpcAuthenticationReader authenticationReader() { return new BasicGrpcAuthenticationReader(); // final List<GrpcAuthenticationReader> readers = new ArrayList<>(); // readers.add(new BasicGrpcAuthenticationReader()); // readers.add(new SSLContextGrpcAuthenticationReader()); // return new CompositeGrpcAuthenticationReader(readers); } }