I use Oauth and want to create user but have error
POST http://localhost:4200/proxy/user/createUser 401 (Unauthorized)
In spring i have some configuration
#Configuration
#EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/createUser", "/user/**", "/user/createUser", "proxy/user/createUser").permitAll();
http.csrf().disable();
http.formLogin().disable();
http.authorizeRequests().anyRequest().authenticated();
}
}
and
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/createUser", "/register", "/token", "/token/createUser", "proxy/user/createUser").permitAll();
http.requestMatchers()
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
}
What configuration changes are required to enable access to ../createUser?
looks like http.authorizeRequests().anyRequest().authenticated() this is creating problem in code. just change in WebSecurity as
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests().antMatchers("/createUser", "/user/**", "/user/createUser", "proxy/user/createUser")
.permitAll()
.formLogin().disable();
}}`
AND
change in ResourceServerConfig as
http.authorizeRequests()
.antMatchers("/createUser", "/register", "/token", "/token/createUser",
"proxy/user/createUser")
.permitAll();
for details checkout Security-config.
Related
I have the below configuration where i need to configure HTTPBasic authentication for /api/v1/** endpoints and i want to configure form authentication for /users/ url pattern. When i run with the below configuration, the configuration for web requests is working correctly but the configuration for API is not working. No security is being applied. Where am I going wrong?
#Configuration
#EnableWebSecurity
public class WebSecurityConfig {
#Order(1)
#Configuration
public static class MVCSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Bean
public BCryptPasswordEncoder getBCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.
antMatcher("/users/**")
.csrf()
.and()
.authorizeRequests()
.antMatchers(
"/resources/**", "/users/register", "/users/signup", "/users/confirm", "/users/user-action", "/users/reset-password", "/confirm", "/webjars/**")
.permitAll()
.antMatchers("/users/**")
.hasRole("USER")
.anyRequest()
.authenticated()
.and()
.formLogin().loginPage("/login").usernameParameter("username").passwordParameter("password");
http
.authorizeRequests()
.antMatchers("/api/v1/users/**")
.hasRole("USER")
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
}
I have put your code to work with this configuration bellow:
#EnableWebSecurity
public class SecurityConfiguration {
public class ApiSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/api/v1/users/**")
.authorizeRequests().anyRequest()
.hasRole("USER").and().httpBasic();
}
}
#Configuration
#Order(2)
public class MVCSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().and().authorizeRequests()
.antMatchers("/resources/**", "/users/register", "/users/signup", "/users/confirm",
"/users/user-action", "/users/reset-password", "/confirm", "/webjars/**").permitAll()
.antMatchers("/users/**").hasRole("USER")
.and()
.formLogin().usernameParameter("username").passwordParameter("password");
}
}
}
View docs for Spring Security and sample code here.
I am using spring-boot-1.5.10 and spring-boot-starter-security.
In my microservice, I am exposing API's to the external world and internal microservices.
so I would like to 2-kind of security. one for external calls and other for internal calls.
I have referred this URL and tried to implement multiple security adapters in my application.
But no luck it's always picking the internal one instead of external one,
Please find the security adapter for your reference,
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired(required = false)
ServiceWebSecurityConfigurer serviceWebSecurityConfigurer;
// #Override
// public void configure(WebSecurity web) throws Exception {
// web
// .ignoring()
// .antMatchers(HttpMethod.PUT,"/v1/emp/**")
// .antMatchers(HttpMethod.DELETE,"/v1/emp/**");
// }
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authenticationProvider(new ExternalApiAuthenticationProvider())
.securityContext()
.securityContextRepository(new ExternalApiSecurityContextRepository())
.and()
.exceptionHandling()
.authenticationEntryPoint(new ApiAuthenticationEntrypoint())
.and()
.httpBasic().disable()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/v1/**").fullyAuthenticated();
if(serviceWebSecurityConfigurer != null)
serviceWebSecurityConfigurer.configure(http);
http.authenticationProvider(new InternalApiAuthenticationProvider())
.securityContext()
.securityContextRepository(new InternalApiSecurityContextRepository())
.and()
.exceptionHandling()
.authenticationEntryPoint(new ApiAuthenticationEntrypoint())
.and()
.httpBasic().disable()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.PUT,"/v1/emp/**").fullyAuthenticated()
.antMatchers(HttpMethod.DELETE,"/v1/emp/**").fullyAuthenticated();
}
}
It always picks the "InternalApiSecurityContextRepository" even the external API's using internal security.
It seems the later is overriding the former.
UPDATE-1(as per Gaurav Srivastav answer)
External API call security adapter :
#EnableWebSecurity
public class WebSecurityConfig {
#Configuration
#Order(2)
public static class InternalSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authenticationProvider(new InternalApiAuthenticationProvider())
.securityContext()
.securityContextRepository(new InternalApiSecurityContextRepository())
.and()
.exceptionHandling()
.authenticationEntryPoint(new InternalApiAuthenticationEntrypoint())
.and()
.httpBasic().disable()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.PUT,"/v1/emp/**").fullyAuthenticated()
.antMatchers(HttpMethod.DELETE,"/v1/emp/**").fullyAuthenticated();
}
}
#Configuration
#Order(1)
public static class ExternalSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authenticationProvider(new ExternalApiAuthenticationProvider())
.securityContext()
.securityContextRepository(new ExternalApiSecurityContextRepository())
.and()
.exceptionHandling()
.authenticationEntryPoint(new ApiAuthenticationEntrypoint())
.and()
.httpBasic().disable()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/v1/**").fullyAuthenticated();
}
}
}
It works for External(Since the order is 1) but for internal we are getting the following exception and it is using the External configuration security context,
An internal server error occurred.Message:An Authentication object was not found in the SecurityContext
I think the problem here is, we cannot use 2-security context it seems.Is there anyway to use different security context?
Any hint would be really appreciable to solve the issue.
Thanks in Advance.
You have define more than one configuration and specify the order using #Order annotation.
Internal Configuration with its own authentication provider and url pattern.
#EnableWebSecurity
public class MultiHttpSecurityConfig {
#Configuration
#Order(1)
public static class InternalSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/internal/**")
.authorizeRequests().anyRequest().hasRole("ADMIN")
.and().httpBasic().authenticationEntryPoint(authenticationEntryPoint());
}
}
#Configuration
#Order(2)
public static class ExternalSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/external/**")
.authorizeRequests().anyRequest().hasRole("ADMIN")
.and().httpBasic().authenticationEntryPoint(authenticationEntryPoint());
}
}
Get more detail through using below article.
https://www.baeldung.com/spring-security-multiple-entry-points
So I have a two login pages. One for Customer and one for AM. I configured 2 login pages in my WebSecurityConfig class. When I try to login in AM using an admin account it works but when I try to login in Customer using a user account the loginProcessingUrl can't be found.
In my WebSecurityConfig class:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig
{
#Autowired
MyDBAuthenticationService myDBAuthenticationService;
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(myDBAuthenticationService);
}
#Configuration
#Order(1)
public static class WebConfigurationAdapter1 extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests().antMatchers("/am/**").access("hasRole('ROLE_AM')")
.and()
.exceptionHandling()
.accessDeniedPage("/403")
.and()
.formLogin()
.loginPage("/amLogin")
.loginProcessingUrl("/am/postLogin")
.defaultSuccessUrl("/amChatPage")
.failureUrl("/amLogin?error")
.and().logout().logoutUrl("/amLogout").logoutSuccessUrl("/amLogoutSuccessful")
.deleteCookies("JSESSIONID")
.and().csrf().disable();
System.out.println("1st Configurer");
}
}
#Configuration
#Order(2)
public static class WebConfigurationAdapter2 extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests().antMatchers("/customer/**").access("hasRole('ROLE_CUSTOMER')")
.and()
.exceptionHandling()
.accessDeniedPage("/403")
.and()
.formLogin()
.loginPage("/customerLogin")
.loginProcessingUrl("/customer/postLogin")
.defaultSuccessUrl("/customerChatPage")
.failureUrl("/customerLogin?error")
.and().logout().logoutUrl("/customerLogout").logoutSuccessUrl("/customerLogoutSuccessful")
.and().csrf().disable();
System.out.println("2nd Configurer");
}
}
}
Here's my SpringWebAppInitializer class:
#Configuration
public class SpringWebAppInitializer implements WebApplicationInitializer{
#Override
public void onStartup(ServletContext sc) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(ApplicationContextConfig.class);
ServletRegistration.Dynamic dispatcher = sc.addServlet("dispatcher", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
Things that I have done so far are:
Putting sout() in each static class to know if it gets run. Both did display the sout().
Change name of both processing url and make it unique. Also change in my jsp file.
Spring boot - how to configure multiple login pages?
Here is the result when I login as AM:
Result in netbeans. It enters the Controller but says "null"
Here is the result when I login as Customer:
Since there is no differentiation pattern between both http configuration Spring Security is taking the first one login as default, that is the reason why only admin login works, because it is part of the web security adapter declared as Order(1).
In order to separate both configuration properly it is necessary to define a pattern separation with .antMatcher.
here is one small example to give you an idea of how define both configuration
For admins (see the .antMatcher definition it forces to apply the http configuration only to admin/** urls.
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.antMatcher("/admin/**").authorizeRequests().anyRequest().authenticated().anyRequest().hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/adminLogin")
.loginProcessingUrl("/admin/postLogin")
.defaultSuccessUrl("/admin/home")
.failureUrl("/adminLogin?error")
.and().logout().logoutUrl("/admin/logout").logoutSuccessUrl("/home")
.and()
.csrf().disable();
}
For customers (see the .antMatcher definition it forces to apply the http configuration only to customer/** urls.
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.antMatcher("/customer/**").authorizeRequests().anyRequest().authenticated().anyRequest().hasRole("USER")
.and()
.formLogin()
.loginPage("/customerLogin")
.loginProcessingUrl("/customer/postLogin")
.defaultSuccessUrl("/customer/home")
.failureUrl("/customerLogin?error")
.and()
.logout().logoutUrl("/customer/logout").logoutSuccessUrl("/home")
.and()
.csrf().disable();
}
There are other examples here: Example two login pages and visit the spring security documentation Multiple Http Security
Hope this information helps you.
According to the new configuration you have to do some changes, please review the following configuration, and compare with yours and you will see what is the difference (antMatcher is different of antMatchers)
#Configuration
#EnableWebSecurity
public class WebSecurityConfig
{
#Autowired
MyDBAuthenticationService myDBAuthenticationService;
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(myDBAuthenticationService);
}
#Configuration
#Order(1)
public static class WebConfigurationAdapter1 extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
//.authorizeRequests().antMatchers("/am/**").access("hasRole('ROLE_AM')")
.antMatcher("/am/**").authorizeRequests().anyRequest().hasRole("AM")
.and()
.exceptionHandling()
.accessDeniedPage("/403")
.and()
.formLogin()
.loginPage("/amLogin")
.loginProcessingUrl("/am/postLogin")
.defaultSuccessUrl("/am/chatPage")
.failureUrl("/amLogin?error")
.and().logout().logoutUrl("/am/logout").logoutSuccessUrl("/amLogoutSuccessful")
.deleteCookies("JSESSIONID")
.and().csrf().disable();
System.out.println("1st Configurer");
}
}
#Configuration
#Order(2)
public static class WebConfigurationAdapter2 extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
//.authorizeRequests().antMatchers("/customer/**").access("hasRole('ROLE_CUSTOMER')")
.antMatcher("/admin/**").authorizeRequests().anyRequest().hasRole("CUSTOMER")
.and()
.exceptionHandling()
.accessDeniedPage("/403")
.and()
.formLogin()
.loginPage("/customerLogin")
.loginProcessingUrl("/customer/postLogin")
.defaultSuccessUrl("/customer/chatPage")
.failureUrl("/customerLogin?error")
.and().logout().logoutUrl("/customer/logout").logoutSuccessUrl("/customerLogoutSuccessful")
.and().csrf().disable();
System.out.println("2nd Configurer");
}
}
}
And finally remember the controller, you should have the following RequestMapping definition at least
#RequestMapping("/adminLogin"), #RequestMapping("/customerLogin"), #RequestMapping("/am/chatPage"), #RequestMapping("/customer/chatPage")
I want to put restriction on this "/realtime/updates" Url but If I request "/anyurl" it redirects me to Login page. I want to be redirected to login page only for "/realtime/updates".
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecConfig1 extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests().antMatchers("/realtime/updates").hasRole("USER").anyRequest().authenticated().and().formLogin();
}
#Autowired
public void ConfigGlobal(AuthenticationManagerBuilder auth) throws Exception{
auth.inMemoryAuthentication().withUser("abc").password("123").roles("USER");
}
}
You need to change one snippet in the protected void configuremethod.
Try this:
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers("/**").permitAll()
.antMatchers("/realtime/updates").hasRole("USER")
.and().formLogin().permitAll();
}
You need to add your restrictions in configure method.Your method like below :
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/realtime/updates/**").authenticated()
.antMatchers("/otherURL/**").hasRole("ADMIN")
.and()
.exceptionHandling().accessDeniedPage("/login")
.and()
.formLogin().loginPage("/index")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/j_spring_security_check")
.failureUrl("/loginControl?error=true")
.defaultSuccessUrl("/loginControl?error=false")
.and()
.logout().logoutUrl("/logout").logoutSuccessUrl("/index")
;
}
I was calling super.configure(http); inside configure method I removed that it worked.
This is was previous code:
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests().antMatchers("/realtime/updates")
.hasRole("USER")
.anyRequest()
.authenticated()
.and()
.formLogin();
}
This is current code that worked:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/realtime/updates")
.hasRole("USER")
.anyRequest()
.authenticated()
.and()
.formLogin();
}
I am using Spring Security for basic authentication to secure my REST APIs.
Below is the configuration code:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("password")
.roles("admin");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated();
}
}
I am getting forbidden (403) error on authenticating myself using the correct username and password.
Please suggest the modifications to get it working.
You haven't enabled HTTP Basic Authentication you have to use HttpSecurity.httpBasic()
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception{
auth.inMemoryAuthentication().withUser("user").password("password").roles("admin");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().authenticated();
}
}
Updated
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().httpBasic().and().authorizeRequests().anyRequest().authenticated();
}