Skip to content

Commit

Permalink
feat: adds token exchange and general auth (#176)
Browse files Browse the repository at this point in the history
Java SDK only does token exchange with client credentials. This PR
allows token exchange or general authentication using the Nimbus
Authorization Grant.
  • Loading branch information
imdominicreed authored Oct 4, 2024
1 parent 864e9ce commit bb325c4
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.SignedJWT;
import com.nimbusds.oauth2.sdk.AuthorizationGrant;
import com.nimbusds.oauth2.sdk.ClientCredentialsGrant;
import com.nimbusds.oauth2.sdk.ErrorObject;
import com.nimbusds.oauth2.sdk.TokenRequest;
import com.nimbusds.oauth2.sdk.TokenResponse;
Expand Down Expand Up @@ -41,6 +40,7 @@ class GRPCAuthInterceptor implements ClientInterceptor {
private final ClientAuthentication clientAuth;
private final RSAKey rsaKey;
private final URI tokenEndpointURI;
private final AuthorizationGrant authzGrant;
private SSLFactory sslFactory;
private static final Logger logger = LoggerFactory.getLogger(GRPCAuthInterceptor.class);

Expand All @@ -52,11 +52,12 @@ class GRPCAuthInterceptor implements ClientInterceptor {
* @param rsaKey the RSA key to be used by the interceptor
* @param sslFactory Optional SSLFactory for Requests
*/
public GRPCAuthInterceptor(ClientAuthentication clientAuth, RSAKey rsaKey, URI tokenEndpointURI, SSLFactory sslFactory) {
public GRPCAuthInterceptor(ClientAuthentication clientAuth, RSAKey rsaKey, URI tokenEndpointURI, AuthorizationGrant authzGrant, SSLFactory sslFactory) {
this.clientAuth = clientAuth;
this.rsaKey = rsaKey;
this.tokenEndpointURI = tokenEndpointURI;
this.sslFactory = sslFactory;
this.authzGrant = authzGrant;
}

/**
Expand Down Expand Up @@ -110,12 +111,9 @@ private synchronized AccessToken getToken() {

logger.trace("The current access token is expired or empty, getting a new one");

// Construct the client credentials grant
AuthorizationGrant clientGrant = new ClientCredentialsGrant();

// Make the token request
TokenRequest tokenRequest = new TokenRequest(this.tokenEndpointURI,
clientAuth, clientGrant, null);
clientAuth, authzGrant, null);
HTTPRequest httpRequest = tokenRequest.toHTTPRequest();
if(sslFactory!=null){
httpRequest.setSSLSocketFactory(sslFactory.getSslSocketFactory());
Expand Down
31 changes: 30 additions & 1 deletion sdk/src/main/java/io/opentdf/platform/sdk/SDKBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
import com.nimbusds.oauth2.sdk.AuthorizationGrant;
import com.nimbusds.oauth2.sdk.ClientCredentialsGrant;
import com.nimbusds.oauth2.sdk.GeneralException;
import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic;
import com.nimbusds.oauth2.sdk.auth.Secret;
import com.nimbusds.oauth2.sdk.id.ClientID;
import com.nimbusds.oauth2.sdk.id.Issuer;
import com.nimbusds.oauth2.sdk.token.BearerAccessToken;
import com.nimbusds.oauth2.sdk.token.TokenTypeURI;
import com.nimbusds.oauth2.sdk.tokenexchange.TokenExchangeGrant;
import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
import io.grpc.*;
import io.opentdf.platform.wellknownconfiguration.GetWellKnownConfigurationRequest;
Expand Down Expand Up @@ -41,6 +46,7 @@ public class SDKBuilder {
private ClientAuthentication clientAuth = null;
private Boolean usePlainText;
private SSLFactory sslFactory;
private AuthorizationGrant authzGrant;

private static final Logger logger = LoggerFactory.getLogger(SDKBuilder.class);

Expand All @@ -49,6 +55,7 @@ public static SDKBuilder newBuilder() {
builder.usePlainText = false;
builder.clientAuth = null;
builder.platformEndpoint = null;
builder.authzGrant = null;

return builder;
}
Expand Down Expand Up @@ -99,6 +106,24 @@ public SDKBuilder platformEndpoint(String platformEndpoint) {
return this;
}

public SDKBuilder authorizationGrant(AuthorizationGrant authzGrant) {
if (this.authzGrant != null) {
throw new RuntimeException("Authorization grant can't be specified twice");
}
this.authzGrant = authzGrant;
return this;
}

public SDKBuilder tokenExchange(String jwt) {
if (this.authzGrant != null) {
throw new RuntimeException("Authorization grant can't be specified twice");
}

BearerAccessToken token = new BearerAccessToken(jwt);
this.authzGrant = new TokenExchangeGrant(token, TokenTypeURI.ACCESS_TOKEN);
return this;
}

public SDKBuilder clientSecret(String clientID, String clientSecret) {
ClientID cid = new ClientID(clientID);
Secret cs = new Secret(clientSecret);
Expand Down Expand Up @@ -168,7 +193,11 @@ private GRPCAuthInterceptor getGrpcAuthInterceptor(RSAKey rsaKey) {
throw new SDKException("Error resolving the OIDC provider metadata", e);
}

return new GRPCAuthInterceptor(clientAuth, rsaKey, providerMetadata.getTokenEndpointURI(), sslFactory);
if (this.authzGrant == null) {
this.authzGrant = new ClientCredentialsGrant();
}

return new GRPCAuthInterceptor(clientAuth, rsaKey, providerMetadata.getTokenEndpointURI(), this.authzGrant, sslFactory);
}

static class ServicesAndInternals {
Expand Down

0 comments on commit bb325c4

Please sign in to comment.