Spring actuator and Spring Security to allow access - all. Whitelabel Error Page - spring-security

Gradle configuration:
plugins {
id("org.springframework.boot") version "2.3.3.RELEASE"
}
Spring Security configuration:
#Configuration
#RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public PasswordEncoder passwordEncoder() {
int rounds = 12;
return new BCryptPasswordEncoder(rounds);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/actuator/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.permitAll();
}
}
Spring Boot configuration:
server:
port: 9090
management:
server:
port: 90901
endpoints:
web:
exposure:
include: '*'
I would like to set up access without authorization to actuator endpoints. However, when I try to request information from the browser line, I get a display error.
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Can anyone explain why this is happening and how to fix it?

Related

Spring cloud + Keyclock + Angular - CORS Error

I'm trying to build a microservices application using spring-cloud + spring-gateway + keycloak + angular-frontend. In my application there is a api-gateway application that handle all the request and later will dispatch those request to the right microservice.
For the front-end I'm using angular and for test the endpoints I'm using postman. At the moment I'm having a CORS problem.
I've configured the api-gateway in this way:
spring:
cloud.gateway:
globalcors.corsConfigurations:
'[/**]':
allowedOrigins: '*'
allowedPorts: '*'
allowedHeaders: '*'
allowedMethods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
security.oauth2:
client:
provider:
keycloak:
authorization-uri: ${app.config.keycloak.url}/realms/${app.config.keycloak.realm}/protocol/openid-connect/auth
token-uri: ${app.config.keycloak.url}/realms/${app.config.keycloak.realm}/protocol/openid-connect/token
userinfo-uri: ${app.config.keycloak.url}/realms/${app.config.keycloak.realm}/protocol/openid-connect/userinfo
jwk-set-uri: ${app.config.keycloak.url}/realms/${app.config.keycloak.realm}/protocol/openid-connect/certs
user-name-attribute: preferred_username
user-info-authentication-method: header
registration:
keycloak:
provider: keycloak
client-id: ${app.config.keycloak.client}
authorization-grant-type: authorization_code
redirect-uri: '{baseUrl}/login/oauth2/code/keycloak'
scope: openid
resourceserver:
jwt:
jwk-set-uri: ${app.config.keycloak.url}/realms/${app.config.keycloak.realm}/protocol/openid-connect/certs
Below the securityConfig of gateway:
#Configuration
public class SecurityConfig {
#Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.authorizeExchange()
.anyExchange().authenticated()
.and().cors()
.and().csrf().disable().oauth2Login()
.and().oauth2ResourceServer().jwt();
return http.build();
}
}
And below the securityConfig of ms:
#EnableWebSecurity
public class SecurityConfig {
#Bean
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests(authorizeRequests -> authorizeRequests
.antMatchers("/v3/api-docs/**").permitAll()
.antMatchers("/swagger-ui/**").permitAll()
.anyRequest().authenticated()
).oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}
}
Said that, if for instance I make a request with postman to the path /api/controller I get the correct response. If I'm using the angular client and try to access an end-point I get this error:
Preflight: (failed)net::ERR_CONNECTION_REFUSED
Do you have any idea how to fix this? Any help will be appreciated. Thanks to all
Below my gateway pom dependencies:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

spring security oauth2 returning 404 after authorize

I have setup OAuth2 client application with the following configuration in my application.yml file
spring:
security:
oauth2:
client:
registration:
octa:
client-id: <confidential>
client-secret: <confidential>
scope: openid
redirect-uri: http://localhost:8555/oauth/callback
clientName: octa
provider: octa
provider:
octa:
issuer-uri: https://dev-7858070.okta.com/oauth2/default
user-name-atttibute: name
server:
port: 8555
My spring boot application is running on port 8555 and below is my security configuration
#Configuration
public class ApplicationSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests()
.antMatchers("/", "/login**","/callback/", "/webjars/**", "/error**", "/oauth/**")
.permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
}
When the authorization server returns the url http://localhost:8555/oauth/callback?code=t8oJIWdR2lTgY1_06WPzR2d with 404 error.
I should ideally be getting the access token. Where am I going wrong?

Spring security WebSecurityConfigurerAdapter reading application.properties

In my application, I want to configure spring security for configuring HSTS support.
I have modified pom.xml for adding required libraries.
Now I want to read the HSTS related configurations from application.properties. I have added the code as below;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Value("${app.security.headers.hsts}")
private boolean hsts;
#Value("${app.security.headers.hsts.includeSubDomains}")
private boolean includeSubDomains;
#Value("${app.security.headers.hsts.maxAge}")
private long maxAge;
#Override
protected void configure(HttpSecurity http) throws Exception {
if(hsts) {
http.headers().
httpStrictTransportSecurity().
includeSubDomains(includeSubDomains).
maxAgeInSeconds(maxAge);
}
}
}
However the spring application is failed to start. It is throwing below error,
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecurityConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'app.security.headers.hsts' in value "${app.security.headers.hsts}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)

Spring Security (Java Config): Using antmatchers for same URL with differing HTTP methods

