微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将 Okta 声明映射到 .NET Blazor 中的角色

如何解决将 Okta 声明映射到 .NET Blazor 中的角色

我有一个与 Okta 集成的 .NET 5.0(从 .NET Core 升级)托管的 Blazor 解决方案。

我可以毫无问题地登录,但是当我被重定向回我的应用程序时,我遇到了将角色映射到声明的问题。


   Unhandled exception rendering component: InvalidOperation_EnumFailedVersion

system.invalidOperationException: InvalidOperation_EnumFailedVersion

  at System.Collections.Generic.List`1.Enumerator[[System.Security.Claims.Claim,System.Security.Claims,Version=5.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a]].MoveNextRare()

  at System.Collections.Generic.List`1.Enumerator[[System.Security.Claims.Claim,PublicKeyToken=b03f5f7f11d50a3a]].MoveNext()

  at System.Security.Claims.ClaimsIdentity.FindAll(Predicate`1 match)+MoveNext()

  at WFBC.Client.RolesClaimsPrincipalFactory.createuserAsync(RemoteUserAccount account,RemoteAuthenticationUserOptions options)

  at Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationService`3.<GetAuthenticatedUser>d__26[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationState,Microsoft.AspNetCore.Components.WebAssembly.Authentication,Version=5.0.2.0,PublicKeyToken=adb9793829ddae60],[Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteUserAccount,[Microsoft.AspNetCore.Components.WebAssembly.Authentication.OidcProviderOptions,PublicKeyToken=adb9793829ddae60]].MoveNext()

这里抛出错误

namespace WFBC.Client
{
    public class RolesClaimsPrincipalFactory : AccountClaimsPrincipalFactory<RemoteUserAccount>
    {
        public RolesClaimsPrincipalFactory(IAccesstokenProviderAccessor accessor) : base(accessor)
        {
        }

        public override async ValueTask<ClaimsPrincipal> createuserAsync(RemoteUserAccount account,RemoteAuthenticationUserOptions options)
        {
            var user = await base.createuserAsync(account,options);
            if (!user.Identity.IsAuthenticated)
            {
                return user;
            }

            var identity = (ClaimsIdentity)user.Identity;
            var roleClaims = identity.FindAll(claim => claim.Type == "groups");
            if (roleClaims == null || !roleClaims.Any())
            {
                return user;
            }

            foreach (var existingClaim in roleClaims)
            {
                identity.RemoveClaim(existingClaim);
            }

            var rolesElem = account.AdditionalProperties["groups"];
            if (!(rolesElem is JsonElement roles))
            {
                return user;
            }

            if (roles.ValueKind == JsonValueKind.Array)
            {
                foreach (var role in roles.EnumerateArray())
                {
                    identity.AddClaim(new Claim(options.RoleClaim,role.GetString()));
                }
            }
            else
            {
                identity.AddClaim(new Claim(options.RoleClaim,roles.GetString()));
            }

            return user;
        }
    }
}

这个 foreach 循环似乎是异常的来源:

            foreach (var existingClaim in roleClaims)
            {
                identity.RemoveClaim(existingClaim);
            }

我能找到的唯一信息似乎指向尝试修改 IEnumerable,但在这种情况下我不是。 roleClaims一个 IEnumerable,但身份是一个 ClaimsIdentity 对象。

这以前是有效的,所以我不确定它是由 .NET 5.0 升级还是 Okta nuget 包的一些更改引起的。不幸的是,Blazor 调试到客户端项目还远未做好生产准备,目前对我不起作用。

解决方法

试试这个代码:

public class RolesClaimsPrincipalFactory : AccountClaimsPrincipalFactory<RemoteUserAccount>
    {
        public RolesClaimsPrincipalFactory(IAccessTokenProviderAccessor accessor) : base(accessor)
        {
        }

        public override async ValueTask<ClaimsPrincipal> CreateUserAsync(RemoteUserAccount account,RemoteAuthenticationUserOptions options)
        {
            var user = await base.CreateUserAsync(account,options);
            if (user.Identity.IsAuthenticated)
            {
                var identity = (ClaimsIdentity)user.Identity;
                var roleClaims = identity.FindAll(identity.RoleClaimType);
                if (roleClaims != null && roleClaims.Any())
                {
                    foreach (var existingClaim in roleClaims)
                    {
                        identity.RemoveClaim(existingClaim);
                    }

                    var rolesElem = account.AdditionalProperties[identity.RoleClaimType];
                    if (rolesElem is JsonElement roles)
                    {
                        if (roles.ValueKind == JsonValueKind.Array)
                        {
                            foreach (var role in roles.EnumerateArray())
                            {
                                identity.AddClaim(new Claim(options.RoleClaim,role.GetString()));
                            }
                            
                        }
                        else
                        {
                            identity.AddClaim(new Claim(options.RoleClaim,roles.GetString()));
                        }
                    }
                }
            }

            return user;
        }
    }

不要忘记 Program.Main 中的 .AddAccountClaimsPrincipalFactory<RolesClaimsPrincipalFactory>();

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。