WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

認証チケットの期限切れをユーザーに通知

by WebSurfer 11. May 2024 16:15

ASP.NET Core Identity を使ったユーザー認証システムで認証チケットの有効期限が切れたとき、下の画像のようにユーザーにその旨通知する方法を書きます。

認証チケット有効期限切れの通知

先の記事「ASP.NET Core Identity タイムアウト判定」で書いたこととほぼ同じで、違うのは先の記事ではミドルウェアを使っていたのを Login ページで行うようにし、ターゲットフレームワークを .NET Core 3.1 から .NET 8.0 に変更した点です。

Visual Studio 202 のテンプレートを使って ASP.NET Core Web アプリのプロジェクトを作る際、認証を「個別のユーザーアカウント」に設定すると ASP.NET Core Identity を利用したクッキーベースのユーザー認証が実装されます。

ユーザーがログインに成功すると、サーバーからは応答ヘッダの Set-Cookie に認証チケットを入れて認証クッキーとしてクライアント(ブラウザ)に送信します。

その後は、ブラウザは要求の都度サーバーに認証クッキーを送信するので認証状態が継続されるという仕組みになっています。

認証チケットには有効期限があります (デフォルトで 5 分、SlidingExpiration で延長あり)。一旦認証を受けたユーザーがログオフせずブラウザを立ち上げたまま長時間席を外すなどして、タイムアウトに設定した時間を超えてアクセスしなかった場合を考えてください。

タイムアウトとなった後でユーザーが席に戻ってきて再度どこかのページを要求したとすると、要求したページが匿名アクセスを許可してなければ、ログインページにリダイレクトされます。

その際、ユーザーに認証チケットが期限切れとなっていることを知らせるためには、どのようにできるかということを書きます。

一旦認証を受けたが、認証チケットが期限切れになっているというのは、Web サーバー側では以下の条件で判定できるはずです。

  1. 要求 HTTP ヘッダーに認証クッキーが含まれる。
  2. 認証クッキーの中の認証チケットが期限切れ。

一旦認証クッキーの発行を受ければ、ブラウザを閉じない限り要求の都度サーバーにクッキーを送り続けます。(下の「注 1」に書きましたが、[Remember me?]チェックボックスにチェックを入れて認証を受けた場合は話が違ってくるので注意してください)

Web サーバーが認証クッキーを取得できれば、それを復号して認証チケットを取得し、チケットの中の有効期限の日時の情報を取得できます。それで上記の 2 つの条件を確認できます。

ログインページで条件を確認して、認証チケットが期限切れになっていた場合はこの記事の一番上の画像のようにメッセージを表示してみました。

以下がログインページのコードです。スキャフォールディング機能を利用して自動生成した Login.cshtml.cs, Login.cshtml のコードに手を加えています。(スキャフォールディング方法の詳細は別の記事「ASP.NET Core MVC プロジェクトに Identity 実装」を見てください)

Login.cshtml.cs

コメントで「2024/5/11 追加」としたコードを自動生成された Login.cshtml.cs に追加しています。

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#nullable disable

using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Authentication;
// ・・・中略・・・

namespace MvcNet8App2.Areas.Identity.Pages.Account
{
    public class LoginModel : PageModel
    {
        private readonly SignInManager<ApplicationUser> _signInManager;
        private readonly ILogger<LoginModel> _logger;

        // 2024/5/11 追加(下の「注 2」参照)
        private readonly CookieAuthenticationOptions _options;

        public LoginModel(SignInManager<ApplicationUser> signInManager, 
                          ILogger<LoginModel> logger,

                          // 2024/5/11 追加(下の「注 2」参照)
                          IOptions<CookieAuthenticationOptions> options)
        {
            _signInManager = signInManager;
            _logger = logger;

            // 2024/5/11 追加(下の「注 2」参照)
            _options = options.Value;
        }

        // ・・・中略・・・

