Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OAuth2 feature for Config Clients #2363

Closed
wants to merge 8 commits into from
Closed

Add OAuth2 feature for Config Clients #2363

wants to merge 8 commits into from

Conversation

cobar79
Copy link

@cobar79 cobar79 commented Dec 7, 2023

  • When OAuth2 token property present, call IDP for Bearer Token.
  • Add Bearer Token header on config server resource requests.
  • Replace deprecated Base64Utils

spring-builds and others added 3 commits November 30, 2023 13:48
When OAuth2 token property present, call IDP for Bearer Token.
Add Bearer Token header on config server resource requests.
gh-2348
- When OAuth2 token property present, Call IDP and obtain Bearer token.
- Add Bearer token to config server requests.
- Replaced deprecated Base64Utils.
gh-2348
@@ -21,6 +21,11 @@
]]>
</description>

<properties>
<jasypt-spring-boot.version>3.0.5</jasypt-spring-boot.version>
<okhttp.version>4.11.0</okhttp.version>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the boot-managed version?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spencergibb
I attempted "boot managed" JCE but had problems with cipher in the client properties. There is so little information on JCE in a Spring Boot project and tons of examples for JASYPT that I went with the common encryption that was easier to set up and manage.

I can revisit it if I can get better documentation of getting it working the the config client.

client-secret: '{cipher}e4b1f56fb017319eb959595343d0e4f5a742e975860b723433f90e8f3e869a379db7c756e0537273aebf72cc3a4c3d48caf4955889c5e22be588523b0a88b5c8'

    Property: spring.cloud.config.client-secret
    Value: "{cipher}e4b1f56fb017319eb959595343d0e4f5a742e975860b723433f90e8f3e869a379db7c756e0537273aebf72cc3a4c3d48caf4955889c5e22be588523b0a88b5c8"
    Origin: URL [file:config/application-local.yml] - 73:22
    Reason: java.lang.UnsupportedOperationException: No decryption for FailsafeTextEncryptor. Did you configure the keystore correctly?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does that have to do with okhttp?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mock server for IDP testing. See ConfigClientRequestTemplateFactoryTest

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, then back to my original comment, why can't the boot managed version of ok http be used?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, looking back I didn't specify okhttp as the one to boot manage.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I am on the same page, I take "boot managed version of ok http" to be the org.springframework.test.web.client.MockRestServiceServer?

Since I have never used it, I may need help getting it to work. My first attempt failed with it timing out and not responding. My guess is because it has to be bound to the same RestTemplate making the call?
If so, that is going to be the chicken and the egg dilemma since I am testing the Factory method that creates the Template.

mockRestServiceServer = MockRestServiceServer.bindTo(new RestTemplate()).build();
mockRestServiceServer.expect(requestTo(new URI(properties.getTokenUri())))
	.andExpect(method(HttpMethod.POST))
	.andExpect(content().contentType(MediaType.APPLICATION_FORM_URLENCODED))
	.andRespond(withStatus(HttpStatus.OK)
		.contentType(MediaType.APPLICATION_JSON)
		.body(TOKEN_RESPONSE));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-dependencies/3.2.0/spring-boot-dependencies-3.2.0.pom

<okhttp.version>4.12.0</okhttp.version>

You should just be able to remove the version property and the version tag.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Did not know it was included. Will have to update all my microservices.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It didn't used to be, it was added at some point. We had the same thing in spring cloud

@@ -117,6 +117,47 @@ public class ConfigClientProperties {
*/
private String password;

/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be cleaner to place these properties in a subclass called oauth2 so we would use spring.cloud.config.oauth2.*

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. See ConfigClientOauth2Properties

@@ -67,6 +82,17 @@ public ConfigClientProperties getProperties() {
return this.properties;
}

public SimplePBEByteEncryptor buildEncryptor() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be some kind of bean that the user can override

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I embedded it into the ConfigClientProperties. It got real messy trying to pass it into the pass additional configurations into the ConfigClientRequestTemplateFactory constructor.

restTemplate.setInterceptors(interceptors);
}
else {
requestTemplateFactory.addAuthorizationToken(headers, username, password);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if this token expires?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, the Spring Security Framework handles refreshing of the token. I am still trying to set up a test for the actuator monitor endpoint to see if the security framework will append the token to the config server request to pull new updates. In theory it should work since the Spring Context is fully boot strapped.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK please let us know when you have tested that

Copy link
Author

@cobar79 cobar79 Dec 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the redaction. I was looking at postman response and failed to review the client logs.

09:40:07.119 [http-nio-9440-exec-8] WARN  o.s.c.c.c.ConfigServerConfigDataLoader - Could not locate PropertySource ([ConfigServerConfigDataResource@6cca236b uris = array<String>['http://localhost:8888/config-server'], optional = true, profiles = 'local']): 401 : "{"path":"/config-server/gdelt-ingest/local","message":"An error occurred while attempting to decode the Jwt: Jwt expired at 2023-12-19T15:50:42Z","propertyPath":null,"propertyValue":null,"timestamp":"2023-12-19 09:40:07.086-07"}"

Copy link
Author

@cobar79 cobar79 Dec 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ryanjbaxter @spencergibb
Is it ok to bring in a JWT Decoder to check expiration?

		<dependency>
			<groupId>com.auth0</groupId>
			<artifactId>java-jwt</artifactId>
			<version>4.4.0</version>
		</dependency>

restTemplate.setInterceptors(interceptors);
}
else {
requestTemplateFactory.addAuthorizationToken(headers, username, password);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK please let us know when you have tested that

@ryanjbaxter
Copy link
Contributor

We will also need to add some documentation for this

@cobar79
Copy link
Author

cobar79 commented Dec 19, 2023

@ryanjbaxter Can you point me to the repo that contains the Spring Cloud Config that I will need to update?

@spencergibb
Copy link
Member

@cobar79
Copy link
Author

cobar79 commented Dec 20, 2023

Docs live here https://github.com/spring-cloud/spring-cloud-config/tree/main/docs/modules/ROOT/pages

Nervous that I didn't fork correctly. I am in the 4.0.5-SNAPSHOT and I do not see the modules directory under the docs module?
I only see src/main/asciidoc folder?

Also curious how this will go since I see a 4.1.0 release of spring-cloud-starter-config on Dec 6th in Maven Central?

@ryanjbaxter
Copy link
Contributor

Yes this will actually have to go in a feature release, most likely 4.2.x. That said its best to use main.

@cobar79
Copy link
Author

cobar79 commented Dec 21, 2023

Thanks @ryanjbaxter
Sorry, I am very new to the forking to another repo and merging back.

Can I sync the current fork in my repo or do I need to:

  • Close this PR
  • Delete the fork in my repo
  • Create a new fork into my repo from main which shows 4.1.1-SNAPSHOT.
  • Create the feature branch off main in my repo.
  • Move code to new fork.
  • Then cut new PR back into main on this repo.

@ryanjbaxter
Copy link
Contributor

Yes I think so

@cobar79 cobar79 closed this Dec 22, 2023
@cobar79
Copy link
Author

cobar79 commented Dec 22, 2023

Moving to version 4.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Provide support for OAuth2 in Spring Config Client.
5 participants