Is there a way to get SSL certificate details using JavaScript?
Nope, not possible.
It is possible to detect via javascript whether the current page being viewed is over an SSL connection (document.location.protocol=="https:"), but that's about it.
The current JS language standard does not expose certificate information; beyond that It probably depends on how you're using JavaScript, if you're expecting the end user's Browser to expose certificate information then it's going to be really problematic because you'd need to get at the minimum FF, Chrome, Safari, IE, Edge, ... to expose it.
However, as mentioned on this Information Security post, this is not really a desirable option for these browsers to implement, as it would allow a situation where a website developer could write code to mistakenly trust user side credentials.
It's not so much a visibility security risk that prevents javascript from accessing the browser's current SSL Certificate info, but more of a fourth wall barrier security risk where the JS developer must be aware that the "user-accepted" certificate is not necessarily the one that the website provided. The HTML page really shouldn't be handling the security issues with client side code, but instead it should be able to depend on the security layer to do it's job properly. (I can totally understand wanting to checkup on the security layer, but any managerial work you do at the top layer is just going to be either superficial or a reworking of the entire biosphere)
Because let's assume for a moment that javascript did provide a way to work with the certificate, then when Bob already trusts Mallory because his security is broken there is no way of stopping the following exchange:
Office Worker Bob is on one side of the great firewall of Mega Corp., IT Mallory is in charge of the firewall passing traffic in and out of the company locally, and Web Host Alice's awesome website is out on the WWW.
- By Mega Corp. company policy Bob is setup to just accept what Mallory has to say at face value.
- Bob who would like to visit Alice's site, but has no direct outside access, tries to establish a secure connection through the firewall by holding up his certificate(Eg:"I hereby declare I am Bob") and asks Alice in a really convoluted way, "what certificate did I send to you?"
- Mallory gets Bob's request, but instead passes on her own(Eg:"Uh, Bob says it's ok for me to read his webmail"), and even though Mallory doesn't understand Bob's convoluted question she still repeats it to Alice, "akdvyfenwythnwerhy?".
- Alice does some math and figures out that "akdvyfenwythnwerhy?" is asking "what certificate did I send you?" and answers back to Mallory with what she sees("Hi Bob this is Alice you said: Uh, Bob says it's ok for me to read his webmail").
- Mallory does some math, has an ah ha moment "akdvyfenwythnwerhy?=what certificate did I send to you?", and answers Bob's question on behalf of Alice("Hi Bob this is Alice(Mallory) you said: I hereby declare I am Bob").
- Bob believes life is good and continues on to read his webmail, because by company policy he knows Mallory would never lie to him.
- Mallory now able to read both sides of the conversation passes on Bob's request to read his webmail to Alice.
- Alice gets Bob's request and says hey wait a minute Bob I need you to run this JS code to prove you know you're talking to Alice.
- Mallory gets the code, runs it, and sends the results stating that she knows she's talking to Alice back to Alice.
- Alice says, good enough for me here's your webmail.
- Mallory reads Bob's webmail before passing it on to Bob, and everyone is blissfully happy.
(Note: I did not address the case where you're running JS server-side, then it would depend on what program you're using to run your JS code.)
Edit 4/4/2018 -- While the above is not wrong it's more from the perspective of embedded and linked JS than it is about the `XMLHTTPRequest` JS object; moreover quite possibly the strongest argument to be made against sharing PKI details with `XMLHTTPRequest` is as follows:
There needs to remain a strong dividing line between the HTTP portion and the S portion of the HTTPS protocol. JavaScript and it's XMLHTTPRequest
object reside on the HTTP(app layer) side of that line, while the whole certificate exchange process resides on the S(trans/sec layer) side of that line. In order to keep the security side atomic(hot-swappable) its internal workings cannot be exposed across the line to the application side; because there may come a day when the transport/security layer no longer uses PKI certificates to facilitate its secure communication service, and when that day comes no one would need to rewrite any existing JS code that was relying on details contained within those certificates to deal with the propagation wave caused by the www community slowly adopting their favorite flavor of any new security layer.
That being said, the security side does appear to also be doing legal entity vetting --at least in some cases like EV certificates--, and it is IMO a short coming of RFC7230 section 2.7.2 that it does not redefine the authority
of the https-URI
to include an optional legalentity
that the security layer would use when verifying the url it is communicating with is not only the proper end point but also currently under control of the intended business relation.
authority = [ userinfo "@" ] host [ "#" legalentity ] [ ":" port ]
legalentity = *( unreserved / pct-encoded / sub-delims )
The certificate isn't part of the DOM, so no, this won't be possible. Sorry!
This information simply isn't exposed to javascript, it is so rarely used (well never since it isn't available, but it would be rarely used) that it wasn't deemed important enough to add to the javascript object model I suppose...same for any very rarely used feature left out of anything.
Of course, it could have also been left out for security reasons...I'm not creative enough to come up with one at the moment, but I'm sure there's an exploit to be had there as well.