質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

ASP.NET Web API

ASP.NET Web APIはブラウザやモバイル機器のようなクライアント向けのHTTPサービスを構築するフレームワークです。Microsoft .NET Frameworkがベースになっており、RESTfulサービスを構築するには理想的です。

Q&A

1回答

1112閲覧

JwtBearer認証とロールベース承認においてサーバでユーザのロールを変えた場合の対処

Gene_Selfish

総合スコア7

.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

ASP.NET Web API

ASP.NET Web APIはブラウザやモバイル機器のようなクライアント向けのHTTPサービスを構築するフレームワークです。Microsoft .NET Frameworkがベースになっており、RESTfulサービスを構築するには理想的です。

0グッド

0クリップ

投稿2018/12/11 02:11

前提・実現したいこと

JwtBearer と ASP.NET Core Identity による WEB API の認証について調べています。
クライアントからログインし、JWTトークンを取得後、
サーバ側でそのユーザのロールを変更しても、クライアントに保存したトークン内のロールで
WEB APIを呼び出すことができてしまいます。
どのように対処すれば、サーバ上の最新のロールで WEB API へのアクセスをチェックすることができるでしょうか。

試したこと

ユーザを削除した場合であれば、StartupのConfigureServicesメソッド内で、
以下のようにすることによって401応答を返すことができることはわかりました。

services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.Events = new JwtBearerEvents { OnTokenValidated = context => { var userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>(); var user = userManager.GetUserAsync(context.Principal).Result; if (user == null) { context.Fail("Unauthorized"); } return Task.CompletedTask; } };   ・・・・・・ });

ロールの変更に対してはどのように対処することができるでしょうか。

補足情報(FW/ツールのバージョンなど)

ASP.NET Core 2.1

参考にしたWEBサイト
ASP.NET Core 2.1 - Simple API for Authentication, Registration and User Management
※こちらでは ASP.NET Core Identity とロールベースの承認は使用していません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

これまでに分かったことを書きます。
ISecurityTokenValidatorインターフェースを実装します。

C#

1using System; 2using System.Linq; 3using System.Security.Claims; 4using Microsoft.AspNetCore.Identity; 5using Microsoft.IdentityModel.Tokens; 6using Microsoft.Extensions.DependencyInjection; 7using SpaRoleAuthExp.Areas.Identity.Data; 8using System.IdentityModel.Tokens.Jwt; 9 10namespace SpaRoleAuthExp.Auth 11{ 12 public class MySecurityTokenValidator : ISecurityTokenValidator 13 { 14 public bool CanValidateToken => true; 15 16 public int MaximumTokenSizeInBytes { get; set; } = TokenValidationParameters.DefaultMaximumTokenSizeInBytes; 17 18 private IServiceProvider _serviceProvider { get; } 19 20 private JwtSecurityTokenHandler _tokenHandler { get; } 21 22 public MySecurityTokenValidator(IServiceProvider serviceProvider) 23 { 24 _serviceProvider = serviceProvider; 25 _tokenHandler = new JwtSecurityTokenHandler(); 26 } 27 28 public bool CanReadToken(string securityToken) 29 { 30 return _tokenHandler.CanReadToken(securityToken); 31 } 32 33 public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken) 34 { 35 // クライアントから受け取ったトークンから、ClaimsPrincipal(と SecurityToken vt)を作る 36 var cp = _tokenHandler.ValidateToken(securityToken, validationParameters, out var vt); 37 38 var userManager = _serviceProvider.GetService<UserManager<ApplicationUser>>(); 39 // (1)そのClaimsPrincipalで、DBからユーザを取得する。※このとき、GetUserAsync(cp)メソッドだとログイン中のユーザを削除していても何故かユーザーを取得できる 40 var applicationUser = userManager.FindByNameAsync(cp.Identity.Name).Result; 41 42 if (applicationUser == null) 43 { 44 validatedToken = null; 45 return new ClaimsPrincipal(); // これによりクライアントにHTTPステータス401を応答する。※ここでnullを返すと例外が発生する。 46 } 47 48 var principalFactory = _serviceProvider.GetService<IUserClaimsPrincipalFactory<ApplicationUser>>(); 49 // 現在のDB内のユーザからClaimsPrincipalを作る 50 var claimsPrincipal = principalFactory.CreateAsync(applicationUser).Result; 51 // DBからユーザのロールを取得する 52 var roles = userManager.GetRolesAsync(applicationUser).Result; 53 // ClaimsPrincipalにロールを追加する 54 var claims = roles.Select(role => new Claim(ClaimTypes.Role, role)); 55 claimsPrincipal.AddIdentity(new ClaimsIdentity(claims)); 56 57 validatedToken = vt; // 最初に作ったSecurityTokenを返す 58 return claimsPrincipal; // 現在のDB内のユーザ情報(ロール含む)から作ったClaimsPrincipalを返す 59 } 60 } 61}

そして、StartupのConfigureServicesメソッド内で、MySecurityTokenValidatorを登録します。

C#

1public void ConfigureServices(IServiceCollection services) 2{ 3//・・・省略・・・ 4 services.AddAuthentication(options => 5 { 6 options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; 7 options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; 8 options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 9 }) 10 .AddJwtBearer(options => 11 { 12 options.RequireHttpsMetadata = false; 13 options.SaveToken = true; 14 options.TokenValidationParameters = new TokenValidationParameters 15 { 16 ValidateIssuerSigningKey = true, 17 ValidateIssuer = false, 18 IssuerSigningKey = new SymmetricSecurityKey(key), 19 ValidateAudience = false 20 }; 21 options.SecurityTokenValidators.Clear(); // これがないと、デフォルトの認証が動く。 22 // カスタマイズしたSecurityTokenValidatorを登録する 23 options.SecurityTokenValidators.Add(new MySecurityTokenValidator(services.BuildServiceProvider())); 24 }); 25//・・・省略・・・      26}

これで実現できましたが、若干疑問もあります。
(1)のところで、userManager.GetUserAsync(cp) とすると、ユーザーを削除していても取得できてしまうところが、どういうカラクリによるものなのか分からず気持ちが悪いです。

投稿2018/12/25 03:07

Gene_Selfish

総合スコア7

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問