        public async Task OnGetAsync(string returnUrl = null)
        {
            // 2024/5/11 追加・・・
            // .AspNetCore.Identity.Application はデフォルトのクッキー名
            string cookie = Request.Cookies[".AspNetCore.Identity.Application"];
            if (!string.IsNullOrEmpty(cookie))
            {
                IDataProtectionProvider provider = 
                                      _options.DataProtectionProvider;

                // 下の「注 3」参照
                IDataProtector protector = provider.CreateProtector(
                    // CookieAuthenticationMiddleware のフルネーム
                    "Microsoft.AspNetCore.Authentication.Cookies." +
                    "CookieAuthenticationMiddleware",
                    // クッキー名 .AspNetCore.Identity.Application から
                    // .AspNetCore. を除去した文字列
                    "Identity.Application",
                    // .NET Framework 版は "v1"、Core 版は "v2"
                    "v2");

                // 認証クッキーから暗号化された認証チケットを復号
                TicketDataFormat format = new TicketDataFormat(protector);

                // 下の「注 3, 4」参照
                AuthenticationTicket authTicket = format.Unprotect(cookie);

                // ユーザー名を取得
                ClaimsPrincipal principal = authTicket.Principal;
                IIdentity identity = principal.Identity;
                string userName = identity.Name!;

                // 認証チケットの有効期限の日時を取得
                AuthenticationProperties property = authTicket.Properties;
                DateTimeOffset? expiersUtc = property.ExpiresUtc;

                // expiresUtc と現在の時刻を比較して期限切れか否かを判定
                if (expiersUtc.Value < DateTimeOffset.UtcNow)

                {
                    ViewData["AuthTicket"] = $"{userName} さん、"+
                      $"認証チケットの有効期限 {expiersUtc.Value} が切れています。";
                }
            }
            // ・・・追加はここまで

            // ・・・中略・・・
        }

        public async Task<IActionResult> OnPostAsync(string returnUrl = null)
        {
            
            // ・・・中略・・・

        }
    }
}

Login.cshtml

認証ケットが期限切れの場合は cshtml から ViewData で情報をもらって期限切れのメッセージを表示するための一行を追加したのみです。

@page
@model LoginModel

@{
    ViewData["Title"] = "Log in";
}

<h1>@ViewData["Title"]</h1>

@* 2024/5/11 以下の一行を追加 *@
<p><font color=red>@ViewData["AuthTicket"]</font></p>

<div class="row">
    <div class="col-md-4">
        <section>

・・・中略・・・

</div>

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

注 1 : デフォルトのログインページには[Remember me?]チェックボックスがあって、これにチェックを入れて認証を受けると Set-Cookie ヘッダに expires 属性が追加され認証クッキーが HDD / SSD に保存されます。expires 属性に指定される期限は認証チケットの有効期限と同じになります。期限を過ぎるとブラウザ側で認証クッキーを削除してしまいますので、条件 1 の「要求 HTTP ヘッダーに認証クッキーが含まれる」ことの判定はできなくなります。

注 2 : DI 機能により CookieAuthenticationOptions オブジェクトを取得します。それをベースに復号に必要な TicketDataFormat オブジェクトを取得し、認証クッキーから認証チケットを復号しています。

Visual Studio で「個別のユーザーアカウント」を認証に選んで作成したプロジェクトまたはスキャフォールディング機能を使って ASP.NET Core Identity を追加したプロジェクトでは以下のコードが Program.cs 含まれるはずです。その場合、コンストラクタの引数に IOptions<CookieAuthenticationOptions> options を含めるだけで DI 機能が働きます。