I'm trying to restrict GET access to a URL for one role, and POST access to the same URL for another role as seen below.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("readuser").password("password").roles("USER", "READ").and()
.withUser("admin").password("password").roles("USER", "READ", "WRITE");
}
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin().permitAll().and()
.logout().permitAll().and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/api/foo").hasRole("READ")
.antMatchers(HttpMethod.POST, "/api/foo").hasRole("WRITE")
.anyRequest().authenticated()
.and().csrf().disable()
.httpBasic();
When I try a GET (or a POST) with my readuser account, I get an access denied error; but when I try either with the admin account, it can do both.
However, when I remove the line .antMatchers(HttpMethod.POST, "/api/foo").hasRole("WRITE") then my readuser account can properly hit /api/foo with a GET request.
How can I make Spring Security allow both of these restrictions?
UPDATE - including relevant spring security debug log information
Here are the relevant logs when attempting with readuser:
************************************************************
Request received for GET '/api/foo?id=foo':
Request(GET //localhost:8089/api/foo?id=foo)#b4603eb
servletPath:/api/foo
pathInfo:null
headers:
Authorization: Basic cnVudXNlcjpwYXNzd29yZA==
Cookie: JSESSIONID=node0fe3b0i44a5sbpohi6jq6dkkw0.node0
Cache-Control: no-cache
Accept: */*
User-Agent: PostmanRuntime/3.0.11-hotfix.2
Connection: keep-alive
Postman-Token: 99a23213-6cf8-4686-9886-7f9c2de13c6f
Host: localhost:8089
Accept-Encoding: gzip, deflate
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
BasicAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
************************************************************
.
.
.
2017-05-08 11:31:27.817 DEBUG 5812 --- [p1731685294-106] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/api/foo'; against 'GET'
2017-05-08 11:31:27.817 DEBUG 5812 --- [p1731685294-106] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/api/foo'; against '/api/foo'
2017-05-08 11:31:27.817 DEBUG 5812 --- [p1731685294-106] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /api/foo?id=foo; Attributes: [hasRole('ROLE_WRITE')]
2017-05-08 11:31:27.818 DEBUG 5812 --- [p1731685294-106] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#a38eb23d: Principal: org.springframework.security.core.userdetails.User#5c7268d6: Username: readuser; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_READ,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_READ, ROLE_USER
2017-05-08 11:31:27.818 DEBUG 5812 --- [p1731685294-106] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#7b20c046, returned: -1
2017-05-08 11:31:27.819 DEBUG 5812 --- [p1731685294-106] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is not anonymous); delegating to AccessDeniedHandler
org.springframework.security.access.AccessDeniedException: Access is denied
.
.
.
2017-05-08 11:31:27.823 DEBUG 5812 --- [p1731685294-106] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
You are using the wrong HttpMethod class.
javax.ws.rs.HttpMethod#GET returns a String and therefore you use antMatchers(String... antPatterns) instead of antMatchers(HttpMethod method, String... antPatterns) in your Spring Security configuration.
With that configuration Spring Security checks against the URL patterns GET and /api/foo (both for all HTTP methods), see your log:
2017-05-08 11:31:27.817 DEBUG 5812 --- [p1731685294-106] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/api/foo'; against 'GET'
2017-05-08 11:31:27.817 DEBUG 5812 --- [p1731685294-106] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/api/foo'; against '/api/foo'
You have to use org.springframework.http.HttpMethod#GET, which returns a HttpMethod object.

Spring Security Authenticates and immediately returns Access Denied

This text is directly from my console logger when running this locally. The second line immediately follows the first. I'm not sure what is happening behind the scenes that is providing the access denied exception.
2014-01-30 07:48:14.854 INFO 5452 --- [nio-8085-exec-3] o.s.b.a.audit.listener.AuditListener : AuditEvent [timestamp=Thu Jan 30 07:48:14 CST 2014, principal=r2n, type=AUTHENTICATION_SUCCESS, data={details=org.springframework.security.web.authentication.WebAuthenticationDetails#957e: RemoteIpAddress: 127.0.0.1; SessionId: 2C7EC273522BB6880EE3410201F8A41F}]
2014-01-30 07:48:14.859 INFO 5452 --- [nio-8085-exec-4] o.s.b.a.audit.listener.AuditListener : AuditEvent [timestamp=Thu Jan 30 07:48:14 CST 2014, principal=r2n, type=AUTHORIZATION_FAILURE, data={message=Access is denied, type=org.springframework.security.access.AccessDeniedException}]
My code is compiled using Spring Boot version 1.0.0.RC1, Spring Security 3.1.0.Release and thymeleaf for spring 2.1.1.Release. I know there are some conflicts with the underlying spring dependencies and thymeleaf for spring 3 as spring boot uses spring 4.
I don't think my issues lie their.
Here's the code from WebSecurityConfiguration extending WebSecurityConfigurerAdapter. My authentication is using ldap.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/error").anonymous()
.antMatchers("/navigation").anonymous()
.antMatchers("/**").hasRole("ADMIN") // #4
.and()
.formLogin()
.permitAll()
.defaultSuccessUrl("/")
.and()
.csrf().disable();
}
Your "r2n" user appears not to have "ADMIN" authorities. Maybe you set him up with "ROLE_ADMIN" and the access rule is "ADMIN" or something?
P.S. I think you mean Spring Security 3.2.0.RELEASE (the Javaconfig isn't in 3.1).

Resources