title: In Owin web application, how to protect static files using Cookie Authentication?
body: <p>What I'm trying to do is very simple, at least so it seemed at first.</p>
  <p>I need to protect static HTML files (and possibly other static resources) behind simple Cookie Authentication. Any request to these files from user agent without carrying authentication cookie should be rejected with return HTTP 401 status code.</p>
  <p>And I need to do this on top of Owin because of project restriction. I'm dealing with legacy project which have not yet migrate to ASP.NET Core.</p>
  <p>Here's my Project directory structure.</p>
  <pre><code>OwinWebProject
  |- wwwroot
  |  |- index.html
  |  |- login.html
  |- Startup.cs
  |- Web.config
  </code></pre>
  <p>Below is my Owin Startup class. What I do here is handling these paths:</p>
  <ul>
  <li><code>/login</code> which simply establish wrap some simple claims in an identity, and then tells the Authentication Manager to set the authentication state if that identity as 'logged in'. No actual identity checks here for simplicity</li>
  <li><code>/logout</code> does the opposite of <code>/login</code>. It clears the authentication state.</li>
  <li><code>/secret</code> to test whether <code>/login</code> and <code>/logout</code> works</li>
  <li><code>/hello</code> just for testing if Owin middlewares are properly configured.</li>
  </ul>
  <p>I also use <code>Microsoft.Owin.StaticFiles.FileServerExtensions</code> to serve my static files.</p>
  <pre class="lang-cs prettyprint-override"><code>// using statements omitted 
  
  [assembly: OwinStartup(typeof(OwinWebProject.Startup))]
  namespace OwinWebProject
  {
      public class Startup
      {
          public void Configuration(IAppBuilder app)
          {
  
              // BEGIN Configure Cookie Authentication
              app.UseCookieAuthentication(new CookieAuthenticationOptions
              {
                  CookieName = &quot;MyApp&quot;,
                  AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                  SlidingExpiration = true,
              });
              // END Configure Cookie Authentication
  
              // BEGIN Configure File Server to serve static resources
              var wwwRootFS = new PhysicalFileSystem(@&quot;.\wwwroot&quot;);
              var fileServerOpts = new FileServerOptions
              {
                  EnableDefaultFiles = true,
                  FileSystem = wwwRootFS,
              };
              fileServerOpts.DefaultFilesOptions.DefaultFileNames = new[] { &quot;index.html&quot; };
              fileServerOpts.StaticFileOptions.ServeUnknownFileTypes = true;
              app.UseFileServer(fileServerOpts);
              // END Configure File Server
  
  
              // BEGIN create route handlers for 
              // setting the auth state (i.e logging in), 
              // clearing the auth state (i.e logging out),
              // and for testing authentication state
   
              // this route is unguarded
              app.Map(&quot;/hello&quot;, (config) =&gt; 
                  config.Run(context =&gt; {
                      return context.Response.WriteAsync(&quot;It works!&quot;);
                  })
              );
  
  
              // this route is for testing authentication state
              app.Map(&quot;/secret&quot;, (config) =&gt;
                  config.Run(context =&gt; {
                      if (context.Request.User == null || !context.Request.User.Identity.IsAuthenticated)
                      {
                          context.Response.StatusCode = 401;
                          return Task.FromResult(0);
                      }
                      return context.Response.WriteAsync(&quot;If you can read this, it means you have logged in&quot;);
                  })
              );
  
  
              // this route is for setting the authentication state
              app.Map(&quot;/login&quot;, (config) =&gt;
                  config.Run(context =&gt; { 
                      var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationType);
                      identity.AddClaim(new Claim(ClaimTypes.Name, &quot;fakeuser&quot;));
                      var authManager = context.Authentication;
                      authManager.SignIn(identity);
                      context.Response.Redirect(&quot;/index.html&quot;);
                      return Task.FromResult(0);
                  })
              );
  
              // this route is for clearing the authentication state
              app.Map(&quot;/logout&quot;, (config) =&gt;
                  config.Run(context =&gt; {
                      var authManager = context.Authentication;
                      authManager.SignOut(CookieAuthenticationDefaults.AuthenticationType);
                      context.Response.Redirect(&quot;/&quot;);
                      return Task.FromResult(0);
                  })
              );
  
              // END create route handlers
  
          }
      }
  }
  
  </code></pre>
  <p>Here is index.html.</p>
  <pre class="lang-html prettyprint-override"><code>&lt;html&gt;
  &lt;body&gt;
  If you can see this that mean you are authenticated
  
  &lt;p&gt;&lt;a href=&quot;/logout&quot;&gt;Logout&lt;/a&gt;&lt;/p&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  <p>Here is login.html</p>
  <pre class="lang-html prettyprint-override"><code>&lt;html&gt;
  &lt;body&gt;
  &lt;p&gt;&lt;a href=&quot;/login&quot;&gt;Click here to log in&lt;/a&gt;&lt;/p&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  <p>Requesting '/secret' without first requesting '/login' will give me HTTP 401 Unauthorized because I can easily check for authentication state in the path handler and respond accordingly. This means my Cookie Authentication setting works.</p>
  <p>If I want, I can even configure CookieAuthenticationOptions to automatically replace the HTTP 401 with HTTP redirects to login page, but this is not my current problem.</p>
  <p>My problem is, is there a way to also enforce the same authentication for all static contents under wwwroot?</p>
  <p>To add, another further question is how to exclude just some static resources. Because obviously from above example, login.html should not be protected by authentication.</p>