作成者: Damien Bowden
クレームは、信頼できる ID プロバイダーまたは ASP.NET Core ID を使用して発行できる任意のユーザーまたは ID データから作成できます。 クレームは、サブジェクトが何であるかを表す名前と値のペアであり、サブジェクトで何が実行できるかではありません。 この記事では、次の領域について説明します。
- OpenID Connect クライアントを使用して要求を構成し、マッピングする方法
- 名前とロールの要求を設定する
- 要求の名前空間をリセットする
- TransformAsync を使用して要求をカスタマイズし、拡張する
OpenID Connect 認証を使用した要求マッピング
プロファイル要求は id_token
で返すことができます。これは認証に成功すると返されます。 ASP.NET Core クライアント アプリでは、プロファイル スコープのみ必要となります。 要求に id_token
を使用するとき、追加の要求マッピングは必要ありません。
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-your-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Add("profile");
options.SaveTokens = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
上記のコードでは、Microsoft.AspNetCore.Authentication.OpenIdConnect NuGet パッケージが必要です。
ユーザー要求を取得するもう 1 つの方法は、OpenID Connect ユーザー情報 API を使用する方法です。 ASP.NET Core クライアント アプリでは GetClaimsFromUserInfoEndpoint
プロパティを使用してこれを構成します。 最初の設定との重要な違いの 1 つは、MapUniqueJsonKey
メソッドを使って必要な要求を指定する必要があるということです。そうしない場合、クライアント アプリでは標準要求の name
、given_name
、email
のみを使用できます。 id_token
に含まれる要求は既定でマッピングされます。 これは最初のオプションとの大きな違いです。 必要な要求の一部を明示的に定義する必要があります。
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Add("profile");
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.ClaimActions.MapUniqueJsonKey("preferred_username",
"preferred_username");
options.ClaimActions.MapUniqueJsonKey("gender", "gender");
});
var app = builder.Build();
// Code removed for brevity.
Note
ID プロバイダーの検出ドキュメントで PAR のサポートがアドバタイズされている場合、既定の Open ID Connect ハンドラーはプッシュ承認要求 (PAR) を使用します。 ID プロバイダーの検出ドキュメントは、通常、.well-known/openid-configuration
にあります。 ID プロバイダーのクライアント構成で PAR を使用できない場合は、PushedAuthorizationBehavior オプションを使用して PAR を無効にすることができます。
builder.Services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect("oidc", oidcOptions =>
{
// Other provider-specific configuration goes here.
// The default value is PushedAuthorizationBehavior.UseIfAvailable.
// 'OpenIdConnectOptions' does not contain a definition for 'PushedAuthorizationBehavior'
// and no accessible extension method 'PushedAuthorizationBehavior' accepting a first argument
// of type 'OpenIdConnectOptions' could be found
oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.Disable;
});
PAR が使用されている場合にのみ認証が成功するようにするには、代わりに PushedAuthorizationBehavior.Require を使用します。 この変更により、OpenIdConnectEvents に対する新しい OnPushAuthorization イベントも導入されます。これにより、プッシュされた承認要求をカスタマイズしたり、手動で処理したりできます。 詳細については、API 提案 をご覧ください。
名前要求とロール要求のマッピング
Name 要求と Role 要求は ASP.NET Core HTTP コンテキストで既定のプロパティにマッピングされます。 場合によっては、既定のプロパティに異なる要求を使用する必要があります。それを行わない場合、名前要求とロール要求で既定値が一致しません。 要求は TokenValidationParameters プロパティを利用してマッピングできます。また、必要に応じてあらゆる要求に設定できます。 要求からの値は、HttpContext User.Identity.Name プロパティとロールで直接使用できます。
User.Identity.Name
に値がないか、ロールが不足している場合、返された要求で値を確認し、NameClaimType
値と RoleClaimType
値を設定してください。 クライアント認証から返された要求は HTTP コンテキストで表示できます。
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
// Other options...
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "email"
//, RoleClaimType = "role"
};
});
要求名前空間、既定の名前空間
ASP.NET Core によって既定の名前空間が一部の既知の要求に追加されますが、アプリでは不要となることがあります。 必要に応じて、これらの追加された名前空間を無効にし、OpenID Connect サーバーによって作成された正確な要求を使用します。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
JsonWebTokenHandler.DefaultInboundClaimTypeMap.Clear();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-your-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Add("profile");
options.SaveTokens = true;
});
var app = builder.Build();
// Code removed for brevity.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-your-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Add("profile");
options.SaveTokens = true;
});
var app = builder.Build();
// Code removed for brevity.
グローバルではなくスキームごとに名前空間を無効にする必要がある場合は、MapInboundClaims = false オプションを使用できます。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-your-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.MapInboundClaims = false;
options.Scope.Add("profile");
options.SaveTokens = true;
});
var app = builder.Build();
// Code removed for brevity.
IClaimsTransformation
を使用してカスタム要求を拡張または追加する
IClaimsTransformation インターフェイスを使用し、ClaimsPrincipal クラスに要求を追加できます。 インターフェイスには 1 つのメソッド TransformAsync が必要です。 このメソッドは複数回呼び出される場合があります。 新しい要求は ClaimsPrincipal
にまだ存在しない場合にのみ追加します。 新しい要求を追加する目的で ClaimsIdentity
が作成されます。これは ClaimsPrincipal
に追加できます。
using Microsoft.AspNetCore.Authentication;
using System.Security.Claims;
public class MyClaimsTransformation : IClaimsTransformation
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
ClaimsIdentity claimsIdentity = new ClaimsIdentity();
var claimType = "myNewClaim";
if (!principal.HasClaim(claim => claim.Type == claimType))
{
claimsIdentity.AddClaim(new Claim(claimType, "myClaimValue"));
}
principal.AddIdentity(claimsIdentity);
return Task.FromResult(principal);
}
}
IClaimsTransformation インターフェイスと MyClaimsTransformation
クラスは、次のようにサービスとして登録できます。
builder.Services.AddTransient<IClaimsTransformation, MyClaimsTransformation>();
外部 ID プロバイダーからの要求をマップする
次のドキュメントを参照してください。
クレームは、信頼できる ID プロバイダーまたは ASP.NET Core ID を使用して発行できる任意のユーザーまたは ID データから作成できます。 クレームは、サブジェクトが何であるかを表す名前と値のペアであり、サブジェクトで何が実行できるかではありません。 この記事では、次の領域について説明します。
- OpenID Connect クライアントを使用して要求を構成し、マッピングする方法
- 名前とロールの要求を設定する
- 要求の名前空間をリセットする
- TransformAsync を使用して要求をカスタマイズし、拡張する
OpenID Connect 認証を使用した要求マッピング
プロファイル要求は id_token
で返すことができます。これは認証に成功すると返されます。 ASP.NET Core クライアント アプリでは、プロファイル スコープのみ必要となります。 要求に id_token
を使用するとき、追加の要求マッピングは必要ありません。
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-your-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Add("profile");
options.SaveTokens = true;
});
ユーザー要求を取得するもう 1 つの方法は、OpenID Connect ユーザー情報 API を使用する方法です。 ASP.NET Core クライアント アプリケーションでは GetClaimsFromUserInfoEndpoint
プロパティを使用してこれを構成します。 最初の設定との重要な違いの 1 つは、MapUniqueJsonKey
メソッドを利用し、必要な要求を指定する必要があるということです。指定しない場合、標準要求の name
、given_name
、email
をクライアント アプリケーションで利用できます。 id_token
に含まれる要求は既定でマッピングされます。 これは最初のオプションとの大きな違いです。 必要な要求の一部を明示的に定義する必要があります。
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-your-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Add("profile");
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.ClaimActions.MapUniqueJsonKey("preferred_username", "preferred_username");
options.ClaimActions.MapUniqueJsonKey("gender", "gender");
});
名前要求とロール要求のマッピング
Name 要求と Role 要求は ASP.NET Core HTTP コンテキストで既定のプロパティにマッピングされます。 場合によっては、既定のプロパティに異なる要求を使用する必要があります。それを行わない場合、名前要求とロール要求で既定値が一致しません。 要求は TokenValidationParameters プロパティを利用してマッピングできます。また、必要に応じてあらゆる要求に設定できます。 要求からの値は、HttpContext User.Identity.Name プロパティとロールで直接使用できます。
User.Identity.Name
に値がないか、ロールが不足している場合、返された要求で値を確認し、NameClaimType
値と RoleClaimType
値を設定してください。 クライアント認証から返された要求は HTTP コンテキストで表示できます。
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
// other options...
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "email",
// RoleClaimType = "role"
};
});
要求名前空間、既定の名前空間
ASP.NET Core によって既定の名前空間が一部の既知の要求に追加されますが、アプリでは不要となることがあります。 必要に応じて、これらの追加された名前空間を無効にし、OpenID Connect サーバーによって作成された正確な要求を使用します。
public void Configure(IApplicationBuilder app)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
IClaimsTransformation
を使用してカスタム要求を拡張または追加する
IClaimsTransformation
インターフェイスを使用し、ClaimsPrincipal
クラスに要求を追加できます。 インターフェイスには 1 つのメソッド TransformAsync
が必要です。 このメソッドは複数回呼び出される場合があります。 新しい要求は ClaimsPrincipal
にまだ存在しない場合にのみ追加します。 新しい要求を追加する目的で ClaimsIdentity
が作成されます。これは ClaimsPrincipal
に追加できます。
public class MyClaimsTransformation : IClaimsTransformation
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
ClaimsIdentity claimsIdentity = new ClaimsIdentity();
var claimType = "myNewClaim";
if (!principal.HasClaim(claim => claim.Type == claimType))
{
claimsIdentity.AddClaim(new Claim(claimType, "myClaimValue"));
}
principal.AddIdentity(claimsIdentity);
return Task.FromResult(principal);
}
}
IClaimsTransformation
インターフェイスと MyClaimsTransformation
クラスはサービスとして ConfigureServices メソッドで追加できます。
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IClaimsTransformation, MyClaimsTransformation>();
ASP.NET Core Identity でカスタム要求を拡張または追加する
次のドキュメントを参照してください。
IUserClaimsPrincipalFactory を使用して Identity に要求を追加する
外部 ID プロバイダーからの要求をマップする
次のドキュメントを参照してください。
ASP.NET Core