builder.Services.AddDefaultIdentity<ApplicationUser>(options => 
    options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>()

注 3 : IDataProtectionProvider.CreateProtector メソッドの引数ですが、これには暗号化するときに��用した値 (暗号化を特定の目的にロックするためのものらしい)と同じものを設定する必要があります。それが CookieAuthenticationMiddleware の名前、認証クッキー名、ASP.NET Identity のバージョンになるようです。

暗号化するときに使用した値と、上の CreateProtector メソッドの引数に指定したものが違うと復号に失敗し、上のコードで authTicket が null になり、次の行の authTicket.Principal で NullReferenceException がスローされます。

注 4 : 別の記事「ASP.NET Core でのデータ保護キーの管理」で書きましたがデータ保護キーがリサイクルで失われることがあります。その場合は復号に失敗し、上のコードで authTicket が null になり、次の行の authTicket.Principal で NullReferenceException がスローされます。

リサイクルで失われるようなことは無くても、データ保護キーの有効期限はデフォルトで 90 日だそうですので、有効期限を過ぎると復号に失敗すると思われます (未検証・未確認です)。

Tags: , , , ,

Authentication

IdentityServer で Web API の認証を サポート

by WebSurfer 8. April 2022 16:48

先の記事「Duende IdentityServer」で作成した認証サーバーを利用して ASP.NET Core Web API アプリのユーザー認証ができるようにしてみます。

Duende Software のドキュメント Protecting an API using Client Credentials に例が載っていますが、その記事では Machine to Machine で(即ち、個々のユーザー認証なしで)トークンを取得しているところを、IdentityServer に登録済みのユーザーの id と password で認証を受けてトークンを取得するように変更しました。

個々のユーザーのクレデンシャルを使うのは望ましくないというような意味のことがドキュメントに書いてあった気がしますが、せっかく苦労してサンプルを作ったので以下にその手順を書いておきます。

(1) Web API プロジェクトの作成

Visual Studio 2022 の「ASP.NET Core Web API」のテンプレートを使って[フレームワーク(F)]を「.NET 6.0 (長期的なサポート)」とし[認証の種類(A)]を「なし」にして Web API プロジェクトを作成します。

Web API プロジェクトの作成

(2) NuGet パッケージのインストール

Microsoft.AspNetCore.Authentication.JwtBearer を NuGet からインストールします。

NuGet パッケージのインストール

(3) JWT 認証スキーマを登録

Web API プロジェクトに含まれる Program.cs のコードを編集して JWT 認証スキーマを登録します。Duende Software のドキュメントの Adding an APIAuthorization at the API を参考にしました。

.NET 6.0 のプロジェクトの Program.cs では以下のようになります。自動生成されたコードに「// 追加」とコメントしたコードを追加します。

// 追加
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;

var builder = WebApplication.CreateBuilder(args);

// 追加
builder.Services.AddAuthentication(
        JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Authority = "https://localhost:5001";
            options.TokenValidationParameters = 
                new TokenValidationParameters
                {
                    ValidateAudience = false
                };
        });

// 追加
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ApiScope", policy =>
    {
        policy.RequireAuthenticatedUser();
        policy.RequireClaim("scope", "scope3");
    });
});

// ・・・中略・・・

// 追加
app.UseAuthentication();

app.UseAuthorization();
app.MapControllers();
app.Run();

上のコードで、options.Authority に設定する URL は先に作成した Duende IdentityServer の URL に合わせてください。デフォルトでは上のように "https://localhost:5001" となっているはずです。

policy.RequireClaim("scope", "scope3") の "scope3" は後で Duende IdentityServer プロジェクトの Config.cs ファイルで設定します。下のステップ (5) のコードを見てください。

(4) [Authorize] 属性を付与

自動生成された WeatherForecastController コントローラの Get() メソッドに [Authorize] 属性を付与します。using Microsoft.AspNetCore.Authorization; の追加を忘れないようにしてください。

ここまでの設定で JWT トークンベースのアクセス制限の実装は完了しており、トークンなしで WeatherForecastController コントローラの Get() メソッドを要求すると HTTP 401 Unauthorized 応答が返ってくるはずですので試してみてください。

(5) IdentityServer に Client を追加

先に作成済の Duende IdentityServer プロジェクトの Config.cs ファイルを開いて上の Web API アプリの認証をサポートするための Client を追加します。以下の「// 追加」とコメントしたコードを既存のファイルに追加します。

using Duende.IdentityServer.Models;

namespace DuendeIdentityServer
{
    public static class Config
    {

        // ・・・中略・・・

        public static IEnumerable<ApiScope> ApiScopes => new ApiScope[] {
            new ApiScope("scope1"),
            new ApiScope("scope2"),
            
            // 追加
            new ApiScope("scope3")
        };

        public static IEnumerable<Client> Clients => new Client[] {

            // ・・・中略・・・
            
            // 追加
            new Client
            {                
                ClientId = "WebApiNet6",
                ClientSecrets = { new Secret("0C86E143-30E0-4FB4-8710-008CD861BF5B".Sha256()) },

                AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                AllowedScopes = { "scope3" }
            }
        };
    }
}

Duende Software のドキュメントの例では Machine to Machine communication でトークンを取得していますが、そこを Issuing Tokens based on User PasswordsToken Endpoint を参考に id と password を送信してトークンを取得できるように変更しました。AllowedGrantTypes を GrantTypes.ResourceOwnerPassword に設定するのがキモらしいです。

(6) クライアントアプリの作成

IdentityServer に登録済みのユーザーの id と password を送信してトークンを取得し、そのトークンを要求ヘッダに設定して Web API の WeatherForecast アクションメソッドを GET 要求して結果を表示する検証用のアプリを作成します。

