Skip to content

Commit

Permalink
Add OAuth2 support for config clients.
Browse files Browse the repository at this point in the history
  • Loading branch information
Bruce Randall committed Dec 22, 2023
1 parent 61909a3 commit d188da9
Show file tree
Hide file tree
Showing 13 changed files with 943 additions and 13 deletions.
74 changes: 74 additions & 0 deletions docs/modules/ROOT/pages/client.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,80 @@ spring:
----

If the config server requires OAuth2 JWT security, clients can provide the following combinations of properties.

For client credentials grant type:
----
spring:
cloud:
config:
oauth2:
token-uri: http://localhost:9080/realms/${realm}/protocol/openid-connect/token
client-id: oauth2-client
client-secret: oauth2-client-secret
grant-type: client_credentials
----

For password credentials grant type you can include username and password
----
spring:
cloud:
config:
oauth2:
token-uri: http://localhost:9080/realms/${realm}/protocol/openid-connect/token
client-id: oauth2-client
client-secret: oauth2-client-secret
grant-type: client_credentials
username: actuator-user
password: actuator-secret
----

Additionally, client-secret and password can be encrypted with http://www.jasypt.org/index.html[Jasypt].
----
spring:
cloud:
config:
encryptor:
encryptor-algorithm: PBEWITHHMACSHA512ANDAES_256
encryptor-iterations: 1000
----
The Jasypt encryption password will need to be passed as a system property. Examples:
----
-Djasypt.encryptor.password=my-favorite-password
----
It can also be done in the Spring Application.
----
import org.springframework.cloud.config.client.EncryptorConfig;
@EnableEncryptableProperties //enable Jayspt encryption
@SpringBootApplication
public class MyBootApplication {
public static void main(String[] args) {
System.setProperty(EncryptorConfig.ENCRYPTOR_SYSTEM_PROPERTY, "my-favorite-password");
//OR
System.setProperty("jasypt.encryptor.password", "my-favorite-password");
SpringApplication.run(MyBootApplication.class, args);
}
}
----
Example of OAuth2 properties with encryption.
----
spring:
cloud:
config:
oauth2:
token-uri: http://localhost:9080/realms/${realm}/protocol/openid-connect/token
client-id: oauth2-client
client-secret: ENC(WzBZMDgGCSqGSIb3DQEFDDArBBSNIl7Wk7QOYfVUgZwVvAt9kXw8QgICEAACASAwDAYIKoZIhvcNAgsFADAdBglghk=)
grant-type: client_credentials
username: actuator-user
password: ENC(7QOYfVUgZwVvAt9kXw8QgICEAACASAwDAYIKoZIhvcNAgsFADAdBglghkWzBZMDgGCSqGSIb3DQEFDDArBBSNIl7Wk==)
encryptor:
encryptor-algorithm: PBEWITHHMACSHA512ANDAES_256
encryptor-iterations: 1000
----

If config server requires client side TLS certificate, you can configure client side TLS certificate and trust store via properties, as shown in following example:

[source,yaml]
Expand Down
25 changes: 25 additions & 0 deletions spring-cloud-config-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
]]>
</description>

<properties>
<jasypt-spring-boot.version>3.0.5</jasypt-spring-boot.version>
<java-jwt.version>4.4.0</java-jwt.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down Expand Up @@ -80,6 +85,16 @@
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot</artifactId>
<version>${jasypt-spring-boot.version}</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${java-jwt.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand All @@ -95,6 +110,16 @@
<artifactId>spring-cloud-test-support</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.cloud.config.client;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
* @author Bruce Randall
*
*/
public class AccessTokenResponse {

@JsonProperty("access_token")
private String accessToken;

@JsonProperty("token_type")
private String tokenType;

public String getAccessToken() {
return accessToken;
}

public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}

public String getTokenType() {
return tokenType;
}

public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}

public String getBearerHeader() {
return getTokenType() + " " + getAccessToken();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.cloud.config.client;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
* @author Bruce Randall
*
*/
@ConfigurationProperties(ConfigClientOAuth2Properties.PREFIX)
public class ConfigClientOAuth2Properties {

/**
* Prefix for Spring Cloud Config properties.
*/
public static final String PREFIX = "spring.cloud.config.oauth2";

/**
* The OAuth2 token URI of the IDP issuing JWT tokens. When present enables OAuth2
* client calls.
*/
private String tokenUri;

/**
* The OAuth2 grant type (client_credentials, password).
*/
private String grantType;

/**
* The OAuth2 client id should it be needed in JWT token request.
*/
private String clientId;

/**
* The OAuth2 client secret should it be needed in JWT token request.
*/
private String clientSecret;

/**
* The OAuth2 username to use when contacting the IDP.
*/
private String oauthUsername;

/**
* The OAuth2 user password to use when contacting the IDP.
*/
private String oauthPassword;

public String getTokenUri() {
return tokenUri;
}

public void setTokenUri(String tokenUri) {
this.tokenUri = tokenUri;
}

public String getGrantType() {
return grantType;
}

public void setGrantType(String grantType) {
this.grantType = grantType;
}

public String getClientId() {
return clientId;
}

public void setClientId(String clientId) {
this.clientId = clientId;
}

public String getClientSecret() {
return clientSecret;
}

public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}

public String getOauthUsername() {
return oauthUsername;
}

public void setOauthUsername(String oauthUsername) {
this.oauthUsername = oauthUsername;
}

public String getOauthPassword() {
return oauthPassword;
}

public void setOauthPassword(String oauthPassword) {
this.oauthPassword = oauthPassword;
}

@Override
public String toString() {
return "ConfigClientOAuth2Properties{" + "tokenUri='" + tokenUri + '\'' + ", grantType='" + grantType + '\''
+ ", clientId='" + clientId + '\'' + ", oauthUsername='" + oauthUsername + '\'' + '}';
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,16 @@ public class ConfigClientProperties {
*/
private String password;

/**
* OAUTH2 Properties.
*/
private ConfigClientOAuth2Properties configClientOAuth2Properties;

/**
* Encryption properties.
*/
private EncryptorConfig encryptorConfig;

/**
* The URI of the remote server (default http://localhost:8888).
*/
Expand Down Expand Up @@ -248,6 +258,22 @@ public void setPassword(String password) {
this.password = password;
}

public ConfigClientOAuth2Properties getConfigClientOAuth2Properties() {
return configClientOAuth2Properties;
}

public void setConfigClientOAuth2Properties(ConfigClientOAuth2Properties configClientOAuth2Properties) {
this.configClientOAuth2Properties = configClientOAuth2Properties;
}

public EncryptorConfig getEncryptorConfig() {
return encryptorConfig;
}

public void setEncryptorConfig(EncryptorConfig encryptorConfig) {
this.encryptorConfig = encryptorConfig;
}

public Credentials getCredentials(int index) {
return extractCredentials(index);
}
Expand Down
Loading

0 comments on commit d188da9

Please sign in to comment.