Securing a REST application in SpringBoot and accessing it from a Rest Client - spring

I am pretty new to Springboot. I have developed a rest server but I was wondering how to perform Basic authentication from a client and how to configure the spring boot server to authenticate request. The tutorials I saw online didn't include a restful client. Would be great if you can show some code including both the client request and server authentication process with springboot rest.

On the client side since you are using Jersey Client you need to do something like the following:
Client c = Client.create();
c.addFilter(new HTTPBasicAuthFilter(user, password));
One the server side you need to enable Spring Security and set Basic Authentication for it which would look something like the following (this is the simplest possible case).
#Configuration
#EnableWebSecurity
public class RootConfig extends WebSecurityConfigurerAdapter {
#Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception
{
auth.inMemoryAuthentication()
.withUser("tester").password("passwd").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeUrls()
.anyRequest().authenticated()
.and()
.httpBasic();
}
}

Related

Spring Boot Security + Spring Boot REST Repository config issue

I have Spring boot application as below
And the Web Security Config as
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().formLogin();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// #formatter:off
auth.inMemoryAuthentication().withUser("chiru").password("{noop}chiru").roles("ADMIN").and().withUser("user")
.password("{noop}user").roles("USER");
// #formatter:on
}
}
And the i have Repository as below
public interface IssuesRepository extends CrudRepository<Issues, Integer> {
}
when i try to add data through REST Using Postman with Basic Authentication, its failing
Use httpBasic() instead of formLogin(), like http.authorizeRequests().anyRequest().authenticated().and().httpBasic();.
formLogin() is used when you want to have login page to authenticate the user (so you have), but in your example you are using http basic to do that. Spring security doesn't recognizes your http basic header and returns login page.
PS. You can use both methods http.httpBasic().and().formLogin()

Avoid oauth authentication for specific endpoints: Spring boot oAuth2

I am quite new to Spring boot OAuth. My application is using OAuth2 integrated with Azure AD. I want to have a URL which will not redirect to Azure AD for authentication. It was quite straight forward with Spring Security, we could configure something like this:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/someURL");
}
Is there an alternative available for OAuth?
Yes can allow access to everyone by using this
#Override
public void configure(HttpSecurity http) throws Exception {
http.antMatchers("/someURL").permitAll();
}
for details check.
You can avoid specific end point authentication like below
#Override
public void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/url/**").permitAll()
.anyRequest().authenticated();
}

Spring Security with OAuth2 and anonymous access

I have my Spring REST API secured with Spring Security and OAuth2, I can successfully retrieve a token and access my APIs. My App defines the OAuth2 client itsself.
Now I want users to have anonymous access on some resources. The use case is really simple: I want my app to be usable without login - but if they are logged in, I want to have access to that principal.
Here is my WebSecurityConfigurerAdapter so far:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/api1").anonymous().and()
.authorizeRequests().antMatchers("/ap2**").permitAll();
}
As soon as I add a second antMatcher/anonymous, it fails to work though, and it doesn't really express my intent either - e.g. I wan't to have anonymous access on api1 GETs, but authenticated on POSTs (easy to do with #PreAuthorize).
How can I make the OAuth2 authentication optional?
I dropped my #EnableWebSecurity and used a ResourceServerConfigurerAdapter like so:
#Configuration
#EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/api/api1", "/api/api2").permitAll()
.and().authorizeRequests()
.anyRequest().authenticated();
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("my-resource-id");
}
}
/api/api1 may now be called with or without authentication.

how to IP white list /oauth/check_token endpoint in spring security

I have two applications (war), one acting as a Resource Server and other is my Auth Server running on two different servers. I am using client_credentials grant_type. I need to white list the IP of my resource server so that nobody else can access the "/oauth/check_token" end point directly using post-man or browser or any other user-agent. Here is the code snippet from auth server :
#EnableAuthorizationServer
#Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("isFullyAuthenticated()")
.allowFormAuthenticationForClients().realm(REALM + "/client");
}
...
some other configuration code related to ClientDetails and tokenStore.
...
}
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers(HttpMethod.GET,"/oauth/check_token").access("isFullyAuthenticated() and hasIpAddress('0.0.0.0/0')").accessDecisionManager(accessDecisionManager)
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint)
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
I found a way to whitelist IP in spring :
#Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http
.authorizeRequests()
.anyRequest().access("hasIpAddress('0.0.0.0/0')");
}
But this is not helping in my situation because it is only checking for fullyAuthenticated(). I want all the resource server should be authenticated and authorized before accessing "/oauth/check_token"
Edited
I have referred to a similar kind of problem : How to find users' IPs in Spring Security? but it wasn't helping me because in that question they were trying to authorize a resource server Api, but in my case i want to authorize spring-security default endpoint i.e; /oauth/check_token
On further debuggin I found that if I remove .antMatchers(HttpMethod.GET,"/oauth/check_token").access("hasIpAddress('0.0.0.0/0')").accessDecisionManager(accessDecisionManager)
i am still able to use /oauth/check_token endpoint.
Then I tried to change fullyAuthenticated to permitAll() in AuthorizationServerSecurityConfigurer.checkTokenAccess("permittAll()"); it started allowing everybody to access check_token endpoint. Which implies it isn't even reading the configuration from .antMatchers(HttpMethod.GET,"/oauth/check_token")
Now I am confused how to configure hasIpAddress() and do we need to explicitly mention antMatcher("/oauth/check_token") or it is provided by default.
You can model it like this, which keeps both requirements - IP whitelisting and all requests are authenticated. You can remove the localhost access rule if not needed:
http
.authorizeRequests()
.antMatchers(GET, "/oauth/check_token")
.access("isFullyAuthenticated() and
(hasIpAddress('IP_OR_NETWORK_OF_RESOURCE_SERVER')
or hasIpAddress('127.0.0.1/32'))")
.antMatchers("/**").fullyAuthenticated();

Authorisation and role check in a spring boot application

I have a spring boot application where I have several REST APIs. Now I want to do a authorisation check for all the requests. This involves each request using a x509 client certificate and then some business logic for authorisation purpose, something similar to role checking.
what is the best place to do this i.e. should this check be done in DispatcherServlet - doDispatch method? Doing the same check for each request in Controller doesn't make much of a sense.
Can someone suggest where to put these kind of checks in a spring boot application ?
You have two choices. Java config or xml config.
I recommend java config. Create a config class and configure like this
For java config it would look something like
#Configuration
#EnableWebSecurity
public class LoginSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationMgr) throws Exception {
authenticationMgr.inMemoryAuthentication()
.withUser("jduser").password("jdu#123").authorities("ROLE_USER")
.and()
.withUser("jdadmin").password("jda#123").authorities("ROLE_USER","ROLE_ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/homePage").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
.antMatchers("/userPage").access("hasRole('ROLE_USER')")
.antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')")
.and()
.formLogin().loginPage("/loginPage")
.defaultSuccessUrl("/homePage")
.failureUrl("/loginPage?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/loginPage?logout");
}
}

Resources