Duende Software のドキュメント Creating the client を参考に .NET 6.0 のコンソールアプリとして作成しました。

コードは以下の通りです。NuGet で IdentityModel をインストールしないと動かないので注意してください。

using IdentityModel.Client;
using System.Text.Json;

var client = new HttpClient();

var disco = await client
    .GetDiscoveryDocumentAsync("https://localhost:5001");

if (disco.IsError)
{
    Console.WriteLine(disco.Error);
    return;
}

var tokenResponse2 = await client.RequestPasswordTokenAsync(
    new PasswordTokenRequest
    {
        Address = disco.TokenEndpoint,
        ClientId = "WebApiNet6",
        ClientSecret = "0C86E143-30E0-4FB4-8710-008CD861BF5B",

        Scope = "scope3",

        UserName = "alice",
        Password = "Pass123$"
    });

if (tokenResponse2.IsError)
{
    Console.WriteLine(tokenResponse2.Error);
    return;
}
else
{
    Console.WriteLine(tokenResponse2.Json);
    Console.WriteLine("\n\n");
}

client.Dispose();

var apiClient = new HttpClient();
apiClient.SetBearerToken(tokenResponse2.AccessToken);

var response = await apiClient
              .GetAsync("https://localhost:44300/WeatherForecast");

if (!response.IsSuccessStatusCode)
{
    Console.WriteLine(response.StatusCode);
}
else
{
    var doc = JsonDocument
              .Parse(await response.Content.ReadAsStringAsync())
              .RootElement;
    Console.WriteLine(JsonSerializer
          .Serialize(doc, 
              new JsonSerializerOptions { WriteIndented = true }));
}

apiClient.Dispose();

コンソールアプリの実行結果は以下のようになります。事前に IdentityServer と Web API を動かしておく必要がありますので注意してください。

コンソールアプリの実行結果

一応期待通り動くことは検証できましたが、ホントに上記の設定で良いのかは自信がありません。ひょっとしたら、やってはいけないことをやっているのかもしれませんので、コピペして使うのは避けた方が良いと思います。(笑)

Tags: , ,

Authentication

Duende IdentityServer

by WebSurfer 7. April 2022 12:38

先の記事「VS2022 .NET 6.0 React のユーザー認証」で IdentityServer を勉強しなくてはと書きましたが、そのための第一歩として Duende Software のサイトの Quickstarts を見ながらサンプルを作ってみました。

Duende IdentityServer

上の画像は Visual Studio 2022 のテンプレートで Duende IdentityServer プロジェクトを作成し、それを Visual Studio から実行してブラウザに表示したものです。

以下に、上の画像の Duende IdentityServer プロジェクトの作り方、ASP.NET Core MVC アプリのプロジェクトを作ってその認証を Duende IdentityServer でサポートする方法を備忘録として書いておきます。

(1) テンプレートのインストール

Overview に従って Visual Studio 用のテンプレートをインストールします。コマンドラインから以下のように dotnet コマンド、

dotnet new --install Duende.IdentityServer.Templates

・・・を実行すると、下の画像のように 6 種類のテンプレートが自動的にインストールされます。

テンプレートをインストール

(2) IdentityServer プロジェクトの作成

Visual Studio 2022 を立ち上げて「新しいプロジェクトの作成」画面を開くと以下のように Duende IdentityServer 関係のメニューが表示されます。

Duende IdentityServer

その中の赤枠で囲った ASP.NET Core Identity をユーザー情報のストアに使うテンプレート選択してプロジェクトを作成してみました。プロジェクトを作成する際何故かフレームワークは選択できず自動的に .NET 6.0 になります。

作成したプロジェクトは Quickstarts の中の Using ASP.NET Core Identity に該当します。(記事が少し古いのか、実際に生成されたものと記事の説明が少々異なるのに注意)

中身は ASP.NET Core の Razor Pages アプリで、Visual Studio から実行すると開発サーバーとして Kestrel が立ち上がってアプリが実行され、この記事の一番上の画像のように結果がブラウザに表示されます。

デフォルトではユーザー情報をストアするためのデータベースは SQLite になります。EF Code First の機能を使ってデータベースを生成します。Migration 関係のファイルは Data/Migrations にありますので、パッケージマネージャーコンソールから update-database を実行すればアプリケーションルート直下に AspIdUsers.db というファイルが生成されます。ただしその時点ではユーザーは登録されてないのでログインはできません。

プロジェクトにはユーザーを登録するためのページは含まれてないのでアプリを操作してユーザー登録することはできません。ユーザー情報をシードするために SeedData.cs がプロジェクトに含まれていますが Visual Studio から実行したのではそれは動きません。

dotnet run /seed を実行すれば alice と bob という名前の 2 人のユーザーがパスワード Pass123$ で登録されるようです (未確認です。dotnet コマンドに自信のない自分は Program.cs のコード中の if (args.Contains("/seed")) を true にして実行してユーザー登録しました)。以降は、そのユーザー情報を使ってログインできるようになります。

以上で IdentityServer 側の準備はできました。ただし、後で、認証をサポートする MVC アプリのホスト名などの情報を Config.cs ファイルの設定に反映する必要があることを覚えておいてください。

(3) ASP.NET Core MVC プロジェクトの作成

次に、Duende Software の Interactive Applications with ASP.NET Core の説明に従って ASP.NET Core MVC アプリのプロジェクトを作成し、上で準備した IdentityServer で認証を行うようにします。

Visual Studio 2022 の「ASP.NET Core Web アプリ (Model-View-Controller)」のテンプレートを使って[フレームワーク(F)]を「.NET 6.0 (長期的なサポート)」とし[認証の種類(A)]を「なし」にして MVC アプリのプロジェクトを作成します。

(4) NuGet パッケージのインストール

MVC プロジェクトに Microsoft.AspNetCore.Authentication.OpenIdConnect を NuGet からインストールします。

Microsoft.AspNetCore.Authentication.OpenIdConnect

(5) Program.cs の編集

MVC プロジェクトの Program.cs を開いて以下の「// 追加」とコメントしてあるコードを追加します。options.ClientId と options.ClientSecret は IdentityServer の Config.cs の Client の設定と合わせる必要があるので注意してください。

// 追加
using System.IdentityModel.Tokens.Jwt;

var builder = WebApplication.CreateBuilder(args);

// 追加
JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();

// 追加
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
    .AddCookie("Cookies")
    .AddOpenIdConnect("oidc", options =>
    {
        // IdentityServer の launchSettings.json の設定と合わせる
        // デフォルトで以下の設定になっているはず
        options.Authority = "https://localhost:5001";

        // IdentityServer の Config.cs の Client の設定と合わせる
        options.ClientId = "interactive";
        options.ClientSecret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0";

        options.ResponseType = "code";
        options.SaveTokens = true;

        // 以下を追加すると IdentityServer の SeedData.cs で
        // Claims に追加した name, given_name, family_name
        // 情報も User.Claims に含まれるようになる
        options.Scope.Add("profile");
        options.GetClaimsFromUserInfoEndpoint = true;
    });

// ・・・中略・・・

// 追加
app.UseAuthentication();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

(6) IdentityServer の Config.cs の修正

IdentityServer プロジェクトの Config.cs を開いて RedirectUris, FrontChannelLogoutUri, PostLogoutRedirectUris のホスト名を MVC プロジェクトのものに変更します。

開発環境では MVC プロジェクトの Properties/launchSettings.json に設定されていますのでそれを見るか、実際にアプリを起動してブラウザのアドレスバーを見てください。IIS Express を使うのか Kestrel を使うのかによって変わるので注意してください。

// interactive client using code flow + pkce
new Client
{
    ClientId = "interactive",
    ClientSecrets = { new Secret("49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256()) },

    AllowedGrantTypes = GrantTypes.Code,

    // 以下のホスト名の部分を修正
    RedirectUris = { "https://localhost:44351/signin-oidc" },
    FrontChannelLogoutUri = "https://localhost:44351/signout-oidc",
    PostLogoutRedirectUris = { "https://localhost:44351/signout-callback-oidc" },

   AllowOfflineAccess = true,
   AllowedScopes = { "openid", "profile", "scope2" }
},

(7) HomeController の修正

MVC プロジェクトの HomeController を開いて Privacy アクションメソッドに [Authorize] 属性を付与します。これにより匿名ユーザーが Privacy にアクセスしようとすると IdentityServer のログインページにリダイレクトされるようになります。

ログアウトできるように Logout アクションメソッドを追加します。その説明は Adding sign-out に書いてあります。(それを読んでも自分には仕組みは分かりませんでしたが、このアクションメソッドを呼び出せばログアウトできるのは確認しました)

using Microsoft.AspNetCore.Mvc;
using MvcNet6.Models;
using System.Diagnostics;

// 追加
using Microsoft.AspNetCore.Authorization;

namespace MvcNet6.Controllers
{
    public class HomeController : Controller
    {
        // ・・・中略・・・        

        // 追加
        [Authorize]
        public IActionResult Privacy()
        {
            return View();
        }

        // 追加
        public IActionResult Logout()
        {
            return SignOut("Cookies", "oidc");
        }

        // ・・・中略・・・
    }
}

(8) Private.cshtml の書き換え

ステップ (7) で [Auhtorize] 属性を付与したアクションメソッド Privacy のビュー Private.cshtml を以下のように書き換えます。これは参考に Claims 情報と IdentityServer のプロパティ情報を表示するためで、こうしなければならないというものではないです。

@using Microsoft.AspNetCore.Authentication

@{
    ViewData["Title"] = "Privacy Policy";
}
<h2>Claims</h2>

<dl>
    @foreach (var claim in User.Claims)
    {
        <dt>@claim.Type</dt>
        <dd>@claim.Value</dd>
    }
</dl>

<h2>Properties</h2>

<dl>
@{
#nullable disable
    foreach (var prop in (await Context.AuthenticateAsync()).Properties.Items)
    {
        <dt>@prop.Key</dt>
        <dd>@prop.Value</dd>
    }
}
</dl>

(9) _LoginPartial.cshtml の追加

ASP.NET Core MVC プロジェクトを認証に個別のアカウントを選んで作成すると、ログインしたときに画面のメニューバーの右端にユーザー名と Logout リンクが表示されますが、それと同等なものを Views/Shared フォルダに _LoginPartial.cshtml として追加します。

<ul class="navbar-nav">
@{
    string? givenName = User.Claims.FirstOrDefault(u => u.Type == "given_name")?.Value;

    if (givenName != null)
    {
        <li class="nav-item">
            <span class="nav-link">Hello @givenName !</span>
        </li>
        <li class="nav-item">
        <a class="nav-link" asp-action="Logout" asp-controller="Home">Logout</a>
        </li>
    }
    else
    {
        <li><span class="nav-link">ログインしていません</span></li>
    }
}
</ul>

これを <partial name="_LoginPartial" /> というコードで Views/Shared/_Layour.cshtml に追加します。場所は <div class="navbar-collapse ... の div 要素の中の一番下です。

以上で完了です。まず Visual Studio で IdentiryServer プロジェクトを実行した後、MVC プロジェクトを実行します。ブラウザに表示された MVC アプリのメニューバーの Pricacy をクリックすると、以下のように IdentityServer のログイン画面にリダイレクトされます。そこで、IdentiryServer プロジェクトで登録したユーザーの alice または bob でログインできます。

ログイン画面

ログインに成功すると Privacy 画面にリダイレクトされ、下の画像の結果が表示されます。

Privacy 画面

メニューバーの右端の Logout リンクをクリックするとログアウトできます。


さて、ここまでやってみて、それで IdentityServer が十分理解できたのか、先の記事「VS2022 .NET 6.0 React のユーザー認証」で問題となった Authority とか Issuer とはどういうものか分かったのかと聞かれると、正直何も分かってないです。

さらなる勉強が必要なようですが、どうも手に負えそうもないような感じがしています。(汗)


【2022/7/12 追記】

認証サーバー (Duende IdentityServer) のドメインは localhost:5001 で、ASP.NET Core MVC のドメインは localhost:44351 と異なっていますが、それで何故 Cookie ベースの ASP.NET Core MVC のユーザー認証がうまくいくのでしょう?

Fiddler を使って調べてみると、認証プロセスの過程で以下の Fiddler のキャプチャ画像の #40 の通り localhost:44351/signin-odic に要求が出て、応答の Set_Cookie で認証クッキーが返ってきています。

認証クッキーも受領

そのあたりの詳しい仕組みは全く分かっていませんが、とにかく ASP.NET Core MVC のドメイン localhost:44351 での要求で認証クッキーが返ってくるので、認証サーバーのドメイン (localhost:5001) が異なっても問題ないということでした。

Tags: , ,

Authentication

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  June 2024  >>
MoTuWeThFrSaSu
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

View posts in large calendar