web-dev-qa-db-ja.com

ASP.NetCoreでのOpenIdConnectクレームの変換

ASP.Net Core Webアプリケーションを作成し、UseOpenIdConnectAuthenticationを使用してIdentityServer3に接続しています。 ASP.Net MVC 5サンプルをエミュレートするIdentity Serverから受け取ったクレームを変換して、「 確かに必要のない低レベルのプロトコルクレーム 」を削除しようとしています。 MVC 5では、SecurityTokenValidated通知のハンドラーを追加して、必要なクレームのみを持つものとAuthenticationTicketを交換します。

ASP.Net Coreでは、同等のことを行うには、OnTokenValidated内のOpenIdConnectEventsを処理する必要があると思いました。ただし、その段階では、追加のスコープ情報が取得されているようには見えません。 OnUserInformationReceivedを処理する場合、追加情報は存在しますが、プリンシパルではなくユーザーに保存されます。

他のイベントはどれも、認証が完了した後に保持することに興味がないクレームを永久に削除する明白な場所のようには見えません。どんな提案もありがたく受けました!

12
Piers Lawson

プロセスの早い段階で変換するというLeastPrivilegeの提案が好きです。提供されたコードは完全には機能しません。このバージョンは次のことを行います。

var oidcOptions = new OpenIdConnectOptions
{
   ...

   Events = new OpenIdConnectEvents
   {
       OnTicketReceived = e =>
       {
          e.Principal = TransformClaims(e.Ticket.Principal);
          return Task.CompletedTask;
       }
   }
};

これは、PrincipalではなくTicketを置き換えます。私の他の回答のコードを使用して、新しいPrincipalを作成できます。同時にTicketを置き換えることもできますが、それが必要かどうかはわかりません。

ですから、私の質問にほぼ答える方法を提案してくれたLeastPrivilegeとAdemに感謝します...コードだけを少し調整する必要がありました。全体として、クレームを早期に変換するというLeastPrivilegeの提案を好みます。

10
Piers Lawson

OnSigningInSignInSchemeイベントを実装できます。次に例を示します。

        app.UseCookieAuthentication(new CookieAuthenticationOptions()
        {
            AuthenticationScheme = "OpenIdCookies",
            AutomaticAuthenticate = true,
            Events = new CookieAuthenticationEvents()
            {
                OnSigningIn = async (context) =>
                {
                    ClaimsIdentity identity = (ClaimsIdentity)context.Principal.Identity;
                    identity.Claims = identity.Claims.Where(...);
                }
            }
        });

        var oidcOptions = new OpenIdConnectOptions
        {
            AuthenticationScheme = "oidc",
            SignInScheme = "OpenIdCookies"
        };

        //.. set other options

        app.UseOpenIdConnectAuthentication(oidcOptions); 
5
adem caglin

返信ありがとうAdem ...問題の大部分を解決しました...唯一の問題はそのアイデンティティです。クレームは読み取り専用プロパティです。ただし、新しいプリンシパルの作成は機能することがわかりました。

Events = new CookieAuthenticationEvents()
{
    OnSigningIn = (context) =>
    {
        ClaimsIdentity identity = (ClaimsIdentity)context.Principal.Identity;

        var givenName = identity.FindFirst(Constants.ClaimTypes.GivenName);
        var familyName = identity.FindFirst(Constants.ClaimTypes.FamilyName);
        var sub = identity.FindFirst(Constants.ClaimTypes.Subject);

        var claimsToKeep = new List<Claim> {givenName, familyName, sub};

        var newIdentity = new ClaimsIdentity(claimsToKeep, identity.AuthenticationType);

        context.Principal = new ClaimsPrincipal(newIdentity);

        return Task.FromResult(0);
    }
}

これが正しいアプローチであるかどうかはわかりませんが、機能しているようです。

5
Piers Lawson

私は個人的に、実際の認証が行われるミドルウェアでクレーム変換を行うことを好みます。

そのために、OIDCミドルウェアでOnTicketReceivedイベントを使用できます。

var oidcOptions = new OpenIdConnectOptions
{
   AuthenticationScheme = "oidc",
   SignInScheme = "cookies",

   Authority = Clients.Constants.BaseAddress,

   ClientId = "mvc.hybrid",
   ClientSecret = "secret",
   ResponseType = "code id_token",
   SaveTokens = true,

   TokenValidationParameters = new TokenValidationParameters
   {
      NameClaimType = JwtClaimTypes.Name,
      RoleClaimType = JwtClaimTypes.Role,
   },

   Events = new OpenIdConnectEvents
   {
       OnTicketReceived = e =>
       {
           ClaimsPrincipal p = TransformClaims(e.Ticket.Principal);
           e.Ticket = new AuthenticationTicket(
            p,
            e.Ticket.Properties,
            e.Ticket.AuthenticationScheme);

        return Task.CompletedTask;
    }
  }
};
4
leastprivilege