web-dev-qa-db-fra.com

Réponse 401 pour la demande CORS dans IIS avec Windows Auth activé

J'essaie d'activer la prise en charge CORS dans mon projet WebAPI, et si j'active l'authentification anonyme, alors tout fonctionne bien, mais avec Windows Auth + désactivé l'authentification anonyme, la demande OPTIONS envoyée renvoie toujours une réponse non autorisée 401. Le site qui le demande se trouve sur le DOMAINE devrait donc pouvoir passer l'appel, existe-t-il un moyen de contourner le problème sans désactiver l'authentification Windows?

37
dariusriggins

Depuis MS:

Si vous désactivez l'authentification anonyme, c'est par conception que IIS renverrait un 401 à n'importe quelle demande. S'ils ont activé l'authentification Windows, la réponse 401 dans ce cas aurait un en-tête WWW-Authenticate pour permettre le client pour démarrer une négociation d’authentification. La question devient alors de savoir si le client que le client utilise peut effectuer l’authentification Windows ou non.

Enfin, il semble qu'il puisse y avoir une question sous-jacente de savoir s'il est possible ou non de configurer une URL de telle sorte que l'accès anonyme soit autorisé pour un verbe (OPTIONS, dans ce cas), mais nécessite une authentification Windows pour les autres verbes. IIS ne prend pas cela en charge par une configuration simple. Il peut être possible d'obtenir ce comportement en activant à la fois l'authentification anonyme et Windows, en définissant des ACL sur le contenu qui refuse l'accès à l'utilisateur anonyme, puis en configurant le gestionnaire mappant l'URL en question afin qu'il ne vérifie pas l'existence du fichier associé à l'URL. Mais il faudrait un peu de jeu pour le confirmer.

14
dariusriggins

Vous ne pouvez autoriser que le verbe OPTIONS pour les utilisateurs anonymes.

<system.web>
  <authentication mode="Windows" />
    <authorization>
      <allow verbs="OPTIONS" users="*"/>
      <deny users="?" />
  </authorization>
</system.web>

Selon les spécifications du W3C, le navigateur exclut les informations d'identification de l'utilisateur du contrôle en amont CORS: https://dvcs.w3.org/hg/cors/raw-file/tip/Overview.html#preflight-request

37
Jan Remunda

Plusieurs années plus tard, mais grâce à la réponse de @dariusriggins et @ Lex-li, j'ai réussi à ajouter le code suivant à mon Global.asax:

    public void Application_BeginRequest(object sender, EventArgs e)
    {
        string httpOrigin = Request.Params["HTTP_Origin"];
        if (httpOrigin == null) httpOrigin = "*";
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin);
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Token");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");

        if (Request.HttpMethod == "OPTIONS")
        {
            HttpContext.Current.Response.StatusCode = 200;
            var httpApplication = sender as HttpApplication;
            httpApplication.CompleteRequest();
        }
    }

httpOrigin est en fait recherché dans une liste d'hôtes autorisés mais cela complique les choses. Cela signifie que toutes les autres demandes sont validées mais les options ne font que revenir.

Merci pour cette question, j'aurais été perdu sans ça!

22
Stu

Le moyen le plus simple de résoudre ce problème est de créer une règle de réécriture avec la condition request_method = ^ OPTIONS $. Définissez ensuite l'action comme une réponse personnalisée, définissez-la sur 200 OK. Ensuite, toutes les demandes d'options répondront avec 200 au lieu de 401. Cela résoudra le problème CORS.

Bien sûr, vous devez toujours vous assurer que vous disposez des en-têtes de demande Cross Origin corrects.

Cela empêchera les demandes d'options (qui n'ont pas d'informations d'identification) de répondre avec 401 lorsque l'authentification intégrée est activée.

4
Luke Basil

La réponse acceptée est correcte mais j'ai été en train de dépanner une api de repos avec une configuration "nœud avec iisnode et module npm cors" pendant un certain temps et n'était pas à l'aise avec l'activation de l'authentification anonyme pour tous les utilisateurs. Puisqu'il s'agit d'une application de nœud, la balise system.web ne fait pas grand-chose. Je me suis retrouvé avec l'ajout suivant au web.config:

<system.webServer>
<security>
  <requestFiltering>
    <hiddenSegments>
      <add segment="node_modules" />
    </hiddenSegments>
  </requestFiltering>
  <authorization>
    <add accessType="Allow" verbs="OPTIONS" users="?" />
    <add accessType="Deny" verbs="GET, PUT, POST, DELETE" users="?" />
  </authorization>
</security>
</system.webServer>
4
mrplatina

J'ai rencontré le même problème aujourd'hui en raison d'un bogue dans IE 10 et 11 , j'utilise ServiceStack au lieu de WebApi, mais l'approche peut également fonctionner pour vous.

  1. Activation de l'authentification Windows intégrée et anonyme sur IIS Site Web.
  2. Disposez d'une série de filtres sur le pipeline ServiceStack,
    • Pour le traitement des demandes Cors et OPTIONS, Sur demande Options, j'ajoute les en-têtes nécessaires et termine la demande,
    • Filtre de vérification incluant HttpRequest est authentifié ?,
    • filtre etc.,

