Is there a way to check whether Windows Authentication (Negotiate, Kerberos, NTLM...) is available in the browser (with JavaScript or other methods) without browser prompting for username and password if it is not?
Background
We are developing Angular2 SPA corporate application and want to have SSO with Windows Authentication if it is available (user is accessing the application from Domain joined computer) and gracefully fail over to form based authentication if it is not available (accessing from the Internet or non domain joined computer).
Setup
Have a resource on server side (namely a REST method) which is protected by Windows Authentication. When you call this REST method with JavaScript, either of two things will happen:
Problem
Displaying of Login prompt is undesired, we want to gracefully fall back to form based login.
Some solutions suggest to remove WWW-Authenticate header from response but this will prevent Windows Authentication to work since this step is part of broser-server negotiating an authentication protocol. If removed, browser will never send NTLM or Kerberos token.
We control both the front end and the backend so can modify either one to make it work. Also, there is no CORS, everything is server from a single domain.
Any method that will detect whether Windows Authentication is available or not from the client is good enough for us. What I have found so far is this but it is only for IE and requires ActiveX to be enabled. This question is somewhat related but it too doesn't have a solution and is quite old.
We are using an XmlHttpRequest within an Web Worker. This way it is possible to perform Kerberos authentication without triggering the login window if it fails.
Web Workers are supported by IE11, so you should be good to use it.
This involves proving an single API end point where you can try to authenticate via Kerberos, e.g. 'yourhost.tld/krb5LoginUrl'
Your Webworker (provide as e.g. task.js):
self.addEventListener('message', function(e) {
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", e.data);
oReq.send(null);
function reqListener () {
self.postMessage(this.status);
}, false);
Register the worker in your main application code: const worker = new Worker('task.js');
worker.postMessage(/krb5LoginUrl); // Sends the url to our worker and triggers xmlHttpRequest.
worker.addEventListener('message', function (e) {
if (e.data == 200) {
console.log("Krb5 login successful");
} else {
console.log("Krb5 login failed");
}
}, false);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With