Access OAuth2 Protected api from the Java Batch Application - java

I have Springboot Microservice app comprises( Discovery , Eureka Client , Zulu Proxy , Gateway )which is configured with OAUTH2 which is working fine.
and OAUTH2 is configured as the in memory token store. i have rest end points gateway exposed
ex :
localhost:8080/hello/gateway
now i have java batch , which will call micro service app gateway example (above api) to get the required response. since that is protected with OAUTH2 i cant access api directly.
is there a way to access the api without token or can we bypass the authorization logic by passing the hardcoded token from batch and validating in the Gateway
Tried to create a non-expiring token but since its in-memory token, it will not work after the api restart
Tired to create a custom filter and but it didnt work as expected . below is my resource server code.
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "resource_id";
#Autowired
private AppProperties appProperties;
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID).stateless(false);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.
anonymous().disable()
.authorizeRequests()
.antMatchers("/testService/**").authenticated()
.and()
//.addFilterBefore(new BatchCustomFilter(), BasicAuthenticationFilter.class)
.exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
Let me if know there is any good way of doing this , Suggestions are highly appreciated .

yes had overridden WebSecurityConfigurerAdapter configure method to ignore the specific endpoint.
#Override
public void configure(final WebSecurity web) throws Exception {
web.ignoring().antMatchers("/testService/testApi/**");
}
Now im able to access Api from batch after ignoring the endpoint from web security.

Related

Spring Security: Purpose of .oauth2Client(withDefaults()); in HttpSecurity

This is from the doc
public HttpSecurity
oauth2Client​(Customizer<OAuth2ClientConfigurer>
oauth2ClientCustomizer) throws java.lang.Exception
Configures OAuth 2.0 Client support.
Example Configuration
The following example demonstrates how to enable OAuth 2.0 Client
support for all endpoints.
#Configuration
#EnableWebSecurity
public class OAuth2ClientSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests((authorizeRequests) ->
authorizeRequests
.anyRequest().authenticated()
)
.oauth2Client(withDefaults());
}
}
Parameters: auth2ClientCustomizer - the Customizer to provide more
options for the OAuth2ClientConfigurer
Returns: the HttpSecurity for further customizations
The thing I understood is any requests coming to this server should be authenticated.
How does
.oauth2Client(withDefaults()); help in this case?
If I'm not wrong, an oAuth2 client is the one sending the requet, what can we actually configure about this? The documentation doesnt really explain much.
The http instance of HttpSecurity is a "bean settings server/application side".
Its method oauth2Client is not related to client configurations, but how and where the server/application should handle them.
Example:
Which clients have been authorized
Where to store authorized clients
How to authorize clients
How to remove an old authorized client
I think here , you can find more details about oauth2Client defaults .
#EnableWebSecurity
public class OAuth2ClientSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.oauth2Client(oauth2Client ->
oauth2Client
.clientRegistrationRepository(this.clientRegistrationRepository())
.authorizedClientRepository(this.authorizedClientRepository())
.authorizedClientService(this.authorizedClientService())
.authorizationCodeGrant(authorizationCodeGrant ->
authorizationCodeGrant
.authorizationRequestRepository(this.authorizationRequestRepository())
.authorizationRequestResolver(this.authorizationRequestResolver())
.accessTokenResponseClient(this.accessTokenResponseClient())
)
);
}
}

Spring Security - Wildcards/matchers in authorization rules

While configuring the security of my Spring Boot application, I wanted to secure parts of the API depending on the PathVariable that is entered there. My current configuration is as follows:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//not important
#Override
public void configure(HttpSecurity http) throws Exception {
http.cors();
http.authorizeRequests()
.mvcMatchers("/api").authenticated()
.mvcMatchers("/api/TEST").hasAuthority("SCOPE_dep:TEST")
.and().oauth2ResourceServer().jwt();
}
}
In the the 'api/{PathVariable}' endpoint is the one I want to have customized, making sure that someone with the authority 'SCOPE_dep:TEST' can access the 'api/TEST' endpoint, someone with 'SCOPE_dep:TEST2' authority can access the 'api/TEST2' endpoint, even allowing more then one such endpoint for a user which has multiple of these authorities.
Is there a way to do this by using a type of wildcard/matcher that I'm unaware of, or is the only possiblity hardcoding all these different authorities?

Spring Boot HttpSecurity fluent api order?

