Como posso suprimir a checkbox de diálogo de autenticação do navegador?

Meu aplicativo da web tem uma página de login que envia credenciais de autenticação por meio de uma chamada AJAX. Se o usuário digitar o nome de usuário e a senha corretos, tudo estará bem, mas se não, acontece o seguinte:

  1. O servidor da Web determina que, embora a solicitação inclua um header de autorização bem formado, as credenciais no header não são autenticadas com êxito.
  2. O servidor da web retorna um código de status 401 e inclui um ou mais headers WWW-Authenticate listando os tipos de autenticação suportados.
  3. O navegador detecta que a resposta à minha chamada no object XMLHttpRequest é 401 e a resposta inclui headers WWW-Authenticate. Em seguida, aparece uma checkbox de diálogo de autenticação pedindo, novamente, o nome de usuário e a senha.

Tudo bem até a etapa 3. Não quero que a checkbox de diálogo apareça, quero manipular a resposta 401 em minha function de retorno de chamada AJAX. (Por exemplo, exibindo uma mensagem de erro na página de login.) Eu quero que o usuário digite novamente seu nome de usuário e senha, é claro, mas eu quero que eles vejam meu formulário de login amigável e reconfortante, e não o feio do navegador, padrão diálogo de autenticação.

Incidentalmente, não tenho controle sobre o servidor, portanto, tê-lo retornar um código de status personalizado (ou seja, algo diferente de um 401) não é uma opção.

Existe alguma maneira que eu possa suprimir a checkbox de diálogo de autenticação? Em particular, posso suprimir a checkbox de diálogo Autenticação necessária no Firefox 2 ou posterior? Existe alguma maneira de suprimir a checkbox de diálogo Conectar-se a [host] no IE 6 e posterior?


Editar
Informações adicionais do autor (18 de setembro):
Devo acrescentar que o problema real com a checkbox de diálogo de autenticação do navegador é que ele fornece informações insuficientes ao usuário.

O usuário acaba de digitar um nome de usuário e senha através do formulário na página de login, ele acredita que ele digitou os dois corretamente, e ele clicou no botão de envio ou aperte enter. Sua expectativa é que ele seja levado para a próxima página, ou talvez seja informado que ele digitou suas informações incorretamente e deve tentar novamente. No entanto, ele é apresentado com uma checkbox de diálogo inesperada.

A checkbox de diálogo não reconhece que ele inseriu um nome de usuário e senha. Não indica claramente que houve um problema e que ele deveria tentar novamente. Em vez disso, a checkbox de diálogo apresenta ao usuário informações secretas como “O site diz: ‘ [reino] ‘”. Onde [reino] é um nome de domínio curto que somente um programador poderia amar.

Os projetistas de broswer da Web tomam nota: ninguém perguntaria como suprimir a checkbox de diálogo de autenticação se o diálogo em si fosse simplesmente mais fácil de usar. O motivo completo pelo qual estou fazendo um formulário de login é que nossa equipe de gerenciamento de produtos considera, com razão, que os diálogos de autenticação dos navegadores são terríveis.

Eu não acho que isso é possível – se você usar a implementação do cliente HTTP do navegador, ele sempre irá aparecer na checkbox de diálogo. Dois hacks vêm à mente:

  1. Talvez o Flash lide com isso de forma diferente (ainda não tentei), então ter um filme em flash faz com que o pedido possa ajudar.

  2. Você pode configurar um ‘proxie’ para o serviço que está acessando em seu próprio servidor e modificá-lo um pouco, para que o navegador não os reconheça.

Eu encontrei o mesmo problema aqui, e o engenheiro de back-end da minha empresa implementou um comportamento que aparentemente é considerado uma boa prática: quando uma chamada para uma URL retorna um 401, se o cliente tiver definido o header X-Requested-With: XMLHttpRequest , o servidor descarta o header www-authenticate em sua resposta.

O efeito colateral é que o popup de autenticação padrão não aparece.

Certifique-se de que sua chamada de API tenha o header X-Requested-With definido como XMLHttpRequest . Se assim for, não há nada a fazer além de mudar o comportamento do servidor de acordo com essa boa prática …

O navegador exibe um prompt de login quando ambas as condições a seguir forem atendidas:

  1. O status HTTP é 4xx
  2. WWW-Authenticate header WWW-Authenticate está presente na resposta

Se você puder controlar a resposta HTTP, poderá remover o header WWW-Authenticate da resposta, e o navegador não exibirá a checkbox de diálogo de login.

Se você não puder controlar a resposta, poderá configurar um proxy para filtrar o header WWW-Authenticate da resposta.

