Spring Boot: Authenticating both a Stateless REST API and a Stateful "Login" Web Controller in the same project? - spring

So I have an application that contains a REST API which is used by a custom java application on an IOT device with no user interaction.And I also have a web app which needs a stateful session for maintaining user login.
Is it possible to use Spring Security to authenticate requests to my API and web controller differently?What form of authentication should I be using for the REST API?

One way to achieve what you are looking for is to have 2 configurations in your spring security. E.g.
Pay attention to antMatcher (matcher not matchers). The antMatcher will control on what set of url your entire config applies i.e. FormLoginWebSecurityConfigurerAdapter in below example will apply only to uri matching /api/test/**. Of course, you can define the antMatcher only in one of the configs say config1 and the other config in that case will be a catch all (i.e catch everything that does not match config1)
#EnableWebSecurity
#Configuration
public class SecurityConfig {
#Configuration
#Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
public void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication().withUser("user").password("user").roles("USER");
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
}
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
http
.antMatcher("/api/v1/**")
.authorizeRequests()
.antMatchers("/api/v1/**").authenticated()
.and()
.httpBasic();
}
}
#Configuration
#Order(2)
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
public void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication().withUser("user1").password("user").roles("USER");
auth.inMemoryAuthentication().withUser("admin1").password("admin").roles("ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED); // CONFIGURE TYPE OF SESSION POLICY
http
.antMatcher("/api/test/**")
.authorizeRequests()
.antMatchers("/api/test/**").authenticated()
.and()
.formLogin();
}
}
}

Related

Spring Boot Security Authentication: Application having 2 different domain URL and need to authenticate with Spring Security

I need help with one of the issue that I am facing with Spring Boot Security. I have application which has 2 different Urls.(Infoblock CNAME)
domain1.com
domain2.com
both Url are point to the same application.
Due to business reason we need 2 different Url and we are planning to land on diff page based on the URL entered in browser. Issue is with Spring Security AntMatcher.
With AntMatcher we can only provide path but how we can address the domain with it.
Could you please guide me.
Thanks in Advance.
Instead of AntMatcher you can use
http.requestMatcher(new RequestHeaderRequestMatcher("Host", "127.0.0.1:8080"))
with any other matcher from org.springframework.security.web.util.matcher package.
Here is an example:
#EnableWebSecurity
#Configuration
public static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Configuration
#Order(1)
public static class SecConfig1 extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new RequestHeaderRequestMatcher("Host", "127.0.0.1:8080"))
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin();
}
}
#Configuration
#Order(2)
public static class SecConfig2 extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new RequestHeaderRequestMatcher("Host", "127.0.0.2:8080"))
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
}
#Override
protected void configure(HttpSecurity http) throws Exception {
//default deny all
http.authorizeRequests().anyRequest().denyAll();
}
}

LDAP authentication with Spring Boot 1.4.1

I am using Spring boot and developing REST services and want to integrate with LDAP authentication security mechanism.
I googled a lot but did not get a concrete solution as such. I am looking for a complete example.
Also I am using POSTMAN client and want to know how to use it to test the LDAP authentication.
Thanks in advance..!!
Here is an example using ActiveDirectoryLdapAuthenticationProvider
This was actually surprisingly simple. Thank you, Boot.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/yourstuff/**").permitAll()
.antMatchers("/your/protectedstuff/**").authenticated()
.and()
.httpBasic()
.permitAll();
}
#Configuration
protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter {
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new ActiveDirectoryLdapAuthenticationProvider("DOMAINNAME","LDAP SERVER URI"));
}
}
}

Controlling access to Spring Security OAuth2 endpoints

I'm trying to control what clients can generate access tokens in Spring Security OAuth2.0.
I'd like to allow only one client to be able to generate access tokens (access /oauth/authorize, /oauth/token) and all the other ones to validate them.
The documentation says that I should use the standard Spring Security WebSecurityConfigurer to achieve such an access granularity. However, all the configuration I do does not affect access to the end-points.
I tried the following configuration to allow only client mgmt to generate tokens:
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("mgmt")
.secret("pass")
.authorities("ROLE_WRITE")
.and()
.withClient("resource")
.secret("pass")
.authorities("ROLE_READ");
}
}
#Configuration
public class EndpointAuthorizationConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/oauth/token")
.and()
.authorizeRequests()
.antMatchers("/oauth/token")
.hasAuthority("ROLE_WRITE")
.and()
.httpBasic();
}
}
I also tried to define users one more time in the EndpointAuthorizationConfig class, but that did not help. Client resource still can access those endpoints.
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("mgmt")
.password("pass")
.roles("WRITE");
}

Spring Boot Management security works differently with port set

I'm trying to configure a Spring Boot application (1.2.3, but this also fails with the 1.2.4.BUILD-SNAPSHOT version) with Actuator support. I want to use the Actuator security config for controlling access to the management endpoints, and our own authentication for the rest of the application.
Here is my security config:
#Configuration
#EnableWebSecurity
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
#Autowired
private CustomAuthenticationProvider customAuthProvider;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.authenticationProvider(customAuthProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.regexMatchers(API_DOC_REGEX).permitAll()
.regexMatchers(String.format(PATH_REGEX, PUBLIC_ACCESS)).permitAll()
.regexMatchers(String.format(PATH_REGEX, INTERNAL_ACCESS)).access("isAuthenticated() && authentication.hasOrigin('INTERNAL')")
.regexMatchers(String.format(PATH_REGEX, EXTERNAL_AUTHENTICATED_ACCESS)).authenticated()
.antMatchers("/**").denyAll()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.addFilterAfter(customAuthProcessingFilter(), BasicAuthenticationFilter.class)
.csrf().disable();
}
}
This works correctly when I don't set a management port, but when I set the management port, the management URLs return 401 responses. If I comment out the line .antMatchers("/**").denyAll(), then everything goes through without requiring authentication at all. So it looks like it is using my application's security config for the Actuator endpoints when I set a custom port, but I'm not sure why.
How do I get it to use it's own security when running on a custom port?
Expanding on the comment from #M. Deinum, adding another adapter for the Management stuff (even though it already has one) seems to have fixed it. This is the class I ended up with:
#Order(0)
#Configuration
public class ManagementSecurityConfig extends WebSecurityConfigurerAdapter
{
#Autowired
ManagementServerProperties managementProperties;
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.requestMatchers()
.requestMatchers(new RequestMatcher()
{
#Override
public boolean matches(HttpServletRequest request)
{
return managementProperties.getContextPath().equals(request.getContextPath());
}
})
.and()
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}

Spring OAuth 2: public access to a resource

How do I allow public access in an specific URL in a Spring Security OAuth-2 Rest application.
I have all URLs started with /rest/** secured, but would like to make /rest/about public, so I would not require the user to authenticate to access it. I tried using permitAll() but it still requires the token in the request. This is my HttpSecurity configuration:
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends
ResourceServerConfigurerAdapter {
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/rest/about").permitAll()
.antMatchers("/rest/**").authenticated()
;
}
}
A GET request to /rest/about still returns 401 Unauthorized - "error":"unauthorized","error_description":"Full authentication is required to access this resource"
Found the answer. I just needed to add anonymous():
public void configure(HttpSecurity http) throws Exception {
http
.anonymous().and()
.authorizeRequests()
.antMatchers("/rest/about").permitAll()
.antMatchers("/rest/**").authenticated()
;
}
Got the answer from: https://stackoverflow.com/a/25280897/256245

Resources