I am trying to configure an OAuth2 client using Spring Boot. I have the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
And I have added these properties to my application.yaml:
security:
oauth2:
client:
registration:
azure:
client-id: ****
client-secret: ****
authorization-grant-type: client_credentials
provider:
azure:
authorization-uri: https://login.microsoftonline.com/2fdb7e27-9b62-44f7-a0fe-9836eaa1f161/oauth2/v2.0/authorize
token-uri: https://login.microsoftonline.com/2fdb7e27-9b62-44f7-a0fe-9836eaa1f161/oauth2/v2.0/token
jwk-set-uri: https://login.microsoftonline.com/2fdb7e27-9b62-44f7-a0fe-9836eaa1f161/discovery/v2.0/keys
As I understand it from the Spring documentation, this should be enough to auto-configure a ClientRegistrationRepository ("Spring Boot 2.x auto-configuration binds each of the properties under spring.security.oauth2.client.registration.[registrationId] to an instance of ClientRegistration and then composes each of the ClientRegistration instance(s) within a ClientRegistrationRepository. The auto-configuration also registers the ClientRegistrationRepository as a #Bean in the ApplicationContext so that it is available for dependency-injection, if needed by the application.".
I have the following code:
package com.sky.bnc.azurespring
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager
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.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction
import org.springframework.web.reactive.function.client.WebClient
#Configuration
class WebConfiguration {
#Bean
fun authorizedClientManager(clientRegistrationRepository: ClientRegistrationRepository, authorizedClientRepository: OAuth2AuthorizedClientRepository): OAuth2AuthorizedClientManager {
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder
.builder()
.authorizationCode()
.refreshToken()
.clientCredentials()
.build()
val authorizedClientManager = DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
return authorizedClientManager
}
#Bean
fun webClient(authorizedClientManager: OAuth2AuthorizedClientManager): WebClient {
val oauth2Client = ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager)
oauth2Client.setDefaultClientRegistrationId("azure")
return WebClient
.builder()
.apply(oauth2Client.oauth2Configuration())
.build()
}
}
But when I try and run the application I get this error:
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method authorizedClientManager in com.sky.bnc.azurespring.WebConfiguration required a bean of type 'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository' in your configuration.
Process finished with exit code 1
I don't understand what the problem is, I have followed many examples and it seems like it should just be working.
The ClientRegistrationRepository refers to the configuration of the OAuth client in a blocking environment, not reactive. In case you build your application to be fully reactive, consider using the ReactiveClientRegistrationRepository implementation. Spring security project has an example project of how to use that one.
However, you could still mix the reactive and blocking approaches in the same application, although not terribly recommended, there is still a use case for that. For this, you only need to add the spring-boot-starter-web dependency, so that the blocking servlet implementation is added to the classpath. You could watch this talk where this approach is used.
Define the following properties:
azure.activedirectory.client-id=
azure.activedirectory.client-secret=
azure.activedirectory.tenant-id=
azure.activedirectory.authorization-clients.graph.scopes=https://graph.microsoft.com/Analytics.Read,
email
The issue you are facing is due to the configuration in application.yaml file. Please check everything is correct.
Since you are implementing oauth for Azure AD the configuration must look like below,
# Specifies your Active Directory ID:
azure.activedirectory.tenant-id=22222222-2222-2222-2222-222222222222
# Specifies your App Registration's Application ID:
spring.security.oauth2.client.registration.azure.client-id=11111111-1111-1111-1111-1111111111111111
# Specifies your App Registration's secret key:
spring.security.oauth2.client.registration.azure.client-secret=AbCdEfGhIjKlMnOpQrStUvWxYz==
# Specifies the list of Active Directory groups to use for authorization:
azure.activedirectory.user-group.allowed-groups=Users
For complete step-by-step guide please refer here.
Indentation issue,
spring:
security:
ref : click here
Related
I am trying to use limit rate API for a Spring Boot Rest application, with bucket4j based on the following online resource
Please find my configuration below:
Below is maven dependency added to use 4bucketj:
...
<dependency>
<groupId>com.giffing.bucket4j.spring.boot.starter</groupId>
<artifactId>bucket4j-spring-boot-starter</artifactId>
<version>0.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
..
Below is my application.yml config:
spring:
main:
allow-bean-definition-overriding: true
cache:
jcache:
config: classpath:ehcache.xml
bucket4j:
enabled: true
filters:
- cache-name: buckets
url: .*
http-response-body: "{ \"status\": 429, \"error\": \"Too Many Requests\", \"message\": \"You have exhausted your API Request Quota\" }"
rate-limits:
- bandwidths:
- capacity: 2
time: 1
unit: minutes
Below I have added ehcache.xml in path src/main/resources/:
<config xmlns='http://www.ehcache.org/v3'
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jsr107="http://www.ehcache.org/v3/jsr107"
xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">
<cache alias="buckets">
<expiry>
<ttl unit="seconds">3600</ttl>
</expiry>
<heap unit="entries">1000000</heap>
<jsr107:mbeans enable-statistics="true"/>
</cache>
Finally, I have added #EnableCachingin a config class which is being loaded when spring starts.
Based on the config in the application.yml file the API should not accept more than 2 request in one minute and if it is more that two requests, an error should be triggered as stated (http-response-body) in application.yml.
I have deployed the application on my PC and with Postman tool I am able to hit a Rest API more than 10 times within one minute with no error message.
Can anyone please advise why the error message is not triggered, since it should allow only 2 requests and I am sending 10 instead?
I got it working by following this guide from the point 6 onwards, but the only difference i can spot with your implementation is the caching system, so i can guess the problem lies there.
I am trying to use HashiCorp Vault using Spring Cloud Vault on Spring Boot project. I configured my bootstrap.yml file to use app role and secret id to get passwords
bootstrap.yml
spring:
application:
name: pres
cloud:
vault:
authentication: APPROLE
app-role:
role-id: ${role-id}
secret-id: ${secret-id}
role: pres-read
app-role-path: approle
uri: https://hostname:8200
kv:
enabled: true
backend: secret
application-name: pres
profiles:
include: dev
During startup I get the following exception
org.springframework.vault.authentication.VaultLoginException: Cannot login using org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://hostname:8200/v1/auth/approle/login": extension (5) should not be presented in certificate_request; nested exception is javax.net.ssl.SSLHandshakeException: extension (5) should not be presented in certificate_request
I am using spring-cloud-starter-vault-config dependency to access the vault
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-vault-config</artifactId>
<version> 2.2.2.RELEASE</version>
</dependency>
Okay. It looks like this is a Java TLS Bug, hoping java team will fix this in Java 11.0.8.
Update: The issue was fixed in latest Java 11 versions
I am working on enabling spring boot health check using actuator. Since our app is dependent on Spring 1.5.21, so I have to use actuator 1.5.21 release. I read some configurations on their online documentation shows that you can apply the following to only allow "/health" endpoint to expose.
By default, all endpoints except for shutdown are enabled. If you prefer to specifically “opt-in” endpoint enablement you can use the endpoints.enabled property. For example, the following will disable all endpoints except for info:
endpoints.enabled=false
endpoints.info.enabled=true
Since I need to disable all endpoints except "/health" endpoint, so I configured it in application.properties file like below. However, it is not working for me.
endpoints.enabled=false
endpoints.health.enabled=true
Here is the result:
http://localhost:8080/health
{"message":"This endpoint is disabled"}
Environments:
Spring boot: 1.5.21 release
JDK: 1.8
Application: web application
Any thoughts on this? Thanks in advance!
UPDATES:
After I started a new project using the same spring boot 1.5.21.RELEASE, below settings worked.
endpoints.enabled=false
endpoints.health.enabled=true
2020-03-29 19:29:15.541 INFO 9796 --- [ restartedMain] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal)
UPDATE on 3/30:
HOWEVER, when I used it with SDL Tridion 8.5, it stopped working. Any ideas?
<dependency>
<groupId>com.sdl.dxa</groupId>
<artifactId>dxa-common-api</artifactId>
<version>${dxaversion}</version>
</dependency>
<dependency>
<groupId>com.sdl.dxa</groupId>
<artifactId>dxa-common</artifactId>
<version>${dxaversion}</version>
</dependency>
<dependency>
<groupId>com.sdl.dxa</groupId>
<artifactId>dxa-tridion-provider</artifactId>
<version>${dxaversion}</version>
</dependency>
<dependency>
<groupId>com.sdl.dxa.modules</groupId>
<artifactId>dxa-module-core</artifactId>
<version>${dxaversion}</version>
</dependency>
endpoints.enabled=false
endpoints.health.enabled=true
Result:
http://localhost:8080/health
{"message":"This endpoint is disabled"}
No need to use disable. Use only below properties:
management.endpoints.web.exposure.include='health'
I am trying to run a spring cloud config application inside a docker container spawned by ECS. I am having issues correctly setting this up so that the meta data is used to clone the git repo from CodeCommit
I have the following settings
pom.xml dependencies
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws</artifactId>
</dependency>
application.yml
# some other non related settings such as port
spring:
cloud:
config:
server:
git:
uri: https://git-codecommit.eu-central-1.amazonaws.com/v1/repos/<repo name>
skip-ssl-validation: true
cloud:
aws:
credentials:
instance-profile: true
stack:
auto: false
in the docker logs I can find the following
2019-04-25 16:37:54.209 WARN 1 --- [nio-5000-exec-1] .c.s.e.MultipleJGitEnvironmentRepository : Error occured cloning to base directory.
org.eclipse.jgit.api.errors.TransportException: https://git-codecommit.eu-central-1.amazonaws.com/v1/repos/<repo name>: git-upload-pack not permitted on 'https://git-codecommit.eu-central-1.amazonaws.com/v1/repos/<repo name>/'
If I am understanding this correctly; according to the spring cloud config documentation, when you use a CodeCommit git url and don't specify a username and password, it should automatically default to the AWS Credentials Chain, which has instance profile credentials as the final option.
If you provide a username and password with an AWS CodeCommit URI, they must be the AWS accessKeyId and secretAccessKey that provide access to the repository.
If you do not specify a username and password, the accessKeyId and secretAccessKey are retrieved by using the AWS Default Credential Provider Chain.
I guys,
I'm using TomEE 1.6.0 (jax-rs) with a custom Application :
#ApplicationPath("/rest")
public class Whatever extends Application {...}
I do it in order to customize the base path for my REST services and to add a custom provider for every endpoints of this Application :
<?xml version="1.0" encoding="UTF-8"?>
<openejb-jar xmlns="http://www.openejb.org/openejb-jar/1.1">
<pojo-deployment class-name="Whatever">
<properties>
cxf.jaxrs.providers = WhateverProvider
</properties>
</pojo-deployment>
</openejb-jar>
I have a sample JAX-RS endpoint defined like this :
#Path("/whatever")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public class WhateverEndpoint {...}
Everything works fine when deploying in TomEE jax-rs (tomee-maven-plugin:start).
I can call my services on /rest/whatever
The problem is when I want to unit test this service with TomEE Embedded, WhateverEndpoint is not deployed...
The configuration I use for the tests setup (#BeforeClass) is the following :
Properties properties = new Properties();
properties.setProperty(OpenEjbContainer.OPENEJB_EMBEDDED_REMOTABLE, "true");
context = EJBContainer.createEJBContainer(properties).getContext();
I can test the DAO and so on but not the Endpoints...
When I add a #javax.ejb.* annotation like this :
#Singleton
#Path("/whatever")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public class WhateverEndpoint {...}
I have something better in the logs :
INFO - Initializing network services
INFO - REST Application: http://127.0.0.1:4204/web -> org.apache.openejb.server.rest.InternalApplication
INFO - Service URI: http://127.0.0.1:4204/web/whatever -> EJB Whatever
INFO - GET http://127.0.0.1:4204/web/whatever/a -> A a(HttpServletRequest)
INFO - ** Bound Services **
INFO - NAME IP PORT
INFO - httpejbd 127.0.0.1 4204
INFO - admin 127.0.0.1 4200
INFO - ejbd 127.0.0.1 4201
INFO - ejbds 127.0.0.1 4203
What should I do to make it works properly with my custom JAX-RS Application, Path and Provider, just like the TomEE JAX-RS do and without adding ejb annotations ? Should I define additional properties and which one when creating my EJBContainer ? I've see some in the sample applications :
https://github.com/apache/tomee/blob/trunk/examples/rest-on-ejb
https://github.com/apache/tomee/blob/trunk/examples/rest-example
But none of them are working.
Here is my pom.xml :
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0-5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>tomee-embedded</artifactId>
<version>${tomee.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-cxf-rs</artifactId>
<version>${openejb.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>tomee-jaxrs</artifactId>
<version>${tomee.version}</version>
<scope>test</scope>
</dependency>
finally solved it by adding the EJBContainer.APP_NAME property to the properties passed when creating the embedded container :
Properties properties = new Properties();
properties.setProperty(OpenEjbContainer.OPENEJB_EMBEDDED_REMOTABLE, "true");
properties.setProperty(EJBContainer.APP_NAME, "/");
context = EJBContainer.createEJBContainer(properties).getContext();
I had also faced the same issue .I resolved this by adding a class in the TestProxyService annotated with #Singleton and then injecting the resource which I wanted to test.The proxy class would invoke the actual resource class .This
For example
#ApplicationPath("/rest")
public class SampleRestResource{
....methods
}
#Singleton
#ApplicationPath("/rest")
public class TestResource{
#Inject