You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While we realize this is an issue, the desired solution is still in discussion within the team. Please do not pick up this ticket until the team has agreed upon and finalized an interface.
The Java SDK currently only supports the client_credentials OAuth2 grant with client_secret for authentication against the token endpoint. Some enterprise environments have security policies that forbid the use of shared secrets (client_secret) for machine-to-machine authentication and instead require JWT-based client assertions (See RFC 7523 (Section 2.2)).
Users in these environments are currently unable to use the Java SDK's built-in credential management at all, they're forced to either manage token acquisition entirely outside the SDK or forego using the SDK.
Describe the ideal solution
Add support for JWT client assertions as an alternative client authentication method on the existing client_credentials grant, consistent with the approach we've taken in the JS SDK (PR #228).
In some enterprise environments, the key cannot be exported - e.g. KMS, Vault..
If you need to rotate the key, you need to rebuild the configuration
We had to add a dependency on the jose library, even though most consumers of the SDK do not need it
It is common to load keys from a keystore, rather than passing them as strings
Proposed interface
We should replacing the PEM string with a provider interface — a callback that returns a signed JWT assertion on demand. The SDK continues to own the token exchange lifecycle (caching, refresh, retry) but delegates assertion creation entirely to the caller.
Note
Below you'll see references to Scopes as defined by RFC 6749. This is not strictly related to Private Key JWT, but is an adjacent feature supported by several other SDKs that we need to add
public class ClientCredentialsConfig {
// Shared fields
private String clientId;
private String apiTokenIssuer;
private String apiAudience; // Optional. This is required by issuers such as Auth0.
private Set<String> scopes; // Optional. As defined by RFC 6749.
private Map<String, String> customClaims; // Optional custom claims.
// Existing client_secret authentication
private String clientSecret;
// JWT client assertion authentication
private ClientAssertionProvider clientAssertionProvider;
}
Users can acquire tokens outside the SDK and pass them via the API_TOKEN credential method. However, this means the user must handle token refresh/expiry themselves, losing the built-in token lifecycle management we provide through the SDK.
This should also be considered for the other language SDKs (Go, .NET, Python) for consistency.
This pattern should be backported to the JS SDK and the use of the jose library deprecated so we can remove it later as folks transition
We are adding scopes here, which has been implemented in SDKs such as Go, but not yet in JS
Original request:
Author: Nicholas on CNCF Slack (thread)
Oauth2 Flow in OpenFga Java Client SDK.
I can see in the source code of the SDK the implemented Oauth2 flow is "Client Credentials".
My company forbid this specific flow.
They allow "Jwt As Authorization Code Grant" between two backend components.
Warning
While we realize this is an issue, the desired solution is still in discussion within the team. Please do not pick up this ticket until the team has agreed upon and finalized an interface.
Checklist
Describe the problem you'd like to have solved
The Java SDK currently only supports the
client_credentialsOAuth2 grant withclient_secretfor authentication against the token endpoint. Some enterprise environments have security policies that forbid the use of shared secrets (client_secret) for machine-to-machine authentication and instead require JWT-based client assertions (See RFC 7523 (Section 2.2)).Users in these environments are currently unable to use the Java SDK's built-in credential management at all, they're forced to either manage token acquisition entirely outside the SDK or forego using the SDK.
Describe the ideal solution
Add support for JWT client assertions as an alternative client authentication method on the existing
client_credentialsgrant, consistent with the approach we've taken in the JS SDK (PR #228).The token request would use:
History | What the JS SDK Did
In PR #228 , the JS SDK added support for JWT client assertions as an alternative to client_secret for authenticating the client_credentials grant.
The JS SDK introduced:
PrivateKeyJWTConfigtype alongside the existingClientSecretConfig(unified asClientCredentialsConfig=ClientSecretConfig|PrivateKeyJWTConfig)clientAssertionSigningKey(a PEM-encoded PKCS#8 private key string) andclientAssertionSigningAlgorithm(defaults to RS256)The interface in JS was:
Then the SDK builds & signs the JWT
Limitations of the JS Approach
Proposed interface
We should replacing the PEM string with a provider interface — a callback that returns a signed JWT assertion on demand. The SDK continues to own the token exchange lifecycle (caching, refresh, retry) but delegates assertion creation entirely to the caller.
Note
Below you'll see references to Scopes as defined by RFC 6749. This is not strictly related to Private Key JWT, but is an adjacent feature supported by several other SDKs that we need to add
ClientAssertionProvidercan be something like:When
clientAssertionis present, the SDK should:client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearerandclient_assertion=<jwt>in the token requestclient_secretValidation rules:
clientSecretorclientAssertionmust be provided, but not bothclientAssertionis provided, eitherjwtorjwtProvidermust be setclientIdremains requiredTo build the request params, the fn could be:
External DX
Usage would look like:
External DX - example w/ KMS
Alternatives and current workarounds
Users can acquire tokens outside the SDK and pass them via the
API_TOKENcredential method. However, this means the user must handle token refresh/expiry themselves, losing the built-in token lifecycle management we provide through the SDK.References
Additional context
Notes:
Original request:
Author: Nicholas on CNCF Slack (thread)