CORS pre-validation request responds with 302 redirect in Azure web UI

Scenario:

I have two ASP.NET web applications hosted separately in Windows Azure and both associated with the same Azure Active Directory tenant:

  • An MVC application with the AngularJS SPA interface and adal.js library for processing Azure AD authentication on the client.

  • Web API with Microsoft OWIN middleware for processing Azure AD authentication on a server.

Problem:

When angular loads the client application, the page loads correctly after redirecting oauth to the corresponding Identity Authority, and the adal.js library correctly extracts and saves different tokens for each application (checked by checking resources / Session Holding tab in Chrome dev tools). But when the client application tries to access or update some data in the API, CORS pre-check requests respond to 302 redirects in the Identity Authority, which leads to the following error in the console:

XMLHttpRequest cannot load https://webapi.azurewebsites.net/api/items . The request was redirected to ' https://login.windows.net/ {authority-guid} / oauth2 / authorize? response_type = id_token & redirect_uri = .... etc..etc .. ", which is prohibited for cross-origin requests requiring preflight protection.

Examples of headers (anonymous):

  Request
 OPTIONS / api / items HTTP / 1.1
 Host: webapi.azurewebsites.net
 Connection: keep-alive
 Access-Control-Request-Method: GET
 Access-Control-Request-Headers: accept, authorization
 Origin: https://mvcapp.azurewebsites.net
 User-Agent: Mozilla / 5.0 (Windows NT 6.3; WOW64) AppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 39.0.2171.99 Safari / 537.36
 Accept: * / *
 Referer: https://mvcapp.azurewebsites.net/

 Response
 HTTP / 1.1 302 Found
 Content-Length: 504
 Location: https://login.windows.net/{authority-guidasket/oauth2/authorize?response_type=id_token&redirect_uri=https%3A%2F%2F....etc..etc.%2F&client_id={api-guid} & scope = openid + profile + email & response_mode = form_post & state = ... etc ...
 Server: Microsoft-IIS / 8.0
 X-Powered-By: ASP.NET
 Set-Cookie: ARRAffinity = 4f51 ... snip .... redact .... db6d; Path = /; Domain = webapi.azurewebsites.net 

What i did / tried

  • Ensure that your Azure AD tenant allows you to use the implicit OAuth2 flow, as described here and elsewhere.
  • Ensure that the API provides access permissions and that MVC / SPA are registered for access using the permissions granted.
  • Explicitly added the OPTIONS verb handler to the web.config API (see below).
  • Various combinations of enabling CORS are used on the API server, OWIN, as well as with EnableCorsAttribute (see below).

Questions

Can I somehow associate the web API with the Azure AD agent with redirection to CORS pre-validation requests? Is there any missing initialization in the adal.js library and / or OWIN startup code (see below)? Are there any settings on the Azure portal that allow OPTIONS requests through the OWIN pipeline?

Relevant Code:

adal.js initialization

