Skip to content

Conversation

@MrBurtyyy
Copy link
Collaborator

…thentication tokens via API

@MrBurtyyy MrBurtyyy force-pushed the SDK-2771 branch 2 times, most recently from 9d1586b to d994ecd Compare December 11, 2025 13:58
Copy link
Collaborator

@pn-santos pn-santos left a comment

Choose a reason for hiding this comment

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

I'm not that familiar with the current practices in the SDK nor any stylistic conventions in place so apologies in advance if any of the comments are out-of-sync with how stuff is done in the SDKs.

Also, given I'm not really involved with the SDKs don't take the comments as blockers. I'm not going to explicitly approve, I'll leave that to someone more attuned to the SDK code base to take that responsibility, but I don't see anything functional that would be a reason to hold it up.

private final SignedJwtGenerator signedJwtGenerator;

private final String authApiUrl;
private final ObjectMapper objectMapper;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is the ObjectMapper being injected/exposed?

The CreateAuthenticationTokenResponse is defined by this module, shouldn't the ObjectMapper (and it's config) also be owned/defined by this module? What would be the point of the client providing their own instance config if they do not control the annotations/layout of CreateAuthenticationTokenResponse?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We don't expose the ObjectMapper to the Relying Business, but it's done this way (and in other places in the SDK) to make testing with mocks easier in the AuthenticationTokenGenerator

Comment on lines 149 to 172
ObjectMapper objectMapper = new ObjectMapper()
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Copy link
Collaborator

Choose a reason for hiding this comment

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

If we do not expose the ObjectMapper then there's no point in making it an instance var. It should be declared as a static final var of AuthenticationTokenGenerator

this.signedJwtGenerator = signedJwtGenerator;
this.objectMapper = objectMapper;

authApiUrl = System.getProperty(Properties.PROPERTY_YOTI_AUTH_URL, Properties.DEFAULT_YOTI_AUTH_URL);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This class is the sole user of this Properties class... why not simply declare those values as constants here? i.e.

private static final String YOTI_AUTH_URL_KEY = "yoti.auth.url";

(...)

authApiUrl = System.getProperty(YOTI_AUTH_URL_KEY, "https://auth.api.yoti.com/v1/oauth/token");

and get rid of Properties altogether?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We have public properties in here, so the YOTI_AUTH_URL_KEY property can be accessed if we want to override the URL without knowing the actual key needed (like we do in the other modules).

Not sure if we want to change this, @bucky-boy what do you think?

String jwts = signedJwtGenerator.create(sdkId, keyPair, jwtIdSupplier, authApiUrl);

Map<String, String> formParams = new HashMap<>(DEFAULT_FORM_VALUES);
formParams.put("scope", String.join(" ", scopes));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this list be checked for null or empty string?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed 👍

* @throws IOException
*/
public CreateAuthenticationTokenResponse generate(List<String> scopes) throws ResourceException, IOException {
String jwts = signedJwtGenerator.create(sdkId, keyPair, jwtIdSupplier, authApiUrl);
Copy link
Collaborator

Choose a reason for hiding this comment

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

can't this be inlined?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed 👍

Comment on lines 47 to 51
try {
return encode(entry.getKey()) + "=" + encode(entry.getValue());
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

If doing the try/catch to turn it into a runtime exception it would probably make more sense to do it within the encode method.

Copy link
Collaborator

@irotech irotech left a comment

Choose a reason for hiding this comment

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

only not blocking minor comments

formParams.put("grant_type", "client_credentials");
formParams.put("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer");
formParams.put("scope", String.join(" ", scopes));
formParams.put("client_assertion", jwts);
Copy link
Collaborator

Choose a reason for hiding this comment

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

why having a var if used once?

Suggested change
formParams.put("client_assertion", jwts);
formParams.put("client_assertion", createSignedJwt(sdkId, keyPair, jwtIdSupplier, authApiUrl));

connection.setRequestMethod(method);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", Integer.toString(postData.length));
connection.setRequestProperty("charset", "utf-8");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
connection.setRequestProperty("charset", "utf-8");
connection.setRequestProperty("charset", StandardCharsets.UTF_8);

+ "vd67J8cdh1v6d3m0xrT639BIh7FIZjVIg3B8ERBmIH1oFn05BQFYlCEUG7Cl1KV2\n"
+ "/VIBAoGAYin6eHFtBXpPRMddTt4lLOFtpBb9gGp9DxKGAsH0pdfQYgZHz0xKtxrq\n"
+ "6l+d2M9sRhtisxw8YevPFWEVtcUWxz+qESM+wzUMrmWSuwwxXyVgjR4rC8untfPM\n"
+ "laDBX8dDBwBQ3i0FhvuGR/LEjHWr9hj00faKROHOLFim6wbRIkg=\n" //
Copy link
Collaborator

Choose a reason for hiding this comment

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

is this empty comment, "//", in there for any reason?

@sonarqubecloud
Copy link

@MrBurtyyy MrBurtyyy merged commit 428ae21 into DEVELOPMENT Dec 16, 2025
9 checks passed
@MrBurtyyy MrBurtyyy deleted the SDK-2771 branch December 16, 2025 15:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants