I\'m building an AngularJS (1.2.16) web app with a RESTful API, and I\'d like to send 401 Unauthorized responses for requests where authentication information is invalid or
Figured it out!
The trick was to send a WWW-Authenticate response header of some value other than Basic. You can then capture the 401 with a basic $http interceptor, or something even more clever like angular-http-auth.
I had this issue together with Spring Boot Security (HTTP basic), and since Angular 1.3 you have to set $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest'; for the popup not to appear.
For future reference
I've come up with this solution when trying to handle 401 errors.
I didn't have the option to rewrite Basic to x-Basic or anything similar, so I've decided to handle it on client side with Angular.
When initiating a logout, first try making a bad request with a fake user to throw away the currently cached credentials.
I have this function doing the requests (it's using jquery's $.ajax with disabled asynch calls):
function authenticateUser(username, hash) {
    var result = false;
    var encoded = btoa(username + ':' + hash);
    $.ajax({
        type: "POST",
        beforeSend: function (request) {
            request.setRequestHeader("Authorization", 'Basic ' + encoded);
        },
        url: "user/current",
        statusCode: {
            401: function () {
                result = false;
            },
            200: function (response) {
                result = response;
            }
        },
        async: false
    });
    return result;
}
So when I try to log a user out, this happens:
//This will send a request with a non-existant user.
//The purpose is to overwrite the cached data with something else
accountServices.authenticateUser('logout','logout');
//Since setting headers.common.Authorization = '' will still send some
//kind of auth data, I've redefined the headers.common object to get
//rid of the Authorization property
$http.defaults.headers.common = {Accept: "application/json, text/plain, */*"};