0

I am currently trying to enable Windows Integrated Authentication for my ASP.NET Core 5.0 Web-App in IIS 10. The basic setup for Integrated Authentication is well documented and was fairly easy to implement. But my Web-App has an ApiController, that contains some Actions which i want unauthenticated users to be able to use.

In this Microsoft documentation, it states that i can enable both Anonymous Auth and Integrated Auth on my IIS Webpage and then work with [AllowAnonymous] and [Authorize] Attributes in my MVC controllers.

I did additional research on the web and found a lot of SO and other forum's discussions about this topic, of which most date back to around 2010 and might be outdated, while the linked documentation is from 2021 and therefore should be more up-to-date. The consensus on the discussion threads and blogs i found was that this is not possible. And as i tried myself i also came to the conclusion that Anonymous Auth always takes precedence over Integrated Auth and completely cancels it out.

So, is the MS documentation just wrong here or am i missing something?

TostMaster
  • 164
  • 2
  • 9

1 Answers1

0

Ok, i figured it out after finding this question.

Anonymous and Integrated Authentification can in fact be used together. But you have to do a little bit of the work in your own code.

You have to enable both Authentication Types in IIS, which makes every request getting treated like an anonymous request by default. Then, you register a Middleware in your request pipeline that looks for an [Authorize] Attribute at the called Controller and Action. If you find one, you challenge the client to provide Windows login information. Just make sure that you register the Middleware after app.UseRouting(); and before app.UseAuthentication/app.UseAuthorization in your request pipeline.

This is the code i used for the Middleware, i hope it helps someone:

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RProcessServiceCore.Code
{
    public class SingleSignOnMiddleware
    {
        private readonly RequestDelegate next;

        public SingleSignOnMiddleware(RequestDelegate next)
        {
            this.next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            if (!context.User.Identity.IsAuthenticated)
            {
                Endpoint endpoint = context.GetEndpoint();
                if(endpoint != null)
                {
                    foreach (var meta in context.GetEndpoint().Metadata)
                    {
                        if (meta is AuthorizeAttribute)
                        {
                            await context.ChallengeAsync("Windows");
                            return;
                        }
                    }
                }
            }
            await next.Invoke(context);
        }
    }
}

As you can see, I use context.GetEndpoint().Metadata. This is a collection of various metadata elements, including attributes that decorate the called controller and action. So you can just search for an object of Type AuthorizeAttribute in there.

This approach achieves Windows Authentication being enforced on all Controllers and Actions decorated with [Authorize], but allowing anonymous request on Controllers and Actions without this attribute. This approach also allows anonymous access on files in your wwwroot.

TostMaster
  • 164
  • 2
  • 9