Tanto quanto eu sei (sinta-se livre para me corrigir se eu estiver errado), não há como impedir o prompt de login uma vez que o navegador recebe o header WWW-Authenticate .

Eu percebo que esta pergunta e suas respostas são muito antigas. Mas acabei aqui. Talvez outros também o façam.

Se você tiver access ao código do serviço da Web que está retornando o 401. Basta alterar o serviço para retornar 403 (Proibido) nessa situação, em vez de 401. O navegador não solicitará credenciais em resposta a um 403. 403 é o código correto para um usuário autenticado que não está autorizado para um recurso específico. Qual parece ser a situação do OP.

Do documento IETF em 403:

Um servidor que recebe credenciais válidas que não são adequadas para obter access deve responder com o código de status 403 (Proibido)

No Mozilla, você pode obtê-lo com o seguinte script ao criar o object XMLHttpRequest:

 xmlHttp=new XMLHttpRequest(); xmlHttp.mozBackgroundRequest = true; xmlHttp.open("GET",URL,true,USERNAME,PASSWORD); xmlHttp.send(null); 

A segunda linha impede a checkbox de diálogo ….

Qual tecnologia de servidor você usa e há algum produto específico que você usa para autenticação?

Como o navegador está apenas fazendo o seu trabalho, acredito que você tenha que mudar as coisas no lado do servidor para não retornar um código de status 401. Isso pode ser feito usando formulários de autenticação personalizados que simplesmente retornam o formulário novamente quando a autenticação falha.

No Mozilla, configurar o parâmetro mozBackgroundRequest de XMLHttpRequest ( docs ) como true suprime essas checkboxs de diálogo e faz com que as solicitações simplesmente falhem. No entanto, não sei quão bom é o suporte a vários navegadores (incluindo se a qualidade das informações de erro nessas solicitações com falha é muito boa nos navegadores).

jan.vdbergh tem a verdade, se você pode alterar o 401 no lado do servidor para outro código de status, o navegador não vai pegar e pintar o pop-up. Outra solução pode ser alterar o header WWW-Authenticate para outro header personalizado. Eu não acredito porque o navegador diferente não pode suportá-lo, em algumas versões do Firefox, podemos fazer o pedido xhr com mozBackgroundRequest, mas nos outros navegadores ?? aqui, há um link interessante com esse problema no Chromium.

Eu tenho esse mesmo problema com MVC 5 e VPN, onde sempre que estamos fora do DMZ usando a VPN, nos encontramos ter que responder a esta mensagem do navegador. Usando .net eu simplesmente manipulo o roteamento do erro usando

    

até agora, funcionou porque a ação Index sob o controlador home valida o usuário. A exibição nesta ação, se o logon não for bem-sucedida, possui controles de login que eu uso para fazer o login do usuário usando a consulta LDAP passada nos Serviços de Diretório:

  DirectoryEntry entry = new DirectoryEntry("LDAP://OurDomain"); DirectorySearcher Dsearch = new DirectorySearcher(entry); Dsearch.Filter = "(SAMAccountName=" + UserID + ")"; Dsearch.PropertiesToLoad.Add("cn"); 

Enquanto isso tem funcionado bem até agora, e devo deixar você saber que ainda estou testando e o código acima não teve razão para executar, então está sujeito a remoção … o teste atualmente inclui a tentativa de descobrir um caso em que o segundo conjunto de código é de mais uso. Mais uma vez, este é um trabalho em andamento, mas como poderia ser de alguma ajuda ou fazer algumas idéias para o seu cérebro, eu decidi adicioná-lo agora … Vou atualizá-lo com os resultados finais assim que todos os testes forem feitos.

Para aqueles unsing C # aqui é ActionAttribute que retorna 400 vez de 401 , e ‘engole’ diálogo de autenticação básica.

 public class NoBasicAuthDialogAuthorizeAttribute : AuthorizeAttribute { protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { base.HandleUnauthorizedRequest(filterContext); filterContext.Result = new HttpStatusCodeResult(400); } } 

Use como segue:

 [NoBasicAuthDialogAuthorize(Roles = "A-Team")] public ActionResult CarType() { // your code goes here } 

Espero que isso economize algum tempo.

Eu estou usando o Node, Express e Passport e estava lutando com o mesmo problema. Eu tenho que trabalhar explicitamente configurando o header www-authenticate para uma string vazia. No meu caso, ficou assim:

 (err, req, res, next) => { if (err) { res._headers['www-authenticate'] = '' return res.json(err) } } 

Espero que ajude alguém!