Après avoir traversé tous les filtres, il exécute le service.

CorsFeature.cs

AuthenticateFilter

Dans mon AppHost,

appHost.Plugins.Add(new CorsFeature());

appHost.RequestFilters.Add(AuthenticateFilter.Authenticate);

J'ai modifié le CorsFeature pour gérer les OptionsRequest en plus d'ajouter des en-têtes, Authenticate Filter pour vérifier les demandes authentifiées!

3
Sathish Naga

Question connexe: IIS détourne la demande OPTIONS de contrôle en amont CORS

Fusion des informations à partir des réponses trouvées à plusieurs endroits. Si vous devez activer CORS sur une méthode de page ASP.net avec l'authentification Windows sur l'intranet, c'est ce qui semble fonctionner. Sans les modifications apportées à web.config, cela ne fonctionne pas.

Vous devez l'ajouter à Global.asax

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        string httpOrigin = HttpContext.Current.Request.Params["HTTP_Origin"] ?? HttpContext.Current.Request.Params["Origin"] ?? "*";
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin);
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Token");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");

        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        {
            HttpContext.Current.Response.StatusCode = 200;
            var httpApplication = sender as HttpApplication;
            httpApplication.CompleteRequest();
        }
    }

Et ceci à web.config

 <system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." 
           verb="*" type="System.Web.Handlers.TransferRequestHandler" 
           preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>
3
Shiroy

Je comprends que c'est une vieille question avec plusieurs solutions possibles (ainsi que d'autres questions), mais au cas où quelqu'un d'autre rencontrerait cela, IIS CORS 1.0 est disponible à partir de novembre '17:

https://blogs.iis.net/iisteam/introducing-iis-cors-1-

https://docs.Microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference

Vous pouvez le télécharger via IIS Windows Platform Installer (WPI). Cela devrait résoudre bon nombre de vos problèmes d'authentification CORS. Profitez-en!

1
Inphinite Phractals

J'utilise l'API Web et OWIN et j'ai essayé toutes les solutions suggérées, mais la seule chose qui a fonctionné était la suivante

//use it in your startup class
app.Use((context, next) =>
{
    if (context.Request.Headers.Any(k => k.Key.Contains("Origin")) && context.Request.Method == "OPTIONS")
    {
        context.Response.StatusCode = 200;
        context.Response.Headers.Add("Access-Control-Allow-Origin", new string[1] { "ALLOWED_Origin" });
        context.Response.Headers.Add("Access-Control-Allow-Headers", new string[4] { "Origin", "X-Requested-With", "Content-Type", "Accept" });
        context.Response.Headers.Add("Access-Control-Allow-Methods", new string[5] { "GET", "POST", "PUT", "DELETE", "OPTIONS" });
        context.Response.Headers.Add("Access-Control-Allow-Credentials", new string[1] { "true" });

        return context.Response.WriteAsync("");
    }

    return next.Invoke();
});

//this is important! Without it, it didn't work (probably because the middleware was too late)
app.UseStageMarker(PipelineStage.Authenticate);

vous devez insérer ce code quelque part dans l'une de vos classes de démarrage OWIN. Il est important d'appeler app.UseStageMarker(PipelineStage.Authenticate) car sinon la vérification en amont a échoué. Plus d'informations sur UseStageMarker -> https://docs.Microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline

Il est également important de définir explicitement les en-têtes autorisés. Il échouera si vous utilisez * Comme espace réservé.

Peut-être que cela aide quelqu'un.

1
Arikael

Ce qui a fonctionné pour moi (lorsque je travaille avec AngularJS ou JQuery) est d'ajouter withCredentials: fidèle à chaque requête sur le client:

$http.get("http://localhost:88/api/tests", {withCredentials :true})

Et l'activation de CORS sur le serveur, cela a été fait avec Microsoft.Owin.Cors de nuget et en l'ajoutant au démarrage comme ci-dessous:

public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();

        ConfigureOAuth(app);

        WebApiConfig.Register(config);
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        app.UseWebApi(config);

    }

Les références:

0
Philip Patrick

Extension de la réponse fournie par @dariusriggins. Consultez cet article: Microsoft | Développeur: Tout mettre ensemble - tutoriel CORS

Pour les configurations IIS:

Règle d'autorisation

Authorization rule

Étape d'autorisation (ou événement d'autorisation), nous devons nous assurer que nous n'autorisons que les demandes anonymes du contrôle en amont CORS et que toutes les autres demandes entrantes ont des informations d'authentification fournies. Nous pouvons y parvenir grâce aux règles d'autorisation. Une règle d'autorisation par défaut accordant à tous les utilisateurs l'accès au site est déjà en place et fournie par défaut par IIS. Nous commencerons par modifier cette règle pour n'autoriser que les utilisateurs anonymes, s'ils envoient des requêtes utilisant le verbe http OPTIONS. Vous trouverez ci-dessous la configuration cible dans IIS pour cette règle d'autorisation:

Modifier la règle d'autorisation

Edit Authorization rule

0
SubodhW