Skip to content

Commit 8e3b9d9

Browse files
committed
Remove com.nimbusds's HTTPRequest, ClientAuthentication, and related classes
1 parent 3699125 commit 8e3b9d9

7 files changed

Lines changed: 63 additions & 164 deletions

File tree

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AbstractClientApplicationBase.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
package com.microsoft.aad.msal4j;
55

6-
import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
7-
86
import javax.net.ssl.SSLSocketFactory;
97
import java.net.MalformedURLException;
108
import java.net.Proxy;
@@ -29,7 +27,6 @@ public abstract class AbstractClientApplicationBase extends AbstractApplicationB
2927
private String applicationName;
3028
private String applicationVersion;
3129
private AadInstanceDiscoveryResponse aadAadInstanceDiscoveryResponse;
32-
protected abstract ClientAuthentication clientAuthentication();
3330
private String clientCapabilities;
3431
private boolean autoDetectRegion;
3532
protected String azureRegion;

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ClientAuthenticationPost.java

Lines changed: 0 additions & 60 deletions
This file was deleted.

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ConfidentialClientApplication.java

Lines changed: 18 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,8 @@
33

44
package com.microsoft.aad.msal4j;
55

6-
import com.nimbusds.oauth2.sdk.ParseException;
7-
import com.nimbusds.oauth2.sdk.auth.*;
8-
import com.nimbusds.oauth2.sdk.id.ClientID;
96
import org.slf4j.LoggerFactory;
107

11-
import java.util.*;
128
import java.util.concurrent.CompletableFuture;
139
import java.util.function.Function;
1410

