The order of UseCors and UseStaticFiles matters
We have already created a project, and you can obtain it from the downloads attached to this tutorial. I will now explain how the order of UserCors and UseStaticFiles affects the cross-origin behavior.
First of all open the solution explorer. We have added a folder called wwwroot to hold the static files. It contains a CSS file, as well as a JS file that we shall later try to access cross-origin.
Next open the program.cs file. Let's see it line-by-line.
First three lines are the usual code. After that we have defined a default cross-origin policy to allow cross origin requests from a third-party website.
The call to UseStaticFiles precedes UseCors - which means that static files will not be accessible cross-origin, even if done from the third-party site.
// UseStaticFiles precedes UseCors // so cross-origin policy will be ignored using Microsoft.AspNetCore.Cors.Infrastructure; var builder = WebApplication.CreateBuilder(); builder.Services.AddRazorPages(); builder.Services.AddCors(options => { options.AddDefaultPolicy ( policy => { policy.WithOrigins("https://hoven.in"); }); }); var app = builder.Build(); app.UseStaticFiles(); // applies the default policy to all files app.UseCors(); app.MapRazorPages(); app.Run();
Run the project and allow the home page to open.
Open the command prompt and type the following curl command.
// type in one single line curl -i https://localhost:7276/css/site.css -H "origin:https://hoven.in" // response headers // cross-origin request fails HTTP/1.1 200 OK Content-Length: 57 Content-Type: text/css Date: Wed, 17 Aug 20... Server: Kestrel Accept-Ranges: bytes ETag: "1d8b1f7826316b9"
Hit enter to receive the response. We observe that there is no header for allow-cross-origin-requests. Thus, static files are not accessible even to the permitted origins.
Next let us change the precedence by moving UseCors before UseStaticFiles as you see here.
Now again run the project. And, again open the command prompt and type the same curl command again.
// CSS file test // type in one single line curl -i https://localhost:7276/css/site.css -H "origin:https://hoven.in" // cross-origin request succeeds HTTP/1.1 200 OK Content-Length: 57 Content-Type: text/css Date: Wed, 17 Aug 20... Server: Kestrel Accept-Ranges: bytes Access-Control-Allow-Origin: https://hoven.in ETag: "1d8b1f7826316b9"
This time the header Access-Control-Allow-Origin is sent by the server - which means the CORS policy was applied.
Let's also make a request to the javascript file.
// JS file test // type in one single line curl -i https://localhost:7276/css/site.js -H "origin:https://hoven.in" // cross-origin request succeeds HTTP/1.1 200 OK Content-Length: 57 Content-Type: text/javascript Date: Wed, 17 Aug 20... Server: Kestrel Accept-Ranges: bytes Access-Control-Allow-Origin: https://hoven.in ETag: "1d8b1f7826316b9"
We observe that the header Access-Control-Allow-Origin is again sent by the server - which means the CORS policy was applied to this JS file also.
Video Explanation (see it happen!)
Please watch the following youtube video:
The Problem Statement
It appears that there is no method to exclude some files while including others at the same time.
The problem, therefore, is how to apply CORS policy only to a specific CSS file or, say, to a given folder, while excluding the JS file.
The Solution
To solve this problem, start by defining a policy that will apply to the CSS file or that folder. After that use the OnPrepareResponse property to apply this policy when that resource is fetched.
Open the solution explorer and modify the program.cs file. I will now explain it line by line.
First add a named policy to the services collection. This policy allows cross-origin requests from a third party website.
Next call UseStaticFiles with an overload that accepts StaticFileOptions, and set the OnPrepareResponse property. The handler is used to add or change the response headers.
An if condition compares the name or path of the requested resource. We can now filter out all files except the CSS file we want to be accessible cross-origin.
First extract two cross-origin services from the services container. Then obtain the named cross-origin CorsPolicy. This is the policy that we want to apply to this request.
Construct a cross-Origin CorsResult based on this policy, and apply it to the response. Everything else is taken care of by the code executing behind the scenes.
using Microsoft.AspNetCore.Cors.Infrastructure; var builder = WebApplication.CreateBuilder(); builder.Services.AddRazorPages(); const string POLICY_CSS = "PolicyCSS"; builder.Services.AddCors(options => { options.AddPolicy(POLICY_CSS, policy => { policy.WithOrigins("https://hoven.in"); }); }); var app = builder.Build(); app.UseStaticFiles(options: new StaticFileOptions() { OnPrepareResponse = async ctx => { const String CSS_CORS = "site.css"; if (CSS_CORS.Equals(ctx.File.Name)) { // get services var _corsPolicyProvider = app.Services.GetRequiredService<ICorsPolicyProvider>(); var _corsSvc = app.Services.GetRequiredService<ICorsService>(); // extract the policy for this CSS var policy = await _corsPolicyProvider .GetPolicyAsync(ctx.Context, POLICY_CSS); // apply this is the main part if (policy != null) { CorsResult corsResult = _corsSvc.EvaluatePolicy(ctx.Context, policy); _corsSvc.ApplyResult(corsResult, ctx.Context.Response); } } } } ); app.UseCors(); app.MapRazorPages(); app.Run();
Run the Project
Run the project again. And again open the command prompt and make a request to the CSS file.
// type in one single line curl -i https://localhost:7276/css/site.css -H "origin:https://hoven.in" // response // cross-origin request succeeds HTTP/1.1 200 OK Content-Length: 57 Content-Type: text/css Date: Wed, 17 Aug 20... Server: Kestrel Accept-Ranges: bytes Access-Control-Allow-Origin: https://hoven.in ETag: "1d8b1f7826316b9"
We observe that the Access-Control-Allow-Origin header is now present, as expected.
Let's finally verify if the JS file is now blocked from cross-site access.
Run the project again. And again open the command prompt and make a request to the JS file.
// JS file NOT accessible cross origin // type in one single line curl -i https://localhost:7276/css/site.js -H "origin:https://hoven.in" // repsonse // Access-Control-Allow-Origin is absent! // cross-origin request fails HTTP/1.1 200 OK Content-Length: 22 Content-Type: application/javascript Date: Wed, 17 Aug 2022 14:25:02 GMT Server: Kestrel Accept-Ranges: bytes ETag: "1d8b24405aa5996"
We observe that the Access-Control-Allow-Origin header is absent, as expected. Thus we have learnt how to selectively allow cross origin requests to static files like CSS and JS files. Thanks!
This Blog Post/Article "(CORS C# ASP.NET Core) Enabling CORS for Specific CSS or JS Files" by Parveen is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.