How do I trigger the browser's Basic Authentication dialog from an AJAX call?
Asked Answered
C

8

16

I'm using basic authentication to secure a set of WCF web services exposed only inside our corporate network, and I was wondering if there was a way to trigger the browser's credentials dialog to appear from an AJAX call when the web service returns with a 401 error?

Currently my AJAX call receives the 401 as a regular failed request and doesn't prompt the browser to do anything. However, if I take the same URI and copy-paste it into into the browser's URL bar, the returned 401 correctly triggers the Basic Authentication dialog.

Is there any way to get the AJAX callback to tell the browser to pop up that dialog?

Cobham answered 10/11, 2014 at 17:42 Comment(1)
it should pop-up automatically if needed, even from the invisible ajax code. you probably need a more-specific ajax error handlerTouzle
F
9

Dynamically create an iframe with your url and append to document. It'll trigger authentication form. jQuery snipet to add iframe

$('<iframe src="your_url"></iframe>').appendTo('body')

A very simplified example is here:

var url = 'your_url_here';
$.ajax({
    url: url,
    error: function(response){
        if(response.status==401){           
            $('<iframe src="'+url+'"></iframe>').appendTo('body');          
        }
    },
    success:function(){
        //your success code here
    }
});
Felonious answered 24/8, 2016 at 15:58 Comment(3)
Is there a way to possibly manage the context here a little better? Perhaps to get the data passed in the iframe and push it back to the success function? I'd rather keep the iframe invisible.Estafette
Maybe also support POST methods as well?Estafette
@Estafette if you make iframe invisible browser may not make any request hence no authentication dialog. better make it 1x1 px or use absolute position for it and use very large top & left to make it disapear from document view port. one way to push data to success function from iframe is by making the success function globally accessible and call it from iframe like window.top.success(data)Felonious
A
3

I have faced almost the same 401 problem, except for my request was cross domain. But I hope the reason is the same. Following the instructions on developer.mozilla - Access control CORS I have finally succeeded with simple:

var xhttp=new XMLHttpRequest();
xhttp.withCredentials = true;
xhttp.open("GET", "https://my.foo.server/app/resource", true);
xhttp.send();

I think the xhttp.withCredentials is the solution. It is not header! You let browser to communicate with server through cookies. The following answer explains a lot XHR2 withCredentials - which cookies are sent?

Without xhttp.withCredentials there was always 401 (Unauthorized). But using it, the browser added the required header Authorization:Basic dGVFooFooFooFoosaWVudA== or triggered the login dialog, when credentials were not available yet.

Ammadas answered 8/6, 2017 at 13:42 Comment(1)
I was experiencing the same issue with axios and this answer led me straight to the analogous withCredentials configuration.Sanctitude
D
2

You can't, you'll need to provide the request with the credentials.

See How to use Basic Auth with jQuery and AJAX?

Dumanian answered 10/11, 2014 at 17:46 Comment(1)
it is not answer its just suggetion use comment for itAnyways
P
1

Yes, you can invoke it from AJAX. Just pass the request with the following header:

withCredentials: true

Piegari answered 21/12, 2015 at 9:28 Comment(0)
E
1

You would suggest to open/display/insert a form to allow inserting username and password and than resend the AJAX Request with the given credentials. I wouldn't really on browsers credential popup.

How you set authentication header you can read here: How to use Basic Auth with jQuery and AJAX?

Everyday answered 25/8, 2016 at 16:12 Comment(0)
S
0

As found somewhere in the stack :

Receiving a 401 response is the server telling you, “you aren’t authenticated–either not authenticated at all or authenticated incorrectly–but please reauthenticate and try again.” To help you out, it will always include a WWW-Authenticate header that describes how to authenticate

Use jQuery's beforeSend callback to add an HTTP header with the authentication information

beforeSend: function (xhr) {
xhr.setRequestHeader ("Authorization", "Basic " + btoa(username + ":" + password));
},
Scrivens answered 25/8, 2016 at 20:21 Comment(0)
E
0

Do you meet the conditions highlighted in this SO answer?

Also based on in this other answer you may want to check that the headers returned from your backend are the same whether you request it from the browser or from an AJAX call.

Eucharis answered 25/8, 2016 at 20:55 Comment(3)
The headers are the same, I always pass back WWW-authenticate regardless of the type of request when not authenticating successfully. I have full control over the server in this situation, so I can return additional headers if necessary.Estafette
I see then I am not sure what the issue is, I have seen that working before with pouchDB / couchDB, I can put together a small exampleEucharis
can you create a small example on plunkr perhaps and I can take a look?Eucharis
M
0

you could just trigger a redirect when you check for the 401 condition:

window.location = "https://example.com"
Melleta answered 25/8, 2016 at 21:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.