@@ -23,10 +19,9 @@
2319
*/
2420
public class ConfidentialClientApplication extends AbstractClientApplicationBase implements IConfidentialClientApplication {
2521

26-
private ClientAuthentication clientAuthentication;
27-
28-
private boolean clientCertAuthentication = false;
2922
private ClientCertificate clientCertificate;
23+
String assertion;
24+
String secret;
3025

3126
/** AppTokenProvider creates a Credential from a function that provides access tokens. The function
3227
must be concurrency safe. This is intended only to allow the Azure SDK to cache MSI tokens. It isn't
@@ -87,65 +82,31 @@ private void initClientAuthentication(IClientCredential clientCredential) {
8782
validateNotNull("clientCredential", clientCredential);
8883

8984
if (clientCredential instanceof ClientSecret) {
90-
clientAuthentication = new ClientSecretPost(
91-
new ClientID(clientId()),
92-
new Secret(((ClientSecret) clientCredential).clientSecret()));
85+
this.secret = ((ClientSecret) clientCredential).clientSecret();
9386
} else if (clientCredential instanceof ClientCertificate) {
94-
this.clientCertAuthentication = true;
9587
this.clientCertificate = (ClientCertificate) clientCredential;
96-
clientAuthentication = buildValidClientCertificateAuthority();
88+
this.assertion = getAssertionString(clientCredential);
9789
} else if (clientCredential instanceof ClientAssertion) {
98-
clientAuthentication = createClientAuthFromClientAssertion((ClientAssertion) clientCredential);
90+
this.assertion = getAssertionString(clientCredential);
9991
} else {
10092
throw new IllegalArgumentException("Unsupported client credential");
10193
}
10294
}
10395

104-
@Override
105-
protected ClientAuthentication clientAuthentication() {
106-
if (clientCertAuthentication) {
107-
final Date currentDateTime = new Date(System.currentTimeMillis());
108-
final Date expirationTime = ((PrivateKeyJWT) clientAuthentication).getJWTAuthenticationClaimsSet().getExpirationTime();
109-
if (expirationTime.before(currentDateTime)) {
110-
clientAuthentication = buildValidClientCertificateAuthority();
111-
}
112-
}
113-
return clientAuthentication;
114-
}
96+
String getAssertionString(IClientCredential clientCredential) {
97+
if (clientCredential instanceof ClientCertificate) {
98+
boolean useSha1 = Authority.detectAuthorityType(this.authenticationAuthority.canonicalAuthorityUrl()) == AuthorityType.ADFS;
11599

116-
private ClientAuthentication buildValidClientCertificateAuthority() {
117-
//The library originally used SHA-1 for thumbprints as other algorithms were not supported server-side.
118-
//When this was written support for SHA-256 had been added, however ADFS scenarios still only allowed SHA-1.
119-
boolean useSha1 = Authority.detectAuthorityType(this.authenticationAuthority.canonicalAuthorityUrl()) == AuthorityType.ADFS;
120-
121-
ClientAssertion clientAssertion = JwtHelper.buildJwt(
122-
clientId(),
123-
clientCertificate,
124-
this.authenticationAuthority.selfSignedJwtAudience(),
125-
sendX5c,
126-
useSha1);
127-
return createClientAuthFromClientAssertion(clientAssertion);
128-
}
129-
130-
protected ClientAuthentication createClientAuthFromClientAssertion(
131-
final ClientAssertion clientAssertion) {
132-
final Map<String, List<String>> map = new HashMap<>();
133-
try {
134-
135-
map.put("client_assertion_type", Collections.singletonList(ClientAssertion.assertionType));
136-
map.put("client_assertion", Collections.singletonList(clientAssertion.assertion()));
137-
return PrivateKeyJWT.parse(map);
138-
} catch (final ParseException e) {
139-
//This library is not supposed to validate Issuer and subject values.
140-
//The next lines of code ensures that exception is not thrown.
141-
if (e.getMessage().contains("Issuer and subject in client JWT assertion must designate the same client identifier")) {
142-
return new CustomJWTAuthentication(
143-
ClientAuthenticationMethod.PRIVATE_KEY_JWT,
144-
clientAssertion,
145-
new ClientID(clientId())
146-
);
147-
}
148-
throw new MsalClientException(e);
100+
return JwtHelper.buildJwt(
101+
clientId(),
102+
clientCertificate,
103+
this.authenticationAuthority.selfSignedJwtAudience(),
104+
sendX5c,
105+
useSha1).assertion();
106+
} else if (clientCredential instanceof ClientAssertion) {
107+
return ((ClientAssertion) clientCredential).assertion();
108+
} else {
109+
throw new IllegalArgumentException("Unsupported client credential");
149110
}
150111
}
151112

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/OAuthHttpRequest.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package com.microsoft.aad.msal4j;
55

66
import com.nimbusds.oauth2.sdk.ParseException;
7-
import com.nimbusds.oauth2.sdk.http.HTTPRequest;
87
import com.nimbusds.oauth2.sdk.http.HTTPResponse;
98

109
import java.io.IOException;
@@ -15,32 +14,35 @@
1514
import java.util.List;
1615
import java.util.Map;
1716

18-
class OAuthHttpRequest extends HTTPRequest {
17+
class OAuthHttpRequest {
1918

19+
final HttpMethod method;
20+
final URL url;
21+
String query;
2022
private final Map<String, String> extraHeaderParams;
2123
private final ServiceBundle serviceBundle;
2224
private final RequestContext requestContext;
2325

24-
OAuthHttpRequest(final Method method,
26+
OAuthHttpRequest(final HttpMethod method,
2527
final URL url,
2628
final Map<String, String> extraHeaderParams,
2729
RequestContext requestContext,
2830
final ServiceBundle serviceBundle) {
29-
super(method, url);
31+
this.method = method;
32+
this.url = url;
3033
this.extraHeaderParams = extraHeaderParams;
3134
this.requestContext = requestContext;
3235
this.serviceBundle = serviceBundle;
3336
}
3437

35-
@Override
3638
public HTTPResponse send() throws IOException {
3739

3840
Map<String, String> httpHeaders = configureHttpHeaders();
3941
HttpRequest httpRequest = new HttpRequest(
4042
HttpMethod.POST,
41-
this.getURL().toString(),
43+
this.url.toString(),
4244
httpHeaders,
43-
this.getQuery());
45+
this.query);
4446

4547
IHttpResponse httpResponse = serviceBundle.getHttpHelper().executeHttpRequest(
4648
httpRequest,
@@ -55,10 +57,6 @@ private Map<String, String> configureHttpHeaders() {
5557
Map<String, String> httpHeaders = new HashMap<>(extraHeaderParams);
5658
httpHeaders.put("Content-Type", HTTPContentType.ApplicationURLEncoded.contentType);
5759

58-
if (this.getAuthorization() != null) {
59-
httpHeaders.put("Authorization", this.getAuthorization());
60-
}
61-
6260
Map<String, String> telemetryHeaders =
6361
serviceBundle.getServerSideTelemetry().getServerTelemetryHeaderMap();
6462
httpHeaders.putAll(telemetryHeaders);
@@ -109,6 +107,10 @@ private HTTPResponse createOauthHttpResponseFromHttpResponse(IHttpResponse httpR
109107
return response;
110108
}
111109

110+
void setQuery(String query) {
111+
this.query = query;
112+
}
113+
112114
Map<String, String> getExtraHeaderParams() {
113115
return this.extraHeaderParams;
114116
}

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/PublicClientApplication.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33

44
package com.microsoft.aad.msal4j;
55

6-
import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
7-
import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
8-
import com.nimbusds.oauth2.sdk.id.ClientID;
96
import org.slf4j.LoggerFactory;
107

118
import java.net.MalformedURLException;
@@ -23,7 +20,6 @@
2320
*/
2421
public class PublicClientApplication extends AbstractClientApplicationBase implements IPublicClientApplication {
2522

26-
private final ClientAuthenticationPost clientAuthentication;
2723
private IBroker broker;
2824
private boolean brokerEnabled;
2925

@@ -161,18 +157,11 @@ private PublicClientApplication(Builder builder) {
161157
super(builder);
162158
validateNotBlank("clientId", clientId());
163159
log = LoggerFactory.getLogger(PublicClientApplication.class);
164-
this.clientAuthentication = new ClientAuthenticationPost(ClientAuthenticationMethod.NONE,
165-
new ClientID(clientId()));
166160
this.broker = builder.broker;
167161
this.brokerEnabled = builder.brokerEnabled;
168162
this.tenant = this.authenticationAuthority.tenant;
169163
}
170164

171-
@Override
172-
protected ClientAuthentication clientAuthentication() {
173-
return clientAuthentication;
174-
}
175-
176165
/**
177166
* @param clientId Client ID (Application ID) of the application as registered
178167
* in the application registration portal (portal.azure.com)

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/TokenRequestExecutor.java

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import com.nimbusds.oauth2.sdk.ParseException;
77
import com.nimbusds.oauth2.sdk.SerializeException;
8-
import com.nimbusds.oauth2.sdk.http.HTTPRequest;
98
import com.nimbusds.oauth2.sdk.http.HTTPResponse;
109
import com.nimbusds.oauth2.sdk.util.URLUtils;
1110
import com.nimbusds.openid.connect.sdk.token.OIDCTokens;
@@ -42,19 +41,18 @@ AuthenticationResult executeTokenRequest() throws ParseException, IOException {
4241
return createAuthenticationResultFromOauthHttpResponse(oauthHttpResponse);
4342
}
4443

45-
OAuthHttpRequest createOauthHttpRequest() throws SerializeException, MalformedURLException, ParseException {
44+
OAuthHttpRequest createOauthHttpRequest() throws SerializeException, MalformedURLException {
4645

4746
if (requestAuthority.tokenEndpointUrl() == null) {
4847
throw new SerializeException("The endpoint URI is not specified");
4948
}
5049

5150
final OAuthHttpRequest oauthHttpRequest = new OAuthHttpRequest(
52-
HTTPRequest.Method.POST,
51+
HttpMethod.POST,
5352
requestAuthority.tokenEndpointUrl(),
5453
msalRequest.headers().getReadonlyHeaderMap(),
5554
msalRequest.requestContext(),
5655
this.serviceBundle);
57-
oauthHttpRequest.setContentType(HTTPContentType.ApplicationURLEncoded.contentType);
5856

5957
final Map<String, List<String>> params = new HashMap<>(msalRequest.msalAuthorizationGrant().toParameters());
6058
if (msalRequest.application() instanceof AbstractClientApplicationBase
@@ -80,26 +78,41 @@ OAuthHttpRequest createOauthHttpRequest() throws SerializeException, MalformedUR
8078
}
8179

8280
oauthHttpRequest.setQuery(URLUtils.serializeParameters(params));
83-
84-
if (msalRequest.application() instanceof AbstractClientApplicationBase
85-
&& ((AbstractClientApplicationBase) msalRequest.application()).clientAuthentication() != null) {
8681

87-
Map<String, List<String>> queryParameters = oauthHttpRequest.getQueryParameters();
88-
String clientID = msalRequest.application().clientId();
89-
queryParameters.put("client_id", Arrays.asList(clientID));
90-
oauthHttpRequest.setQuery(URLUtils.serializeParameters(queryParameters));
82+
//Certain query parameters are required by Public and Confidential client applications, but not Managed Identity
83+
if (msalRequest.application() instanceof AbstractClientApplicationBase) {
84+
addQueryParameters(oauthHttpRequest);
85+
}
86+
return oauthHttpRequest;
87+
}
88+
89+
private void addQueryParameters(OAuthHttpRequest oauthHttpRequest) {
90+
Map<String, List<String>> queryParameters = URLUtils.parseParameters(oauthHttpRequest.query);
91+
String clientID = msalRequest.application().clientId();
92+
queryParameters.put("client_id", Arrays.asList(clientID));
9193

92-
// If the client application has a client assertion to apply to the request, check if a new client assertion
93-
// was supplied as a request parameter. If so, use the request's assertion instead of the application's
94+
// If the client application has a client assertion to apply to the request, check if a new client assertion
95+
// was supplied as a request parameter. If so, use the request's assertion instead of the application's
96+
if (msalRequest.application() instanceof ConfidentialClientApplication) {
9497
if (msalRequest instanceof ClientCredentialRequest && ((ClientCredentialRequest) msalRequest).parameters.clientCredential() != null) {
95-
((ConfidentialClientApplication) msalRequest.application())
96-
.createClientAuthFromClientAssertion((ClientAssertion) ((ClientCredentialRequest) msalRequest).parameters.clientCredential())
97-
.applyTo(oauthHttpRequest);
98+
IClientCredential credential = ((ClientCredentialRequest) msalRequest).parameters.clientCredential();
99+
addJWTBearerAssertionParams(queryParameters, ((ConfidentialClientApplication) msalRequest.application()).getAssertionString(credential));
98100
} else {
99-
((AbstractClientApplicationBase) msalRequest.application()).clientAuthentication().applyTo(oauthHttpRequest);
101+
if (((ConfidentialClientApplication) msalRequest.application()).assertion != null) {
102+
addJWTBearerAssertionParams(queryParameters, ((ConfidentialClientApplication) msalRequest.application()).assertion);
103+
} else if (((ConfidentialClientApplication) msalRequest.application()).secret != null) {
104+
// Client secrets have a different parameter than bearer assertions
105+
queryParameters.put("client_secret", Collections.singletonList(((ConfidentialClientApplication) msalRequest.application()).secret));
106+
}
100107
}
101108
}
102-
return oauthHttpRequest;
109+
110+
oauthHttpRequest.setQuery(URLUtils.serializeParameters(queryParameters));
111+
}
112+
113+
private void addJWTBearerAssertionParams(Map<String, List<String>> queryParameters, String assertion) {
114+
queryParameters.put("client_assertion", Collections.singletonList(assertion));
115+
queryParameters.put("client_assertion_type", Collections.singletonList("urn:ietf:params:oauth:client-assertion-type:jwt-bearer"));
103116
}
104117

105118
private AuthenticationResult createAuthenticationResultFromOauthHttpResponse(

msal4j-sdk/src/test/java/com/microsoft/aad/msal4j/ClientCertificateTest.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,7 @@ void testIClientCertificateInterface_CredentialFactoryUsesSha256() throws Except
7272

7373
when(httpClientMock.send(any(HttpRequest.class))).thenAnswer( parameters -> {
7474
HttpRequest request = parameters.getArgument(0);
75-
Set<String> headerParams = ((PrivateKeyJWT) cca.clientAuthentication()).getClientAssertion().getHeader().getIncludedParams();
76-
if (request.body().contains(((PrivateKeyJWT) cca.clientAuthentication()).getClientAssertion().serialize())
77-
&& headerParams.contains("x5t#S256")) {
78-
75+
if (request.body().contains(cca.assertion)) {
7976
return TestHelper.expectedResponse(200, TestHelper.getSuccessfulTokenResponse(tokenResponseValues));
8077
}
8178
return null;

0 commit comments

Comments
 (0)