web-dev-qa-db-fra.com

Authentification Javascript/Ajax NTLM

Je développe une application mobile HTML5, qui communique avec WebServices. Les services Web utilisent le protocole d'authentification NTLM. J'ai des difficultés à gérer la poignée de main via JavaScript. NTLM envoie le 401 unauthorized en réponse à mon POST, auquel je n’ai trouvé aucun moyen de répondre. 

L'authentification NTLM est-elle possible avec JavaScript? Devrais-je créer un service Web proxy avec par exemple authentification de base entre-deux?

mon appel jQuery ressemble à quelque chose comme ...

$.ajax({
                    type: "POST",
                    url: URL,
                    contentType: "text/xml",
                    dataType: "xml",
                    data: soapRequest,
                    username: 'username',
                    password: 'password',
                    xhrFields: {
                        withCredentials: true
                    },
                    success: processSuccess,
                    error: processError
});
16
TryCatch

Pour autant que je sache, personne n’a implémenté l’authentification Windows Integrated/NTLM avec AJAX, même si cela devrait être possible (j’envisage de le faire pour un projet en cours en combinant l’authentification de formulaire avec WindowsTokenRoleProvider).

Le flux de travail de basedevraitcomme celui-ci (basé sur des articles ici et ici ):

  1. faire une demande GET avec un message NTLM de type 1 codé en base64 dans l'en-tête "Authorization"
  2. extraire le message NTLM de type 2 codé en base64 de l'en-tête "WWW-Authenticate" de la réponse 401.
  3. effectuer l'opération NTLM sur le noonce reçu à l'étape précédente (désolé, je n'ai pas encore d'exemple de code)
  4. effectuez une opération GET finale avec un message NTLM de type 3 de type 3 codé en base64 dans l'en-tête "Autorisation". Cela devrait retourner un 200.

L'authentification NTLM sur HTTP est davantage une implémentation CHAP utilisant HTTP qu'une demande HTTP autorisée.

Je vous tiendrai au courant si je parviens réellement à mettre cela en œuvre. Désolé je ne pourrais pas être plus d'aide.

4
Doct0rZ

Vous n'êtes pas obligé de répondre au défi NTLM (authentification Windows intégrée), votre navigateur doit le faire pour vous, s'il est correctement configuré. Un certain nombre de complications supplémentaires sont également probables.

Étape 1 - Navigateur

Vérifiez que le navigateur peut accéder à vos informations d'identification et les envoyer avec une application Web NTLM ou en accédant d'abord au logiciel que vous développez directement.

Étape 2 - Attribut JavaScript withCredentials

Le 401 Unauthorized error reçu et les symptômes décrits sont exactement les mêmes quand je n'avais pas réussi à définir l'attribut 'withCredentials' sur 'true'. Je ne suis pas familier avec jQuery, mais assurez-vous que votre tentative de définition de cet attribut réussit.

Cet exemple fonctionne pour moi:

var xhttp = new XMLHttpRequest();
xhttp.open("GET", "https://localhost:44377/SomeService", true);
xhttp.withCredentials = true;
xhttp.send();
xhttp.onreadystatechange = function(){
  if (xhttp.readyState === XMLHttpRequest.DONE) {
    if (xhttp.status === 200)
      doSomething(xhttp.responseText);
    else
      console.log('There was a problem with the request.');
  }
};

Étape 3 - Activer CORS côté serveur (Facultatif)

Je suppose que l'une des principales raisons pour lesquelles les gens se retrouvent ici à cette question est qu'ils développent un composant sur leur poste de travail avec un autre composant hébergé ailleurs. Cela provoque le partage de ressources d'origine croisée (CORS) problèmes. Il y a deux solutions:

  1. Désactivez CORS dans votre navigateur - bon pour le développement lorsque votre travail sera finalement déployé sur la même origine que la ressource à laquelle votre code a accès.
  2. Activez CORS sur votre serveur - il y a beaucoup de lecture sur l'internet plus large, mais cela implique essentiellement d'envoyer des en-têtes permettant à CORS.

En bref, pour activer CORS avec les informations d'identification vous devez:

  • Envoyez un en-tête "Access-Control-Allow-Origin" qui correspond à l'origine de la page servie ... il ne peut s'agir de "*"
  • Envoyer un 'Access-Control-Allow-Credentials' avec la valeur 'true'

Voici mon exemple de code .NET de travail dans mon fichier global.asax. Je pense que c'est assez facile de voir ce qui se passe et de le traduire dans d'autres langues si nécessaire.

void Application_BeginRequest(object sender, EventArgs e)
{
    if (Request.HttpMethod == "OPTIONS")
    {
        Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
        Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
        Response.AddHeader("Access-Control-Max-Age", "1728000");
        Response.End();
    }
    else
    {
        Response.AddHeader("Access-Control-Allow-Credentials", "true");

        if (Request.Headers["Origin"] != null)
            Response.AddHeader("Access-Control-Allow-Origin" , Request.Headers["Origin"]);
        else
            Response.AddHeader("Access-Control-Allow-Origin" , "*"); // Last ditch attempt!
    }
}
3
QA Collective

Le problème est que vous ne pouvez pas obtenir le domaine/utilisateur actuellement connecté via javascript (ou si vous le pouvez, je n'ai jamais trouvé de solution).

Si vous connaissez déjà le domaine, le nom d'utilisateur et le mot de passe, vous pouvez utiliser quelque chose du type https://github.com/erlandranvinge/ntlm.js/tree/master

Cependant, je pense que l’utilisation de cette méthode d’authentification unique sera frustrante à long terme.

Nous avons fini par authentifier NTLM dans une iframe cachée et y accéder via javascript.

2
Ridgway

Oui, NTLM n'est pas très amusant. Mais vous voudrez peut-être essayer ceci, https://github.com/tcr/node-ntlm/blob/master/README.md

0
MinimalMaximizer