angular.module("myApp", ["ngRoute", "AdalAngular"]) .config(["$routeProvider", "$locationProvider", "$httpProvider", "adalAuthenticationServiceProvider", function ($routeProvider, $locationProvider, $httpProvider, adalProvider) { $routeProvider.when("/", { // other routes omitted for brevity templateUrl: "/content/views/home.html", requireADLogin: true // restrict to validated users in the Azure AD tenant }); // CORS support (I've tried with and without this line) $httpProvider.defaults.withCredentials = true; adalProvider.init({ tenant: "contoso.onmicrosoft.com", clientId: "11111111-aaaa-2222-bbbb-3333cccc4444", // Azure id of the web app endpoints: { // URL and Azure id of the web api "https://webapi.azurewebsites.net/": "99999999-zzzz-8888-yyyy-7777xxxx6666" } }, $httpProvider); } ]); 

Initializing OWIN Middleware

 public void ConfigureAuth(IAppBuilder app) { // I've tried with and without the below line and also by passing // in a more restrictive and explicit custom CorsOptions object app.UseCors(CorsOptions.AllowAll); app.UseWindowsAzureActiveDirectoryBearerAuthentication( new WindowsAzureActiveDirectoryBearerAuthenticationOptions { TokenValidationParameters = new TokenValidationParameters { // Azure id of the Web API, also tried the client app id ValidAudience = "99999999-zzzz-8888-yyyy-7777xxxx6666" }, Tenant = "contoso.onmicrosoft.com" } ); // I've tried with and without this app.UseWebApi(GlobalConfiguration.Configuration); } 

WebApiConfig Initialization

 public static void Register(HttpConfiguration config) { // I've tried with and without this and also using both this // and the OWIN CORS setup above. Decorating the ApiControllers // or specific Action methods with a similar EnableCors attribute // also doesn't work. var cors = new EnableCorsAttribute("https://mvcapp.azurewebsites.net", "*", "*") { cors.SupportsCredentials = true // tried with and without }; config.EnableCors(cors); // Route registration and other initialization code removed } 

API OPTIONS register verb handler

 <system.webServer> <handlers> <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <remove name="OPTIONSVerbHandler" /> <remove name="TRACEVerbHandler" /> <add name="OPTIONSHandler" path="*" verb="OPTIONS" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" /> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> </handlers> </system.webServer> 

Related Resources

At one point or another, I tried almost all conceivable combinations of things from the following (and many other) forum and blog posts and github example code.

+5
source share
2 answers

Solved (view)

This seems to be caused by deployment issues, in particular, as I first published apps for Azure. Both applications were originally written using Windows authentication and were deployed to a standard (i.e. not azure) web server. Using these technologies, applications worked properly.

For new business requirements, I worked on migrating them to Azure. The next process I was:

  • Deploy / publish both applications, as originally written, from the Visual Studio 2013 Publishing Wizard directly to Azure. Of course, this broke down, as expected, because they could not communicate with the local Active Directory from Azure.
  • Gradually update the code to remove Windows Auth, and replace it using the Azure AD protocol, following the data from all the links at the end of the question.
  • Manually associate applications with an Azure AD tenant to authenticate using the Azure AD portal.

At some point, I noticed the Enable Organizational Authentication option on the Options tab of the VS Publishing Publishing Wizard and started using it to associate applications with the tenant. Since I already linked them manually, Visual Studio finished creating another application for Azure AD for each result in two.

In the end, this is what he did:

  • All Azure entries for both applications have been removed using the portal, both on the Azure sites themselves and on the Azure AD sites / associations.
  • Reverted all code changes in both applications to their original state.
  • Applications have re-authenticated Azure AD (OWIN, adal.js, etc.).
  • Was there a new publication of both applications to allow VS Wizard to process all Azure associations.
  • Updated Web.config files and initialized adal.js with newly created client identifiers.
  • Published again.

Now preflight OPTIONS requests are no longer redirected 302.

Instead, they are now 405 Method Not Allowed, very similar to this thread . Progress, kind of.

Despite the fact that it still does not work from end to end, I will leave this answer (and not delete the question) in case it can help other users redirect CORS preview to Azure 302.

+3
source

I had similar problems to determine the correct packages for this. All you need is an Owin cors to install. Please check the packages for owin.cors first.

 <package id="Microsoft.Owin" version="3.0.0" targetFramework="net45" /> <package id="Microsoft.Owin.Cors" version="2.1.0" targetFramework="net45" /> 

WebConfig options for handlers:

 <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> 

You are right with the specfiying cors option in owin configuration.

  public void ConfigureAuth(IAppBuilder app) { app.UseWindowsAzureActiveDirectoryBearerAuthentication( new WindowsAzureActiveDirectoryBearerAuthenticationOptions { Audience = ConfigurationManager.AppSettings["ida:Audience"], Tenant = ConfigurationManager.AppSettings["ida:Tenant"] }); app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); } 

The controller does not need CORS related attributes.

  [Authorize] public class ContactsController : ApiController { // GET api/<controller> public IEnumerable<string> Get() { return new string[] { "person1", "person2" }; } // GET api/<controller>/5 public string Get(int id) { return "person" + id; } 

WebAPIConfig does not need a CORS entry.

Working example: https://github.com/omercs/corsapisample

You can check the following code in your application:

 app.factory('contactService', ['$http', function ($http) { var serviceFactory = {}; var _getItems = function () { $http.defaults.useXDomain = true; delete $http.defaults.headers.common['X-Requested-With']; return $http.get('http://yourhostedpage/api/contacts'); }; serviceFactory.getItems = _getItems; return serviceFactory; 

}]);

An example of a pre-flight response:

 Remote Address:127.0.0.1:8888 Request URL:http://localhost:39725/api/contacts Request Method:OPTIONS Status Code:200 OK Request Headersview source Accept:*/* Accept-Encoding:gzip, deflate, sdch Accept-Language:en-US,en;q=0.8 Access-Control-Request-Headers:accept, authorization Access-Control-Request-Method:GET Host:localhost:39725 Origin:http://localhost:49726 Proxy-Connection:keep-alive Referer:http://localhost:49726/myspa.html User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36 Response Headersview source Access-Control-Allow-Credentials:true Access-Control-Allow-Headers:authorization Access-Control-Allow-Origin:http://localhost:49726 Content-Length:0 Date:Fri, 23 Jan 2015 01:10:54 GMT Server:Microsoft-IIS/8.0 X-Powered-By:ASP.NET 
+3
source

Source: https://habr.com/ru/post/1211724/


All Articles