[解決][ASP.NET Core 5]CookieOptions.HttpOnly=falseを指定してもcookieがhttponlyになる現象

# 現象
```CookieOptions.HttpOnly = false``` が適用されず、ブラウザにhttponly属性が付与されたset-cookieが返る為、JavaScriptからcookieが取得できない。

## 環境
ASP.NET Core 5

## そもそもの目的
- AntiForgery用のリクエスト・トークンを非同期通信(ajax)の際にも更新したい。
- その為に、XSRF-TOKENをcookieとして返却し、それをJavaScript側で読み取ってリクエスト・ヘッダー('X-XSRF-TOKEN')に追加する仕組みを作った。これはAngularやaxiosがサポートしているものと同じ仕組みである。
- しかし、なぜかJavaScript側でcookieの取得に失敗する。
- ネットワーク状態を確認すると、XSRF-TOKENにhttponly属性が付加されていた。
- サーバ側では、```CookieOptions.HttpOnly = false``` は指定している。
- 何が起きているのか？（この記事の主旨）

## 原因
サーバ側で以下のように指定されていた為、CookieOptionsの指定に関係なく、cookieの戻り値が強制的にhttponlyになっていた。

```C#
services.Configure<CookiePolicyOptions>(options => options.HttpOnly = HttpOnlyPolicy.Always)
``` 

# 主なソースコード
```C#:AntiforgeryCookieResultFilter
    public class AntiforgeryCookieResultFilter : ResultFilterAttribute
    {
        /// <summary>Antiforgeryリクエストトークン用のcookie名</summary>
        public static string RequestTokenCookieName => "XSRF-TOKEN";    // AngularのXSRFサポート機能に準拠

        /// <summary>Antiforgeryリクエストトークン用のリクエストヘッダ名</summary>
        public static string RequestTokenHeaderName => "X-XSRF-TOKEN";  // AngularのXSRFサポート機能に準拠

        private IAntiforgery antiforgery;
        public AntiforgeryCookieResultFilter(IAntiforgery antiforgery)
        {
            this.antiforgery = antiforgery;
        }

        public override void OnResultExecuting(ResultExecutingContext context)
        {
            if (context.Result is ViewResult || context.Result is JsonResult)
            {
                // Antiforgery用のクッキートークンを生成してクッキーに保存する
                var tokens = antiforgery.GetAndStoreTokens(context.HttpContext);

                // Antiforgery用のリクエストトークンをクッキーに保存する
                context.HttpContext.Response.Cookies.Append(RequestTokenCookieName, tokens.RequestToken, new CookieOptions() { 
                    HttpOnly = false,
                    Secure = true,
                    SameSite = SameSiteMode.Strict
                });
            }
        }
    }
```

```Startup.cs
	// (略)

	services.AddMvc(options => {
		// 既存の処理
		...
		
		// ここでAntiforgeryCookieResultFilterをグローバル登録する
		options.Filters.Add<Filters.AntiforgeryCookieResultFilter>();
	}

	// AntiForgeryの設定
	services.AddAntiforgery(options => 
	{
		// AntiForgeryリクエスト・ヘッダの指定
		options.HeaderName = Filters.AntiforgeryCookieResultFilter.RequestTokenHeaderName;
	});

```

# 原因となった箇所

```Startup.cs

	// CookiePolicy Middleware の設定
	services
	    .Configure<CookiePolicyOptions>(x => {
	    	// 常にHttpOnlyをtrueにする
	        x.HttpOnly = HttpOnlyPolicy.Always;	// ★この箇所が原因で、全てのCookie指定がHttpOnly=trueで上書きされていた
	    });
```

上記を以下のように変更することで、HttpOnlyの個別指定が有効になった。

```Startup.cs

	// CookiePolicy Middleware の設定
	services
	    .Configure<CookiePolicyOptions>(x => {
	    	// HttpOnlyのポリシー指定なし
	        x.HttpOnly = HttpOnlyPolicy.None;
	    });
```

もちろん、この変更を行う前に「**そもそもなぜHttpOnlyPolicy.Alwaysが指定されていたのか**」をよく調査する必要がある。
この変更によって、それまでそのシステムの他の部分で設定していたクッキーについてもこのクッキーポリシーに従うようになる為、HttpOnlyの指定を省略していた箇所があるのであれば、適切に```HttpOnly = true```を指定する必要があるかを判断し、個別に指定する必要がある。

# 補足
上記のクッキーポリシーを```HttpOnlyPolicy.Always```にしつつ、任意の箇所だけ個別に ```HttpOnly = false``` にする方法があるのであれば知りたいが、いろいろ調べたり試したりしたところではどのようにしても ```HttpOnlyPolicy.Always``` が優先されてしまい、```false```で上書きすることはできなかった。

ネットを見ると、「**HttpOnly=falseにしても、勝手にhttponly属性がついてしまう**」と嘆いている投稿が散見されるので、そういう人たちの一助になれば幸いである。