Spring Boot - override OAuth client configuration at startup - spring

I have a Spring Boot application with the following config:
#SpringBootApplication
#EnableOAuth2Sso
#Configuration
public class DemoApplication extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/","/appConfig", "/login/**", "/webjars/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/"))
.and().logout()
.logoutSuccessUrl("/").permitAll()
.and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
...
}
In the resources, I have an application.yml, which contains the client configuration:
security:
oauth2:
client:
clientId: #keycloak.client.id#
clientSecret: #keycloak.client.secret#
accessTokenUri: https://#keycloak.host#:#keycloak.port#/auth/realms/#keycloak.realm#/protocol/openid-connect/token
userAuthorizationUri: https://#keycloak.host#:#keycloak.port#/auth/realms/#keycloak.realm#/protocol/openid-connect/auth
authenticationScheme: header
clientAuthenticationScheme: header
resource:
userInfoUri: https://#keycloak.host#:#keycloak.port#/auth/realms/#keycloak.realm#/protocol/openid-connect/userinfo
So far it works fine, but I have to set the clientSecret (and maybe also other properties) programatically at startup of the application as the client is registered with the OpenId server also at startup, so the secret is only known after the registration is done.
I did some experimentation with the AuthorizationServerConfigurerAdapter to create an inMemory client, but if it's also added to the filter chain, the application does not start at all:
- Bean method 'userInfoRestTemplateFactory' not loaded because #ConditionalOnMissingBean (types: org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration; SearchStrategy: all) found bean 'org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration'
Any ideas how to set the clientSecret at startup from code instead of hardcoding it in the application.yml?

These properties go to a ResourceServerProperties object. What if you create it yourself:
#Bean
public ResourceServerProperties ouathResource() {
// read from somewhere
return new ResourceServerProperties( id, secret)
}
The presence of this bean could suppress the automatic creation of other beans, in which case they will have to be created manually too.

Related

Setting up Swagger UI with Spring WebFlux

I am currently in the process of setting up a Swagger UI interface for one of the projects I am working on and I am experiencing various issues.
My project uses Spring security to secure the API calls using bearer token authentication, so I need to provide a way of enabling the input dialog so that users can input their bearer token. I have tried everything mentioned in the documentation of OpenAPI regarding this but nothing seems to work in rendering the dialog correctly.
Secondly the project does CSRF checks and even though my application properties include springdoc.swagger-ui.csrf.enabled=true the check fails constantly. I have a dead end and I have no idea how to resolve both problems. For reference my security configuration is the following:
#Bean
public SecurityWebFilterChain securityFilterChain(ServerHttpSecurity security) {
if (securityProperties.isEnabled()) {
return security
.securityMatcher(new NegatedServerWebExchangeMatcher(ServerWebExchangeMatchers.pathMatchers(securityProperties.getIgnoredPaths())))
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(entryPoint)
.and()
.cors()
.and()
.authorizeExchange(spec -> spec.anyExchange().authenticated())
.oauth2ResourceServer(ServerHttpSecurity.OAuth2ResourceServerSpec::jwt)
.build();
}
return security
.securityMatcher(new PathPatternParserServerWebExchangeMatcher("/**"))
.authorizeExchange(spec -> spec.anyExchange().permitAll())
.csrf()
.disable()
.build();
}
We fixed it with our multi-provider (OAuth2 Keycloak for API and Basic Auth for Swagger UI) Webflux security configuration by adding this to every application.yaml:
springdoc:
api-docs:
enabled: true
swagger-ui:
oauth:
client-id: dev
client-secret: 123
scopes: [openid]
csrf:
enabled: false
Key point here is csrf.enabled: false.
Our Keycloak security configuration:
// Keycloak-based JWT authorization for #RestControllers
#Order(1)
#EnableWebFluxSecurity
#EnableReactiveMethodSecurity
public class JwtSecurityConfig {
#Bean("jwt")
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.authorizeExchange()
.pathMatchers("/api/**")
.authenticated()
.and()
.csrf()
.disable()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(grantedAuthoritiesExtractor());
return http.build();
}
private Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>>
grantedAuthoritiesExtractor() {
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(new GrantedAuthoritiesExtractor());
return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
}
}

Disable CSRF / CORS in Spring Boot: Spring security 5.7 and SAML

I am using a Spring Boot application with the latest stable versions of Spring Boot and Sprign Security. I am doing authentication with an ADFS IDP using SAML2.
That works fine for all GET requests. Now I need to use PUT and POST and therfore I'd like to disable csrf.
With this pease of code I tried to disable csrf:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().and().cors().disable();
}
}
But when doing this the complete SAML Authentication gets lost and no Single-Sign-On and so on is performed.
I am using SAML2 by configuration:
spring:
security:
saml2:
relyingparty:
registration:
DemoApp:
entity-id: urn:id:demo-app
identityprovider:
entity-id: "http://adfs.local/adfs/services/trust"
metadata-uri: "https://adfs.local/FederationMetadata/2007-06/FederationMetadata.xml"
singlesignon:
url: "https://adfs.local/adfs/ls"
sign-request: true
How do I disable csrf and keep the SAML2 things working?
WebSecurityConfigurerAdapter is deprecated. Use a SecurityFilterChain Bean to configure HttpSecurity or a WebSecurityCustomizer Bean to configure WebSecurity. Try this
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.csrf().disable()
.cors().disable();
return http.build();
}
The Java configuration below will disable CSRF protection in Spring security 5.7
#Configuration
#EnableWebSecurity
public class WebSecurityConfig {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable());
return http.build();
}
}
For more details follow the link below
https://docs.spring.io/spring-security/reference/servlet/exploits/csrf.html#servlet-csrf-configure-disable

Spring Security pathMatchers with changeable query param

How can I enable access to the endpoint that has the following path:
POST: /allBooks/{code}/details
My SecurityConfig class i Spring Boot app:
#Bean
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http,
RedirectUriValidator redirectUriValidator, JwtService jwtService) {
http.csrf().disable()
.addFilterAt(qorestorLegacyApiKeyFilter(), SecurityWebFiltersOrder.AUTHENTICATION)
.authorizeExchange()
.matchers(new ApiTokenServerWebExchangeMatcher()).permitAll()
.pathMatchers(
"/path1/getAllBooks",
"/path2/getBook",
"/allBooks/**/details" --> MY ENDPOINT
).permitAll()
...
Thanks!

