欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Asp.net Core 2.0 OpenId Connect Handler缺失Claims?

程序员文章站 2022-06-03 18:10:57
原文:https://leastprivilege.com/2017/11/15/missing-claims-in-the-asp-net-core-2-openid-connect-handler/发布于:2017年11月环境:ASP.NET Core 2.0 原文:https://leastp ......

 

原文:https://leastprivilege.com/2017/11/15/missing-claims-in-the-asp-net-core-2-openid-connect-handler/
发布于:2017年11月
环境:asp.net core 2.0

通过oidc provider 把claims映射到claimsprincipal这一步骤,在asp.net core 2中新的openid connect handler具有不同的行为。
这是特别令人困惑和难以诊断的,因为这里有几个部件聚集在一起。我们来看一下。
您可以使用我的示例oidc客户端来观察到相同的结果。

将标准claim类型映射到microsoft专有claim类型

一件令人烦恼的事情是微软仍然认为他们知道什么是最适合你的,将oidc标准声明映射到其专有声明。
可以通过清除microsoft jwt令牌处理程序上的入站声明类型映射来优雅地修复:

jwtsecuritytokenhandler.defaultinboundclaimtypemap.clear();

基本的openid connect授权请求

接下来,让我们从客户端请求openid scope的场景开始。
首先令人困惑的是microsoft使用openid和profile scope预先在openidconnectoptions上填充了scope集合。这意味着如果你只想请求openid,你首先需要清除scope集合,然后手动添加openid。

services.addauthentication(options =>
{
    options.defaultscheme = "cookies";
    options.defaultchallengescheme = "oidc";
})
    .addcookie("cookies", options =>
    {
        options.accessdeniedpath = "/account/denied";
    })
    .addopenidconnect("oidc", options =>
    {
        options.authority = "https://demo.identityserver.io";
        options.clientid = "server.hybrid";
        options.clientsecret = "secret";
        options.responsetype = "code id_token";
 
        options.savetokens = true;
                    
        options.scope.clear();
        options.scope.add("openid");
                    
        options.tokenvalidationparameters = new tokenvalidationparameters
        {
            nameclaimtype = "name", 
            roleclaimtype = "role"
        };
    });

使用asp.net core v1处理程序,将返回以下声明:nbf,exp,iss,aud,nonce,iat,c_hash,sid,sub,auth_time,idp,amr。

在v2中我们只能得到sid,sub和idp。发生了什么?

微软在其openid connect handler中添加了一个名为claimactions的新概念。claim actions用来实现自外部provider的claim如何映射(或不)到您的claimsprincipal中的claim。查看openidconnectoptions的构造函数,您可以看到,处理程序现在默认会跳过以下声明:

claimactions.deleteclaim("nonce");
claimactions.deleteclaim("aud");
claimactions.deleteclaim("azp");
claimactions.deleteclaim("acr");
claimactions.deleteclaim("amr");
claimactions.deleteclaim("iss");
claimactions.deleteclaim("iat");
claimactions.deleteclaim("nbf");
claimactions.deleteclaim("exp");
claimactions.deleteclaim("at_hash");
claimactions.deleteclaim("c_hash");
claimactions.deleteclaim("auth_time");
claimactions.deleteclaim("ipaddr");
claimactions.deleteclaim("platf");
claimactions.deleteclaim("ver");

如果您想“取消”跳过某项声明,则需要在设置handler时删除特定声明。以下是获取amr声明的非常直观的语法:

options.claimactions.remove("amr");

从oidc provider请求更多的claim

当你要求更多的范围时,例如个人资料或自定义范围导致更多索赔,还有另一个令人困惑的细节需要注意。
根据oidc协议中的response_type,某些声明通过id_token进行传输,有些通过userinfo端点进行传输。我在这里写了关于此细节的。
因此,首先您需要在处理程序中启用对userinfo端点的支持:

options.getclaimsfromuserinfoendpoint = true;

如果声明由userinfo返回,claimsactions将用于从返回的json文档映射claim到principal。这里使用以下默认设置:

claimactions.mapuniquejsonkey("sub", "sub");
claimactions.mapuniquejsonkey("name", "name");
claimactions.mapuniquejsonkey("given_name", "given_name");
claimactions.mapuniquejsonkey("family_name", "family_name");
claimactions.mapuniquejsonkey("profile", "profile");
claimactions.mapuniquejsonkey("email", "email");

如果您向您的客户发送的不属于上述列表的claim,它会被忽略,您需要进行明确的映射。例如您希望客户端通过userinfo(标准oidc声明之一,但不幸未由microsoft映射)获得website claim - 您需要自行添加映射:

options.claimactions.mapuniquejsonkey("website", "website");

这同样适用于您通过userinfo返回的任何其他声明。

我希望这有帮助。简而言之 – 你应该明确的知道你的映射,因为我相信这些默认映射将在可能会发生变化,这将导致您的客户端应用程序出现意外行为。