Skip to content

Commit c83185c

Browse files
authored
Merge pull request #840 from AzureAD/avdunn/update-sha-method
Use SHA256 thumbprints in non-ADFS cert flows
2 parents d3faa28 + 08a5189 commit c83185c

File tree

4 files changed

+43
-10
lines changed

4 files changed

+43
-10
lines changed

msal4j-sdk/src/integrationtest/java/com.microsoft.aad.msal4j/ClientCredentialsIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ private ClientAssertion getClientAssertion(String clientId) {
160160
clientId,
161161
(ClientCertificate) certificate,
162162
"https://login.microsoftonline.com/common/oauth2/v2.0/token",
163-
true);
163+
true, false);
164164
}
165165

166166
private void assertAcquireTokenCommon(String clientId, IClientCredential credential, String authority) throws Exception {

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
import java.io.IOException;
1010
import java.io.InputStream;
11-
import java.lang.reflect.InvocationTargetException;
12-
import java.lang.reflect.Method;
1311
import java.security.KeyStore;
1412
import java.security.KeyStoreException;
1513
import java.security.MessageDigest;
@@ -21,7 +19,6 @@
2119
import java.security.cert.CertificateEncodingException;
2220
import java.security.cert.CertificateException;
2321
import java.security.cert.X509Certificate;
24-
import java.security.interfaces.RSAPrivateKey;
2522
import java.util.ArrayList;
2623
import java.util.Arrays;
2724
import java.util.Base64;
@@ -53,7 +50,14 @@ public String publicCertificateHash()
5350
throws CertificateEncodingException, NoSuchAlgorithmException {
5451

5552
return Base64.getEncoder().encodeToString(ClientCertificate
56-
.getHash(publicKeyCertificateChain.get(0).getEncoded()));
53+
.getHashSha256(publicKeyCertificateChain.get(0).getEncoded()));
54+
}
55+
56+
public String publicCertificateHashSha1()
57+
throws CertificateEncodingException, NoSuchAlgorithmException {
58+
59+
return Base64.getEncoder().encodeToString(ClientCertificate
60+
.getHashSha1(publicKeyCertificateChain.get(0).getEncoded()));
5761
}
5862

5963
public List<String> getEncodedPublicKeyCertificateChain() throws CertificateEncodingException {
@@ -119,9 +123,15 @@ static ClientCertificate create(final PrivateKey key, final X509Certificate publ
119123
return new ClientCertificate(key, Arrays.asList(publicKeyCertificate));
120124
}
121125

122-
private static byte[] getHash(final byte[] inputBytes) throws NoSuchAlgorithmException {
126+
private static byte[] getHashSha1(final byte[] inputBytes) throws NoSuchAlgorithmException {
123127
final MessageDigest md = MessageDigest.getInstance("SHA-1");
124128
md.update(inputBytes);
125129
return md.digest();
126130
}
131+
132+
private static byte[] getHashSha256(final byte[] inputBytes) throws NoSuchAlgorithmException {
133+
final MessageDigest md = MessageDigest.getInstance("SHA-256");
134+
md.update(inputBytes);
135+
return md.digest();
136+
}
127137
}

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

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,11 @@ private void initClientAuthentication(IClientCredential clientCredential) {
101101
} else if (clientCredential instanceof ClientCertificate) {
102102
this.clientCertAuthentication = true;
103103
this.clientCertificate = (ClientCertificate) clientCredential;
104-
clientAuthentication = buildValidClientCertificateAuthority();
104+
if (Authority.detectAuthorityType(this.authenticationAuthority.canonicalAuthorityUrl()) == AuthorityType.ADFS) {
105+
clientAuthentication = buildValidClientCertificateAuthoritySha1();
106+
} else {
107+
clientAuthentication = buildValidClientCertificateAuthority();
108+
}
105109
} else if (clientCredential instanceof ClientAssertion) {
106110
clientAuthentication = createClientAuthFromClientAssertion((ClientAssertion) clientCredential);
107111
} else {
@@ -127,7 +131,20 @@ private ClientAuthentication buildValidClientCertificateAuthority() {
127131
clientId(),
128132
clientCertificate,
129133
this.authenticationAuthority.selfSignedJwtAudience(),
130-
sendX5c);
134+
sendX5c,
135+
false);
136+
return createClientAuthFromClientAssertion(clientAssertion);
137+
}
138+
139+
//The library originally used SHA-1 for thumbprints as other algorithms were not supported server-side,
140+
// and while support for SHA-256 has been added certain flows still only allow SHA-1
141+
private ClientAuthentication buildValidClientCertificateAuthoritySha1() {
142+
ClientAssertion clientAssertion = JwtHelper.buildJwt(
143+
clientId(),
144+
clientCertificate,
145+
this.authenticationAuthority.selfSignedJwtAudience(),
146+
sendX5c,
147+
true);
131148
return createClientAuthFromClientAssertion(clientAssertion);
132149
}
133150

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
final class JwtHelper {
2222

2323
static ClientAssertion buildJwt(String clientId, final ClientCertificate credential,
24-
final String jwtAudience, boolean sendX5c) throws MsalClientException {
24+
final String jwtAudience, boolean sendX5c,
25+
boolean useSha1) throws MsalClientException {
2526
if (StringHelper.isBlank(clientId)) {
2627
throw new IllegalArgumentException("clientId is null or empty");
2728
}
@@ -55,7 +56,12 @@ static ClientAssertion buildJwt(String clientId, final ClientCertificate credent
5556
builder.x509CertChain(certs);
5657
}
5758

58-
builder.x509CertThumbprint(new Base64URL(credential.publicCertificateHash()));
59+
//SHA-256 is preferred, however certain flows still require SHA-1 due to what is supported server-side
60+
if (useSha1) {
61+
builder.x509CertThumbprint(new Base64URL(credential.publicCertificateHashSha1()));
62+
} else {
63+
builder.x509CertSHA256Thumbprint(new Base64URL(credential.publicCertificateHash()));
64+
}
5965

6066
jwt = new SignedJWT(builder.build(), claimsSet);
6167
final RSASSASigner signer = new RSASSASigner(credential.privateKey());

0 commit comments

Comments
 (0)