Skip to content

Commit e622db6

Browse files
authored
Merge pull request #98677 from JasonFreeberg/patch-47
Adding Java sample for client cert validation
2 parents 6c033c8 + 2c254da commit e622db6

File tree

1 file changed

+97
-1
lines changed

1 file changed

+97
-1
lines changed

articles/app-service/app-service-web-configure-tls-mutual-auth.md

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,4 +210,100 @@ export class AuthorizationHandler {
210210
}
211211
```
212212

213-
[exclusion-paths]: ./media/app-service-web-configure-tls-mutual-auth/exclusion-paths.png
213+
## Java sample
214+
215+
The following Java class encodes the certificate from `X-ARR-ClientCert` to an `X509Certificate` instance. `certificateIsValid()` validates that the certificate's thumbprint matches the one given in the constructor and that certificate has not expired.
216+
217+
218+
```java
219+
import java.io.ByteArrayInputStream;
220+
import java.security.NoSuchAlgorithmException;
221+
import java.security.cert.*;
222+
import java.security.MessageDigest;
223+
224+
import sun.security.provider.X509Factory;
225+
226+
import javax.xml.bind.DatatypeConverter;
227+
import java.util.Base64;
228+
import java.util.Date;
229+
230+
public class ClientCertValidator {
231+
232+
private String thumbprint;
233+
private X509Certificate certificate;
234+
235+
/**
236+
* Constructor.
237+
* @param certificate The certificate from the "X-ARR-ClientCert" HTTP header
238+
* @param thumbprint The thumbprint to check against
239+
* @throws CertificateException If the certificate factory cannot be created.
240+
*/
241+
public ClientCertValidator(String certificate, String thumbprint) throws CertificateException {
242+
certificate = certificate
243+
.replaceAll(X509Factory.BEGIN_CERT, "")
244+
.replaceAll(X509Factory.END_CERT, "");
245+
CertificateFactory cf = CertificateFactory.getInstance("X.509");
246+
byte [] base64Bytes = Base64.getDecoder().decode(certificate);
247+
X509Certificate X509cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(base64Bytes));
248+
249+
this.setCertificate(X509cert);
250+
this.setThumbprint(thumbprint);
251+
}
252+
253+
/**
254+
* Check that the certificate's thumbprint matches the one given in the constructor, and that the
255+
* certificate has not expired.
256+
* @return True if the certificate's thumbprint matches and has not expired. False otherwise.
257+
*/
258+
public boolean certificateIsValid() throws NoSuchAlgorithmException, CertificateEncodingException {
259+
return certificateHasNotExpired() && thumbprintIsValid();
260+
}
261+
262+
/**
263+
* Check certificate's timestamp.
264+
* @return Returns true if the certificate has not expired. Returns false if it has expired.
265+
*/
266+
private boolean certificateHasNotExpired() {
267+
Date currentTime = new java.util.Date();
268+
try {
269+
this.getCertificate().checkValidity(currentTime);
270+
} catch (CertificateExpiredException | CertificateNotYetValidException e) {
271+
return false;
272+
}
273+
return true;
274+
}
275+
276+
/**
277+
* Check the certificate's thumbprint matches the given one.
278+
* @return Returns true if the thumbprints match. False otherwise.
279+
*/
280+
private boolean thumbprintIsValid() throws NoSuchAlgorithmException, CertificateEncodingException {
281+
MessageDigest md = MessageDigest.getInstance("SHA-1");
282+
byte[] der = this.getCertificate().getEncoded();
283+
md.update(der);
284+
byte[] digest = md.digest();
285+
String digestHex = DatatypeConverter.printHexBinary(digest);
286+
return digestHex.toLowerCase().equals(this.getThumbprint().toLowerCase());
287+
}
288+
289+
// Getters and setters
290+
291+
public void setThumbprint(String thumbprint) {
292+
this.thumbprint = thumbprint;
293+
}
294+
295+
public String getThumbprint() {
296+
return this.thumbprint;
297+
}
298+
299+
public X509Certificate getCertificate() {
300+
return certificate;
301+
}
302+
303+
public void setCertificate(X509Certificate certificate) {
304+
this.certificate = certificate;
305+
}
306+
}
307+
```
308+
309+
[exclusion-paths]: ./media/app-service-web-configure-tls-mutual-auth/exclusion-paths.png

0 commit comments

Comments
 (0)