Spring Boot Spring Security 5, OAuth2Login Not working as expected

We have developed our own Authorization Server which we are using for Single Sign on
we developed our client app with the annotation #EnableOAuth2Sso with the following configuration
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.and()
.antMatcher("/**")
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class).authorizeRequests()
.and()
.authorizeRequests()
.antMatchers("/","/login/**","/callback/url/**","/error**","/webjars/**","/favicon.ico**").permitAll()
.anyRequest().authenticated()
.and().formLogin().failureHandler(customAuthenticationFailureHandler)
.and().httpBasic()
.and()
.logout().invalidateHttpSession(true).deleteCookies("JSESSIONID");
it was working fine
but just now I want to use the .oauth2Login() features comes with Spring Security 5 so I changed the annotation to #EnableOAuth2Client from #EnableOAuth2Sso and used the following configuration
#Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.oauth2Login();
}
now while compiling I am getting the following error messages
Description:
Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a bean of type 'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository' that could not be found.
The following candidates were found but could not be injected:
- Bean method 'clientRegistrationRepository' in 'OAuth2ClientRegistrationRepositoryConfiguration' not loaded because OAuth2
Clients Configured Condition registered clients is not available
Action:
Consider revisiting the entries above or defining a bean of type 'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository' in your configuration.
So I changed my application.properties from
security.oauth2.client.auto-approve-scopes=read,write
security.oauth2.client.access-token-uri=http://localhost:8080/xxxxx/oauth/token
security.oauth2.client.user-authorization-uri=http://localhost:8080/xxxxx/oauth/authorize
security.oauth2.client.client-id=xxx
security.oauth2.client.client-secret=secret
security.oauth2.client.pre-established-redirect-uri=http://localhost:11001/xxx/login/oauth2/code
security.oauth2.client.registered-redirect-uri=http://localhost:11001/xxx/login/oauth2/code
security.oauth2.client.useCurrentUri=false
security.oauth2.client.use-current-uri=false
security.oauth2.client.grant-type=authorization_code, refresh_token
to the following
spring.security.oauth2.client.registration.client-id=xxx_client
spring.security.oauth2.client.registration.client-secret=secret
spring.security.oauth2.client.registration.authorization-grant-type=authorization_code,refresh_token
spring.security.oauth2.client.registration.redirect-uri=http://localhost:11001/xxx/login/oauth2/code
spring.security.oauth2.client.registration.scope=read,write
spring.security.oauth2.client.registration.client-name=xxxxx
spring.security.oauth2.client.registration.xxxxx.client-authentication-method=POST
spring.security.oauth2.client.provider.token-uri=http://localhost:8080/xxxxx/oauth/token
spring.security.oauth2.client.provider.authorization-uri=http://localhost:8080/xxxxx/oauth/authorize
spring.security.oauth2.client.provider.user-info-uri=http://localhost:8080/xxxxx/validateLogin
But it displays a welcome page where our authorization server name is shown i.e xxxxx and if I click that link it does not connect to our authorization server.
I have confusion here what is the difference between #EnableOAuth2Sso and #EnableOAuth2Client Why when we use OAuth2Login() we need to change our properties
Is there any good example of using OAuth2Login with Custom Oauth2 provider (instead of google,facebook,okta etc)I searched google but no where any example provided

How to config Spring #EnableOAuth2Sso App with self-signed SSL OAuth2 Server?

My app works well with normal non-SSL OAuth2 Servers. But I dont know how to config client to work with the SSL equivalents. I always get 401 when oauth2 server redirects back to http://localhost:8051/app1/login after success authentication and granting permissions. My App code likes below:
application.yml:
server:
port: 8051
servlet:
contextPath: /app1
security:
oauth2:
client:
clientId: sampleclient
clientSecret: samplepw
accessTokenUri: https://localhost:8668/sso-server/oauth/token
userAuthorizationUri: https://localhost:8668/sso-server/oauth/authorize
tokenName: oauth_token
resource:
userInfoUri: https://localhost:8688/api/me
Application.java
#SpringBootApplication
#EnableOAuth2Sso
public class App1 extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/login", "/error**", "/webjars/**").permitAll()
.anyRequest().authenticated()
.and().logout()
.logoutUrl("/logout")
.logoutSuccessUrl("https://localhost:8668/sso-server/logout")
.invalidateHttpSession(true)
.deleteCookies("client-session", "JSESSIONID")
.permitAll()
.and().csrf().disable()
;
}
public static void main(String[] args) {
SpringApplication.run(App1.class, args);
}
}
OAuth2 Servers work as expected and I can call all oauth APIs that clients need with https schema on Postman, so I think we have nothing to do with them and don't post the code here.

Resources