-
Notifications
You must be signed in to change notification settings - Fork 81
feat: Create OAuth client from config & Bump version to 0.2.1 #29
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package com.coze.openapi.client.auth; | ||
|
||
import java.io.FileInputStream; | ||
import java.io.FileNotFoundException; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.fasterxml.jackson.core.exc.StreamReadException; | ||
import com.fasterxml.jackson.databind.DatabindException; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Data; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Data | ||
@Builder | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class OAuthConfig { | ||
@JsonProperty("client_type") | ||
private String clientType; | ||
|
||
@JsonProperty("client_id") | ||
private String clientId; | ||
|
||
@JsonProperty("client_secret") | ||
private String clientSecret; | ||
|
||
@JsonProperty("private_key") | ||
private String privateKey; | ||
|
||
@JsonProperty("public_key_id") | ||
private String publicKeyId; | ||
|
||
@JsonProperty("coze_api_base") | ||
private String cozeApiBase; | ||
|
||
@JsonProperty("coze_www_base") | ||
private String cozeWwwBase; | ||
|
||
public static OAuthConfig load(String configFilePath) { | ||
return doLoad(configFilePath); | ||
} | ||
|
||
private static OAuthConfig doLoad(String configFilePath) { | ||
try (InputStream inputStream = new FileInputStream(configFilePath)) { | ||
ObjectMapper mapper = new ObjectMapper(); | ||
mapper.findAndRegisterModules(); | ||
|
||
return mapper.readValue(inputStream, OAuthConfig.class); | ||
|
||
} catch (FileNotFoundException e) { | ||
throw new RuntimeException("Config file not found: " + configFilePath, e); | ||
} catch (StreamReadException e) { | ||
throw new RuntimeException("JSON file format error: " + e.getMessage(), e); | ||
} catch (DatabindException e) { | ||
throw new RuntimeException("Failed to map config file to object: " + e.getMessage(), e); | ||
} catch (IOException e) { | ||
throw new RuntimeException("I/O error while reading config file: " + e.getMessage(), e); | ||
} | ||
} | ||
Comment on lines
+48
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance security and error handling in configuration loading. While the error handling is good, there are several security considerations for loading sensitive configuration:
Consider these improvements: private static OAuthConfig doLoad(String configFilePath) {
+ File configFile = new File(configFilePath);
+ if (!configFile.exists() || !configFile.canRead()) {
+ throw new RuntimeException("Config file is not accessible");
+ }
try (InputStream inputStream = new FileInputStream(configFilePath)) {
ObjectMapper mapper = new ObjectMapper();
mapper.findAndRegisterModules();
- return mapper.readValue(inputStream, OAuthConfig.class);
+ OAuthConfig config = mapper.readValue(inputStream, OAuthConfig.class);
+ config.validate(); // Add validation call
+ return config;
} catch (FileNotFoundException e) {
- throw new RuntimeException("Config file not found: " + configFilePath, e);
+ throw new RuntimeException("Config file not found", e);
} catch (StreamReadException e) {
throw new RuntimeException("JSON file format error: " + e.getMessage(), e);
} catch (DatabindException e) {
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,14 @@ | |
super(builder); | ||
} | ||
|
||
public static DeviceOAuthClient loadFromFile(String configFilePath) { | ||
OAuthConfig config = OAuthConfig.load(configFilePath); | ||
return new DeviceOAuthClient.DeviceOAuthBuilder() | ||
.clientID(config.getClientId()) | ||
.baseURL(config.getCozeApiBase()) | ||
.build(); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Review comment is accurate - shared test utilities needed and loadFromFile requires test coverage The codebase analysis confirms:
🔗 Analysis chainConsider creating shared test utilities for loadFromFile methods. Multiple OAuth clients now implement similar
Example test utility class: public class OAuthTestUtils {
public static String createTestConfig(String clientType, String clientId) {
return String.format("""
{
"client_type": "%s",
"client_id": "%s",
"coze_api_base": "https://api.test"
}
""", clientType, clientId);
}
public static File writeTestConfig(String config) throws IOException {
File tempFile = File.createTempFile("test-oauth-config", ".json");
tempFile.deleteOnExit();
Files.writeString(tempFile.toPath(), config);
return tempFile;
}
} 🏁 Scripts executedThe following scripts were executed for the analysis: Error: No shell scripts found Script: #!/bin/bash
# Find OAuth client implementations
ast-grep --pattern 'class $_OAuthClient {
$$$
}'
# Find test files related to OAuth
rg -l "OAuthClient.*Test"
# Look for existing loadFromFile implementations and tests
rg -l "loadFromFile|OAuthTestUtils"
Length of output: 686 Script: #!/bin/bash
# Check test implementations for loadFromFile
rg "loadFromFile" api/src/test/java/com/coze/openapi/service/auth/*Test.java -B 1 -A 3
# Look for existing test utilities or helper methods
rg "class|void.*test" api/src/test/java/com/coze/openapi/service/auth/*Test.java
Length of output: 5449 🧰 Tools🪛 GitHub Check: codecov/patch[warning] 19-23: api/src/main/java/com/coze/openapi/service/auth/DeviceOAuthClient.java#L19-L23 |
||
|
||
private static final Logger logger = AuthLogFactory.getLogger(); | ||
|
||
public DeviceAuthResp getDeviceCode() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ | |
|
||
import com.coze.openapi.client.auth.GetAccessTokenReq; | ||
import com.coze.openapi.client.auth.GrantType; | ||
import com.coze.openapi.client.auth.OAuthConfig; | ||
import com.coze.openapi.client.auth.OAuthToken; | ||
import com.coze.openapi.client.auth.scope.Scope; | ||
import com.coze.openapi.service.utils.Utils; | ||
|
@@ -31,6 +32,16 @@ | |
this.ttl = builder.ttl; | ||
} | ||
|
||
public static JWTOAuthClient loadFromFile(String configFilePath) throws Exception { | ||
OAuthConfig config = OAuthConfig.load(configFilePath); | ||
return new JWTOAuthClient.JWTOAuthBuilder() | ||
.privateKey(config.getPrivateKey()) | ||
.publicKey(config.getPublicKeyId()) | ||
.clientID(config.getClientId()) | ||
.baseURL(config.getCozeApiBase()) | ||
.build(); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Improve error handling and exception specificity. The method needs better error handling and should use more specific exceptions.
-public static JWTOAuthClient loadFromFile(String configFilePath) throws Exception {
+public static JWTOAuthClient loadFromFile(String configFilePath) throws IOException, InvalidKeyException {
+ if (configFilePath == null || configFilePath.trim().isEmpty()) {
+ throw new IllegalArgumentException("Config file path cannot be null or empty");
+ }
OAuthConfig config = OAuthConfig.load(configFilePath);
+ if (config == null) {
+ throw new IllegalStateException("Failed to load OAuth configuration from file");
+ }
+ if (config.getPrivateKey() == null || config.getPublicKeyId() == null) {
+ throw new IllegalStateException("Missing required JWT configuration");
+ }
return new JWTOAuthClient.JWTOAuthBuilder()
.privateKey(config.getPrivateKey())
.publicKey(config.getPublicKeyId())
.clientID(config.getClientId())
.baseURL(config.getCozeApiBase())
.build();
}
#!/bin/bash
# Check for existing test files
fd -e java -p "test.*JWTOAuthClient.*Test\.java$"
# Look for test methods related to loadFromFile
rg -l "test.*[Ll]oad.*[Ff]ile.*JWTOAuthClient" -t java 🧰 Tools🪛 GitHub Check: codecov/patch[warning] 36-42: api/src/main/java/com/coze/openapi/service/auth/JWTOAuthClient.java#L36-L42 |
||
|
||
@Override | ||
public OAuthToken refreshToken(String refreshToken) { | ||
return null; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,10 +8,7 @@ | |
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import com.coze.openapi.client.auth.GetAccessTokenReq; | ||
import com.coze.openapi.client.auth.GetPKCEAuthURLResp; | ||
import com.coze.openapi.client.auth.GrantType; | ||
import com.coze.openapi.client.auth.OAuthToken; | ||
import com.coze.openapi.client.auth.*; | ||
import com.coze.openapi.service.utils.Utils; | ||
|
||
import lombok.Getter; | ||
|
@@ -36,6 +33,14 @@ | |
super(builder); | ||
} | ||
|
||
public static PKCEOAuthClient loadFromFile(String configFilePath) { | ||
OAuthConfig config = OAuthConfig.load(configFilePath); | ||
return new PKCEOAuthClient.PKCEOAuthBuilder() | ||
.clientID(config.getClientId()) | ||
.baseURL(config.getCozeApiBase()) | ||
.build(); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Add error handling and test coverage for loadFromFile method The verification confirms the need for both error handling and test coverage. The method requires:
The original review comment's suggested changes are appropriate, but should also include validation for required config fields: public static PKCEOAuthClient loadFromFile(String configFilePath) {
+ if (configFilePath == null || configFilePath.trim().isEmpty()) {
+ throw new IllegalArgumentException("Config file path cannot be null or empty");
+ }
OAuthConfig config = OAuthConfig.load(configFilePath);
+ if (config == null) {
+ throw new IllegalStateException("Failed to load OAuth configuration from file");
+ }
+ String clientId = config.getClientId();
+ String baseUrl = config.getCozeApiBase();
+ if (clientId == null || clientId.trim().isEmpty() || baseUrl == null || baseUrl.trim().isEmpty()) {
+ throw new IllegalStateException("Config must contain non-empty clientId and baseURL");
+ }
return new PKCEOAuthClient.PKCEOAuthBuilder()
.clientID(config.getClientId())
.baseURL(config.getCozeApiBase())
.build();
} 🔗 Analysis chainAdd error handling and test coverage for the loadFromFile method. The method should handle potential file-related exceptions and include comprehensive test coverage.
public static PKCEOAuthClient loadFromFile(String configFilePath) {
+ if (configFilePath == null || configFilePath.trim().isEmpty()) {
+ throw new IllegalArgumentException("Config file path cannot be null or empty");
+ }
OAuthConfig config = OAuthConfig.load(configFilePath);
+ if (config == null) {
+ throw new IllegalStateException("Failed to load OAuth configuration from file");
+ }
return new PKCEOAuthClient.PKCEOAuthBuilder()
.clientID(config.getClientId())
.baseURL(config.getCozeApiBase())
.build();
}
🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Check for existing test files
fd -e java -p "test.*PKCEOAuthClient.*Test\.java$"
# Look for test methods related to loadFromFile
rg -l "test.*[Ll]oad.*[Ff]ile.*PKCEOAuthClient" -t java
Length of output: 183 Script: #!/bin/bash
# Check test file content
cat api/src/test/java/com/coze/openapi/service/auth/PKCEOAuthClientTest.java
# Check OAuthConfig implementation
ast-grep --pattern 'class OAuthConfig {
$$$
static OAuthConfig load($_) {
$$$
}
$$$
}'
Length of output: 6529 🧰 Tools🪛 GitHub Check: codecov/patch[warning] 37-41: api/src/main/java/com/coze/openapi/service/auth/PKCEOAuthClient.java#L37-L41 |
||
|
||
public GetPKCEAuthURLResp genOAuthURL(@NotNull String redirectURI, String state) { | ||
return genOAuthURL(redirectURI, state, CodeChallengeMethod.Plain); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding validation for required fields.
The configuration class contains multiple fields but lacks validation. Some fields might be required depending on the OAuth flow type (e.g.,
clientId
is always required, whileprivateKey
is only needed for JWT flow).Consider adding a validation method: