I'am using swagger version 2.2.2. If I go to the address, http://localhost:8080/swagger-ui.html
, I will directly get the swagger UI. Is there any way, a security layer can be added, like, user should be prompted to enter for user id and password before the swagger UI display?
It is possible, I did it with this security configuration (assuming you are using spring):
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf().disable();
final InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
final PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
manager.createUser(User.withUsername("user").password(encoder.encode("password")).roles("ACTUATOR", "ADMIN").build());
http.authorizeRequests().antMatchers("/swagger-ui**", "/v2/api-docs/**").hasRole("ACTUATOR").and().httpBasic()
.and().userDetailsService(manager);
}
}
Related
I have MasterSecurity config which is to manage login of masters. And
AdminSecurity config which manages admin login.
When I comment one out the other works. But when I try to use both then the master login shows
PostMapping not allowed
package Spring.LoginRegister.Config;
import Spring.LoginRegister.Entity.RolesConstant;
import Spring.LoginRegister.Repository.AdminRepository;
import Spring.LoginRegister.Service.CustomAdminDetailsService;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
#Configuration
#EnableWebSecurity
#AllArgsConstructor
#Order(1)
public class AdminSecurityConfig {
private final AdminRepository adminRepository;
#Bean
public UserDetailsService userDetailsService1(){
return new CustomAdminDetailsService(adminRepository);
}
#Bean
public BCryptPasswordEncoder passwordEncoder1(){
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider authenticationProvider1(){
DaoAuthenticationProvider authProvider= new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService1());
authProvider.setPasswordEncoder(passwordEncoder1());
return authProvider;
}
#Bean
public SecurityFilterChain AdminsecurityFilterChain(HttpSecurity http) throws Exception {
http
.authenticationProvider(authenticationProvider1());
http
.csrf().disable()
.authorizeHttpRequests((request) -> request
.requestMatchers("/AdminDashBoard/**").authenticated()
.requestMatchers("/admin/login").hasRole(RolesConstant.ROLE_ADMIN.toString() )
.anyRequest().permitAll()
)
.formLogin((form) ->form
.loginPage("/admin/login")
.defaultSuccessUrl("/AdminDashBoard", true)
.permitAll()
)
.logout(form -> form
.logoutUrl("/logout")
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutSuccessUrl("/")
);
return http.build();
}
}
My problem is they both work individually when one is removed from the app. When I try to combine both only the admin config works properly. This error comes
Method 'POST' is not supported.
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' is not supported
at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:265)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:441)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:382)
at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(RequestMappingInfoHandlerMapping.java:126)
at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(RequestMappingInfoHandlerMapping.java:68)
at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:504)
at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1274)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1056)
This is my second config:
package Spring.LoginRegister.Config;
import Spring.LoginRegister.Repository.MasterRepository;
import Spring.LoginRegister.Service.CustomAdminDetailsService;
import Spring.LoginRegister.Service.CustomMasterDetails;
import Spring.LoginRegister.Service.CustomMasterDetailsService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
#Configuration
#Order(2)
public class MASTERSecurityConfig {
private MasterRepository masterRepository;
#Bean
public UserDetailsService userDetailsService2(){
return new CustomMasterDetailsService(masterRepository);
}
#Bean
#Primary
public BCryptPasswordEncoder passwordEncoder2(){
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider authenticationProvider2(){
DaoAuthenticationProvider authProvider2= new DaoAuthenticationProvider();
authProvider2.setUserDetailsService(userDetailsService2());
authProvider2.setPasswordEncoder(passwordEncoder2());
return authProvider2;
}
#Bean
public SecurityFilterChain MastersecurityFilterChain(HttpSecurity http) throws Exception {
http
.authenticationProvider(authenticationProvider2());
http
.csrf().disable()
.authorizeHttpRequests((request) ->request
.requestMatchers("/master/home/**").authenticated()
.requestMatchers("/master/login")
.hasRole(RolesConstant.ROLE_HOUSEMASTER.toString())
.anyRequest().permitAll()
)
.formLogin((form) ->form
.loginPage("/master/login")
.defaultSuccessUrl("/master/home", true)
.permitAll())
.logout(form -> form
.logoutUrl("/logout")
.invalidateHttpSession(true)
.logoutSuccessUrl("/")
.permitAll()
);
return http.build();
}
}
I tried StackOverflow previous answers.
Do not make separate Config classes. Just make multiple security filter chains and order them accordingly. Also, you have to prevent creating Beans of relative components as beans are global and they will contradict with each other.
The only configurable parts of this Authenticator seem to be the URL and the Domain. I'm unable to figure out how I would pass on a username or a password or my own search filter.
I looked at the source code of this class but most of the methods seem to be operating on UsernamePasswordAuthenticationToken from which username and password are being extracted. I was unable to find the methods which are used to create this object.
Here's what I'm currently using for AD LDAP Authentication:
package com.test;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
ActiveDirectoryLdapAuthenticationProvider adProvider = new ActiveDirectoryLdapAuthenticationProvider("domain.org",
"ldap://activedirectory-url:389");
adProvider.setConvertSubErrorCodesToExceptions(true);
adProvider.setUseAuthenticationRequestCredentials(true);
auth.authenticationProvider(adProvider);
}
}
I am trying to build simple JSON rest API using spring boot, I have build the application it works fine, now I need to do the simple Basic authentication and I did this with Spring security. Please find the Code below, My pain point here is when I run the application, I ask for the login first time then I tried to reload the URL again it does not ask for user name password. How to make the URL session expired and ask to prompt for login again. Note : I am not using any UI, It just an API
Security Configuration Class
package com.erplogic.erp.topcon.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
#Configuration
public class SecurityConfiguration {
#Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((authz) -> authz.anyRequest().authenticated()
).sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.NEVER)
)
.httpBasic();
return http.build();
}
#Bean
InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.builder().username("user").password(encoder().encode("pass")).roles("USER").build();
return new InMemoryUserDetailsManager(user);
}
#Bean
PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
#Bean
SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
}
Controller Class
package com.erplogic.erp.topcon.controller;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.erplogic.erp.topcon.service.SapApiService;
import com.erplogic.poc.objects.Root;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.erplogic.maven.plclog.wsdl2java.StandardFaultMessage_Exception;
#RestController
public class OutboundController {
#Autowired
private SapApiService sapApiService;
#RequestMapping(path ="/outbound",produces = MediaType.APPLICATION_JSON_VALUE,method = RequestMethod.GET)
public Root getOutbound() throws KeyManagementException, NoSuchAlgorithmException, StandardFaultMessage_Exception, JsonProcessingException {
return ((SapApiService) sapApiService).processOutboudService();
}
#RequestMapping(value = "/outbound/{outboundId}",produces = MediaType.APPLICATION_JSON_VALUE,method = RequestMethod.GET)
public String getOutboundId(#PathVariable String outboundId) throws KeyManagementException, JsonProcessingException, NoSuchAlgorithmException, StandardFaultMessage_Exception {
return ((SapApiService) sapApiService).processOutboudServiceByID(outboundId);
}
}
In my college project i would like to get user informations from an AD Server such as the telephone number, the mail, the full name after an authentication.
So i use the default spring security login page and after the authentication, i get the dn and the permissions with an Authentication object. I would like to know how can i get the details of an ad user.
I would like to get his phone number to send a message with an API. This part is already working. I just need to extract the Ad user details to do it.
You will find my code below :
SecurityConfiguration.java :
package com.le_chatelet.le_chatelet_back.ldap;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Bean
public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider =
new ActiveDirectoryLdapAuthenticationProvider( "mydomain.com", "ldap://adserverip:389");
activeDirectoryLdapAuthenticationProvider.setConvertSubErrorCodesToExceptions(true);
activeDirectoryLdapAuthenticationProvider.setUseAuthenticationRequestCredentials(true);
return activeDirectoryLdapAuthenticationProvider;
}
#Override
protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception{
authenticationManagerBuilder
.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception{
httpSecurity
.authorizeRequests()
.anyRequest()
.fullyAuthenticated()
.and()
.formLogin();
}
}
LoginController.java :
package com.le_chatelet.le_chatelet_back.ldap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.stream.Collectors;
#RestController
public class LoginController {
#Autowired
private UserInterface userInterface;
Logger logger = LoggerFactory.getLogger(LoginController.class);
#GetMapping("/hello")
public String sayHello()
{
return "hello world";
}
#GetMapping("/user")
#ResponseBody
public Authentication getLoggedUserDetail(Authentication authentication) {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//get username
String username = authentication.getName();
logger.info("username : "+username);
// concat list of authorities to single string seperated by comma
String authorityString = authentication
.getAuthorities()
.stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(","));
String role = "role_A";
boolean isCurrentUserInRole = authentication
.getAuthorities()
.stream()
.anyMatch(role::equals);
return authentication;
}
}
If someone can show me code example it would be appreciated.
You can set the a UserDetailsContextMapper on your Provider which allows custom strategy to be used for creating the UserDetails that will be stored as the principal in the Authentication.
provider.setUserDetailsContextMapper(new PersonContextMapper());
Then you can use the #AuthenticationPrincipal annotation in your Controller to get the Person (or a custom class) instance.
#GetMapping("/phone-number")
public String phoneNumber(#AuthenticationPrincipal Person person) {
return "Phone number: " + person.getTelephoneNumber();
}
You can find a full LDAP sample application provided by the Spring Security team.
I'm learning Spring in Action。I have a trouble when I'm reading the Chapter 4.2.3.
package tacos.security;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
DataSource dataSource;
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.ldapAuthentication()
.userSearchBase("ou=people")
.userSearchFilter("(uid={0})")
.groupSearchBase("ou.groups")
.groupSearchFilter("member={0}")
.passwordCompare()
.passwordEncoder(new BCryptPasswordEncoder())
.passwordAttribute("passcode")
.contextSource()
.root("dc=tacocloud,dc=com");
}
}
Spring Tool Suite IDE tells me that The method contextSource() is undefined for the type LdapAuthenticationProviderConfigurer.PasswordCompareConfigurer. I'm sure that I didn't copy the code from book incorrectly. Where is error? How should I correct my code?
I solved this problem. adding ".and()" before ".contextSource()" can be effective.