application.yaml
security:
oauth2:
resourceserver:
jwt:
issuer-uri: <okta issuer uri>
client:
registration:
internal-client: okta
client-id: <My- client id>
client-secret: <My client secret>
authorization-grant-type: client_credentails
scope: internal
provider:
okta:
issuer-uri: <okta issuer uri>
okta:
oauth2:
issuer: <okta issuer uri>
audience: api://default
Above code is my application.yaml file of spring boot application.
package DemoService.ConfigClasses;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
import org.springframework.web.client.RestTemplate;
import DemoService.ConfigClasses.Interceptors.RestTemplateInterceptor;
@Configuration
public class DemoConf {
@Autowired
private ClientRegistrationRepository clientRegistrationRepository;
@Autowired
private OAuth2AuthorizedClientRepository oAuth2AuthorizedClientRepository;
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate= new RestTemplate();
List<ClientHttpRequestInterceptor> interceptor=new ArrayList<>();
interceptor.add(new RestTemplateInterceptor(manager(clientRegistrationRepository,oAuth2AuthorizedClientRepository)));
return restTemplate;
}
@Bean
public OAuth2AuthorizedClientManager manager(ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository auth2AuthorizedClientRepository) {
OAuth2AuthorizedClientProvider provider=OAuth2AuthorizedClientProviderBuilder.builder().clientCredentials().build();
DefaultOAuth2AuthorizedClientManager defaultOAuth2AuthorizedClientManager=new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository, auth2AuthorizedClientRepository);
defaultOAuth2AuthorizedClientManager.setAuthorizedClientProvider(provider);
return defaultOAuth2AuthorizedClientManager;
}
}
It is my configuration class
package DemoService.ConfigClasses;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.server.SecurityWebFilterChain;
@Configuration
@EnableWebFluxSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
@Bean
public SecurityWebFilterChain securityFilterChain(ServerHttpSecurity httpSecurity) {
httpSecurity.authorizeExchange()
.anyExchange()
.authenticated()
.and()
.oauth2ResourceServer()
.jwt();
return httpSecurity.build();
}
}
web security config class
package DemoService.ConfigClasses.Interceptors;
import java.io.IOException;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
public class RestTemplateInterceptor implements ClientHttpRequestInterceptor{
private OAuth2AuthorizedClientManager manager;
public RestTemplateInterceptor(OAuth2AuthorizedClientManager manager) {
super();
this.manager = manager;
}
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
String token=manager.authorize(OAuth2AuthorizeRequest.withClientRegistrationId("internal-client").principal("internal").build()).getAccessToken().getTokenValue();
request.getHeaders().add("Authorization", "Bearer "+token);
return execution.execute(request, body);
}
}
Rest Template interceptor class
I am trying to create a internal service and add spring security with okta oauth2 for securing the service. I am implementing token based authorization for this service. While starting the service the following error is showing:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.1.9)
2024-03-24T12:26:08.837+05:30 INFO 11772 --- [ main] DemoService.DemoServApplication : Starting DemoServApplication using Java 17.0.3 with PID 11772 (C:\Users\lenovo\Downloads\DemoServ\DemoServ\target\classes started by lenovo in C:\Users\lenovo\Downloads\DemoServ\DemoServ)
2024-03-24T12:26:08.843+05:30 INFO 11772 --- [ main] DemoService.DemoServApplication : No active profile set, falling back to 1 default profile: "default"
2024-03-24T12:26:10.280+05:30 WARN 11772 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration]: Error processing condition on org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientRegistrationRepositoryConfiguration
2024-03-24T12:26:10.314+05:30 INFO 11772 --- [ main] .s.b.a.l.ConditionEvaluationReportLogger :
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2024-03-24T12:26:10.413+05:30 ERROR 11772 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to bind properties under 'spring.security.oauth2.client.registration.internal-client' to org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties$Registration:
Reason: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties$Registration]
Action:
Update your application's configuration
You have at least two mistakes in your properties:
registrationproperty: theregistration-idyou later reference asinternal-clientregistration, you reference the provider withinternal-client(instead ofprovider)The cause for your current exception is that in
org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties,registrationis defined as aMap<String, Registration>(where the key is the registration-id), not as just oneRegistration.Try: