C#
ASP.NET_MVC
identity

ASP.Net MVC5 [Authorize(Roles="XXXX")]が正しく動作しない with Identity2

More than 1 year has passed since last update.

Identity2を使った認証処理のカスタマイズ

VisualStudioを標準で生成する認証処理では、認証に使用するユーザー・テーブルのIDがstring型になります。
開発しているシステムではstring型では都合が悪いので認証処理をカスタマイズしました。

認証処理のカスタマイズは次の記事が参考になります。
ASP.NET Identityで独自の認証処理を行う

ユーザー情報の登録、編集、削除処理を行うUserStoreクラス, ユーザー管理を行うUserManagerクラス、
ロール情報の登録、編集、削除処理を行うRoleStoreクラス, ロール管理を行うRoleManagerクラスを独自で作成したユーザー・テーブル(エンティティ)に合わせて実装します。

[Authorize(Roles="XXXX")]はどこを参照するのか?

ユーザーのロールはSingInした時に、正常に認証処理のカスタマイズができていればCookieに保存されます。
[Authorize(Roles="XXXX")]をコントローラー内のアクション名の前に書いておくと、
ソフトウェアは、アクションが実行される前にCookieを参照しCookie内に該当するロールが存在する場合、そのアクションを実行します。

ところが

ロールXXXXのユーザーでログインして、[Authorize(Roles="XXXX")]を適用したアクションにアクセスすると
ログイン画面に飛ばされてしまいました。
(独自でアクション・フィルターを実装?アクションが実行される前に毎回DBアクセス?
ありえん・・なんてことを考えていました。)

SignIn時に呼ばれるCreateIdentityAsync()の戻り値にロールのClaimを追加してみた。

SignInManager.cs
var claimsIdentity = UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie)
claimsIdentity .AddClaim(new Claim(ClaimTypes.Role, "XXXX"));

上記のようにClaimを追加してみたところ、先程までログイン画面に飛ばされてしまった画面にアクセスできるようになりました。
(なるほど、Claim情報はCookieに保存されるのかと納得しました。)

わざわざロールをClaimに追加しないといけないの?

Identityでロールを管理する仕組みが用意されているのだから、自動でClaimにロールが登録されるようになってるだろうと、Identityライブラリのソースコードを読んでみました。

UserManagerクラスにはSupportsUserRoleフラグが定義されています。
IUserRoleStoreインターフェースを継承してUserStoreクラスが作成されている場合にSupportsUserRoleフラグがTrueになります。

SupportsUserRoleがフラグがTrueの場合に、SignIn処理が実行されるとIdentityライブラリ内でロールをClaimに追加する処理が実行されます。

IUserRoleStoreインターフェースを継承していたのに、なぜClaimにロールが追加されなかったのか?

UserStoreクラスを実装する時に、IUserRoleStoreインターフェースとIRoleStoreインターフェースを継承していました。
IRoleStoreインターフェースはRoleStoreクラスを実装するためのインターフェースです。
IRoleStoreインターフェースを継承していたために、IUserRoleStoreインターフェースを継承しているか判定する処理で、IUserRoleStoreインターフェースは継承されていないと判定されていました。
従って、UserManagerクラスのSupportsUserRoleフラグがFalseになり、SignIn時にロールがClaimに追加されていませんでした。

Identityライブラリ

ライブラリの中身を追わないと実装に使えないライブラリって・・・