ASP.NET Core アプリを HTTP.sys でホストして Windows 認証を使用するメモ

外に公開する Web アプリなら、ASP.NET Core Identity や JWT Bearer 認証を採用するんだけど、社内で使う用だとユーザー管理がめんどい。Windows 認証の方が都合がいい。クライアントはほぼ全て Windows だし、Active Directory で管理してるからなおさら。

作成した Web アプリを IIS でホストするのが定石なところを、自己完結型アプリとして動かしたかったので、HTTP.sys でのホストを試してみた。コピペでデプロイできる手軽さは重要でしょ。

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Server.HttpSys;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace HttpSysSample
{
    [ApiController]
    [Route("api/[controller]")]
    public class HomeController : ControllerBase
    {
        [HttpGet("anonymous")]
        public IActionResult Anonymous()
        {
            var user = User.Identity;
            return Ok(new
            {
                user.Name,
                user.IsAuthenticated,
                user.AuthenticationType,
            });
        }

        [Authorize]
        [HttpGet("windows")]
        public IActionResult Windows()
        {
            var user = User.Identity;
            return Ok(new
            {
                user.Name,
                user.IsAuthenticated,
                user.AuthenticationType,
            });
        }
    }

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            // Authorize 属性を付けたアクションだけ認証必須にしたい場合は
            // HTTP.sys 用の認証スキーマを登録しておく必要がある。
            services.AddAuthentication(HttpSysDefaults.AuthenticationScheme);

            services.AddMvc()
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseMvc();
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .UseHttpSys(options =>
                {
                    // Windows 認証を有効にする
                    options.Authentication.Schemes = AuthenticationSchemes.NTLM | AuthenticationSchemes.Negotiate;

                    // Authorize 属性を付けたアクションだけ認証必須にしたいので、
                    // 匿名アクセスを許可する
                    options.Authentication.AllowAnonymous = true;
                });
    }
}

Web アプリを実行し、まずは匿名利用可能な API に Web ブラウザからアクセスしてみると、 認証されていないユーザーを表す JSON が表示された。

f:id:griefworker:20190108135356p:plain

次に Windows 認証が必要な API にアクセスすると、認証ダイアログが表示された。

f:id:griefworker:20190108135407p:plain

Window アカウントの名前とパスワードを入力して OK を押すと、認証に成功し、Window アカウントの名前を含む JSON が表示された。

f:id:griefworker:20190108135418p:plain