【问题标题】:How do you change the default AntiForgeryToken identifier in asp.net core mvc?如何更改 asp.net core mvc 中的默认 AntiForgeryToken 标识符?
【发布时间】:2019-08-17 07:28:17
【问题描述】:

我正在尝试在 .Net Core MVC 应用程序中使用 AWS Cognito 进行身份验证。

登录工作正常,但视图中的任何表单都不起作用,它们都给出了关于我的声明不包含“名称”-声明的错误。

我尝试手动添加名称声明,但仍然抛出错误。

你知道如何在 .net core 中配置它吗?

错误信息:

InvalidOperationException:提供的“System.Security.Claims.ClaimsIdentity”类型标识标记为 IsAuthenticated = true,但没有 Name 值。默认情况下,防伪系统要求所有经过身份验证的身份都具有唯一的名称。如果无法为此身份提供唯一名称,请考虑通过覆盖 DefaultAntiforgeryAdditionalDataProvider 或可为当前用户提供某种形式的唯一标识符的自定义类型来扩展 IAntiforgeryAdditionalDataProvider。

启动配置:

services.AddAuthentication(options =>
            {
                //Sets Default Scheme.
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

                //Must match the string for AddOAuth to set OAuth as default Challenge Scheme.
                options.DefaultChallengeScheme = "Cognito";
            })
               .AddCookie()
               .AddOAuth("Cognito", options =>
               {
                   options.ClientId = Configuration["Authentication:Cognito:ClientId"];
                   options.ClientSecret = Configuration["Authentication:Cognito:Secret"];
                   options.CallbackPath = new PathString("/sign-in");
                   options.AuthorizationEndpoint = "https://myauth.auth.eu-west-1.amazoncognito.com/oauth2/authorize";
                   options.TokenEndpoint = "https://myauth.auth.eu-west-1.amazoncognito.com/oauth2/token";
                   options.SaveTokens = true;
                   options.ClaimsIssuer = "https://cognito-idp.eu-west-1.amazonaws.com/ID";

                   options.Events = new OAuthEvents
                   {
                        //Adds Cognito id_token to Claims.
                        OnCreatingTicket = OnCreatingTicket
                   };
               });

手动添加名称标识符:

private static Task OnCreatingTicket(OAuthCreatingTicketContext context)
        {
            var handler = new JwtSecurityTokenHandler();

            //Cognito stores user information and Claims in the id_token.
            var idToken = context.TokenResponse.Response["id_token"];
            var jwtToken = handler.ReadJwtToken(idToken.ToString());

            var appIdentity = new ClaimsIdentity(jwtToken.Claims);
            foreach (var item in appIdentity.Claims)
            {
                if (item.Type == "sub")
                { 
                    var name = new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", item.Value);
                    var name2 = new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", item.Value);
                    appIdentity.AddClaim(name);
                    appIdentity.AddClaim(name2);
                break;
                }
            }

            context.Principal.AddIdentity(appIdentity);
            return Task.CompletedTask;
        }

【问题讨论】:

标签: asp.net-mvc asp.net-core .net-core asp.net-core-mvc asp.net-core-2.0


【解决方案1】:

我相信您在OnCreatingTicket 方法中手动创建的身份会被防伪功能忽略,因为它未被视为经过身份验证(请参阅source on GitHub,尤其是L51);原因是IsAuthenticated 属性依赖于AuthenticationType 属性不是null 或空的(请参阅source on source.dot.net)。

使用 ClaimsIdentity(IEnumerable<Claim> claims, string authenticationType) 构造函数重载应该使防伪系统将您的自定义身份考虑在内。

或者,为了避免完全创建自定义 ClaimsIdentity,您可以确保由 OAuth 身份验证提供程序创建的声明包含这些声明之一,默认情况下由 @ 中的 DefaultClaimUidExtractor 查找987654331@方法:

  • sub;
  • ClaimTypes.NameIdentifier,即http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier;和
  • ClaimTypes.Upnhttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn

【讨论】:

  • 感谢您的回复!我将上面的声明添加到令牌中,但我仍然遇到同样的错误。我注意到我在 Httpcontext.user 中有 2 个身份。第一个仅设置了 AuthenticationType,第二个具有所有声明。这是应该的吗?
  • 我认为你应该只有一个身份。 context.Principal 已经包含了一个身份,所以你应该给这个添加声明;您必须将 context.Principal.Identity 转换为 ClaimsIdentity 才能为其添加声明。
【解决方案2】:

仅添加名称标识符不起作用。经过大量谷歌搜索,这是您需要做的:

  1. 将名称标识符添加到 JWT
  2. 在启动时为提供者指定一个名称:

    var appIdentity = new ClaimsIdentity(jwtToken.Claims, CookieAuthenticationDefaults.AuthenticationScheme);
    

在第 2 步之后就解决了。

完整代码:

    private static Task OnCreatingTicket(OAuthCreatingTicketContext context)
    {
        var handler = new JwtSecurityTokenHandler();

        var idToken = context.TokenResponse.Response["id_token"];
        var jwtToken = handler.ReadJwtToken(idToken.ToString());

        var appIdentity = new ClaimsIdentity(jwtToken.Claims, CookieAuthenticationDefaults.AuthenticationScheme);

        context.Principal.AddIdentity(appIdentity);

        return Task.CompletedTask;
    }

【讨论】:

    猜你喜欢
    • 2021-09-18
    • 2019-06-09
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    • 2017-07-08
    • 2016-12-22
    • 1970-01-01
    相关资源
    最近更新 更多