Spring 2.0.3.RELEASE
Goal: Implement Spring Boot Security (basic auth for starters) on all endpoints except /actuator/health, /actuator/info and /ping (a custom controller that just returns ResponseEntity.status(HttpStatus.NO_CONTENT).build()).
The below gives me a 401. Any combination seems to either give me complete anonymous access to all endpoints or 401 to all.
I've set the spring.security.user.name and ...password in application.yml and it is working correctly.
I've implemented...
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
super.configure(http);
// just trying to get health working for starters
http.authorizeRequests().antMatchers("/actuator/health").permitAll()
.anyRequest().authenticated()
.and().formLogin().permitAll();
}
}
The below seemed like it was restricted to Actuator's /health and /info endpoints, but instead is also opening up my custom /ping endpoint as well (it's not in this list).
http.requestMatcher(EndpointRequest.to("health", "info"))
.authorizeRequests().anyRequest().permitAll();
The issue ended up being a bug in Spring Tool Suite. Using Boot Dashboard with a Gradle project wasn't always picking up build output. It seems to be using a different directory and I cannot figure it out.
The HttpSecurity configuration that ended up working for me was:
#Override
protected void configure(final HttpSecurity http) throws Exception {
// #formatter:off
http.
authorizeRequests().
antMatchers("/ping", "/actuator/health", "/actuator/info", "/login").permitAll().
anyRequest().authenticated().and().
httpBasic().and().
// CSRF tokens for API access
csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
// #formatter:on
}

How to set default #AuthenticationPrincipal on startup

For development purpose, I am trying to configure a development profile for which developers don't need to be authenticated in the application to call REST services.
But, some of these services need an #AuthenticationPrincipal to work.
So I would like to be able to define a mocked #AuthenticationPrincipal on startup to be used by default.
Does anyone have any kind of idea to do so?
Currently the application behavior expected for the user authentication is:
A REST endpoint should send a HTTP code 401 if the user isn't authenticated.
In this case, the Front-end should redirect the user to the back-end URL /login so that he can authenticate itself.
On success, the back-end should then redirect the user to the front-end.
It turn out that it wasn't a good solution, here a list of the different reasons I can think of:
The behavior of the back-end server would be different between the development and the production environments.
This would force the front-end to also have different behaviors between these two environments.
JUnits wouldn't be able to test all expected answers (example: HTTP code 401 if not authenticated) from endpoints.
So in place, I have created a security configuration (enabled only when not using the production profile) emulating the expected behavior from the front-end point of view.
Here the MockAuthenticationSecurityConfiguration class:
#Configuration
#Profile("!PRODUCTION")
public class MockAuthenticationSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final ApplicationProperties applicationProperties;
public MockAuthenticationSecurityConfiguration(final ApplicationProperties applicationProperties) {
this.applicationProperties = applicationProperties;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("swagger-ui.html").permitAll();
// All API REST endpoint can only be accessed by an authenticated user.
http.authorizeRequests().antMatchers("/api/**").authenticated()
// For these REST endpoint to answer HTTP code 401 in place of redirecting the user to /login.
.and().exceptionHandling().defaultAuthenticationEntryPointFor(new Http401UnauthorizedEntryPoint(), new AntPathRequestMatcher("/api/**"))
// On success, we want to redirect the user to a specific URL (the frontend).
.and().formLogin().permitAll().successHandler(new SimpleUrlAuthenticationSuccessHandler(applicationProperties.getRedirectUrl()))
.and().logout().permitAll()
;
http.csrf().disable();
http.cors();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// Add a mocked user to be used to authenticate.
auth.inMemoryAuthentication().withUser(User.withDefaultPasswordEncoder().username("jdoe").password("jdoe").roles("USER"));
}
}
Here the Http401UnauthorizedEntryPoint class:
public class Http401UnauthorizedEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
}
}
And then the ApplicationProperties class:
#Getter
#Setter
#Component
#ConfigurationProperties("application")
public class ApplicationProperties {
/**
* The URL to which we should redirect the user once he is logged in the application.
*/
private String redirectUrl;
}

How to separate authorization server spring security in java

I have started to learn spring security (Oauth2). I am having a REST API service which is protected by Spring Oauth2. What i want to do is, I want to separate authorization server and resource server, For example,
I am having
Authorization: http://server1:8080/RESTTest/oauth/token/grant_type=client_credentials&client_id=clientt&client_secret=secret
And
Resource
http://server1:8080/RESTTest/api/users/?access_token=2cf682c6-2900-47dc-a468-441fcee0dc18
What i want is,
Authorization : http://Server1:8080/authorizationserver /oauth/token/grant_type=client_credentials&client_id=clientt&client_secret=secret
Resource:
http://server2:8080/RESTTest/api/users/?access_token=2cf682c6-2900-47dc-a468-441fcee0dc18
I am using JDBCTokenstore. I am not sure how to separate it. Can someone help me.
Thanks,
You can map your custom endpoint to defaults provided, fyi http://projects.spring.io/spring-security-oauth/docs/oauth2.html
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
.authenticationManager(authenticationManager);
endpoints.pathMapping("/oauth/token", "/authorizationserver/oauth/token")
}
}

Categories

Resources