简体   繁体   English

如何使用IdentityServer4进行微服务架构的基于角色的授权?

[英]How do role-based authorization using identityserver4 for microservices architecture?

Prehistory: 史前史:
I develop authentication and authorization for microservices using IdentityServer4, but have problem with authorization. 我使用IdentityServer4开发了微服务的身份验证和授权,但是授权有问题。 I have two services: 我有两项服务:
- service with identityserver4, it's my auth service -IdentityServer4服务,这是我的身份验证服务
- test MVC project -测试MVC项目

I successfully connect these services and use Hybrid flow, and authentication work successfully, and also my roles works, because I include roles in JWT token using custom ProfileService on auth service side. 我成功连接了这些服务并使用混合流,并且身份验证也成功完成,并且我的角色也可以正常工作,因为我在auth服务端使用自定义ProfileService在JWT令牌中包含了角色。

Problem situation: 问题情况:
1. User have not any auth token. 1.用户没有任何身份验证令牌。 Try open page with [Authorize(Roles = "Admin")] attribute on MVC site and redirect to page on Auth service. 尝试在MVC网站上使用[Authorize(Roles = "Admin")]属性打开页面,然后重定向到Auth服务上的页面。 2. User enter login and password. 2.用户输入登录名和密码。
3. Got token with Role=Admin, redirect back to MVC site on Auth service. 3.使用Role = Admin获得令牌,重定向回Auth服务上的MVC站点。
4. Page opened for user, because he had Admin role. 4.为用户打开页面,因为他具有管理员角色。
5. Remove user from Admin role on Auth Service. 5.从身份验证服务的管理员角色中删除用户。
6. Reload page and page again opened fine for this user, and it's correct, because in token he had role admin. 6.重新加载页面,然后再次为该用户打开页面,这是正确的,因为他具有管理员角色。

Question: How I can actualize token after change roles or claims on auth service side? 问:在身份验证服务端更改角色或声明后,如何实现令牌?

IdentityServer Config: IdentityServer配置:

public static IEnumerable<Client> GetClients()
        {
            return new Client[]
            {
                new Client
                {
                    ClientId = "Epp.Web.Mvc",
                    ClientName = "Единый Портал Потребителей",
                    AllowedGrantTypes = new List<string>{GrantType.Hybrid},
                    ClientSecrets = new List<Secret>
                    {
                        new Secret("secret".Sha256())
                    },
                    RequireConsent = false,
                    AllowAccessTokensViaBrowser = true,
                    AlwaysIncludeUserClaimsInIdToken = true,
                    AlwaysSendClientClaims = true,
                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "epp",
                        "roles"
                    },
                    RedirectUris = new List<string>
                    {
                        "http://localhost:5002/signin-oidc",
                        "https://localhost:5003/signin-oidc"
                    },
                    PostLogoutRedirectUris = new List<string>{ "http://localhost:5002/signout-callback-oidc" },
                    AccessTokenLifetime = 60 * 10 
                }
            };
        }

MVC Startup: MVC启动:

services.AddAuthentication(options =>
                {
                    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = "oidc";
                })
                .AddCookie(setup => setup.ExpireTimeSpan = TimeSpan.FromHours(2))
                .AddOpenIdConnect("oidc", options =>
                    {
                        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                        options.Authority = "https://localhost:5001";
                        options.ClientId = "Epp.Web.Mvc";
                        options.ResponseType = "code id_token";
                        options.ClientSecret = "secret";

                        options.GetClaimsFromUserInfoEndpoint = true;
                        options.SaveTokens = true;
                        options.RequireHttpsMetadata = false;


                        options.Scope.Add(IdentityServerConstants.StandardScopes.OpenId);
                        options.Scope.Add(IdentityServerConstants.StandardScopes.Profile);
                        options.Scope.Add("epp");
                        options.Scope.Add("roles");
                        options.TokenValidationParameters = new TokenValidationParameters
                        {
                            NameClaimType = "name",
                            RoleClaimType = "role"
                        };
                    });

Actually the question is not specifically about OpenId-Connect, nor Identity server. 实际上,问题不仅仅与OpenId-Connect有关,也不与Identity Server有关。 It's more a generic question about how long to keep some cached (security) data. 关于将某些缓存(安全)数据保留多长时间,这是一个更普遍的问题。 JWT is immutable by design, so you can treat it as a kind of cache. JWT在设计上是不可变的,因此您可以将其视为一种缓存。 Once the cached item (or a jwt) expires, we get a new one. 一旦缓存的项(或jwt)过期,我们将获得一个新项。 So the only solution is to set a reasonably short expiration for your bearer token and use a refresh one to "actualize" the bearer. 因此,唯一的解决方案是为您的承载令牌设置一个合理的短到期时间,并使用刷新来“实现”承载。

I personally can't see how changing roles to scopes for a given service can help. 我个人看不到将角色更改为给定服务的范围有什么帮助。 That's about a bit different thing. 那是另一回事。 We can more or less constantly define that application1 has access to service1.write scope, and by that restrict All but application1' users from access to the API. 我们可以或多或少不断地定义application1有权访问service1.write范围,从而限制了All but application1' users对API的访问。 But what if the app is universal? 但是,如果该应用程序具有通用性,该怎么办? No answer here. 这里没有答案。

Another suggestion was to use reference tokens and invalidate when necessary. 另一个建议是使用参考标记,并在必要时使之无效。 Well, you could do. 好吧,你可以做。 But by default the API caches the reference token validation' result, so... We get the same problem in a new place. 但是默认情况下,API会缓存参考令牌验证的结果,因此...我们在一个新地方遇到了同样的问题。

What should work is moving role based authorization into each service, as @VidmantasBlazevicius suggested, but again inside the service you most likely have some cache, so you again have to think how to invalidate it when necessary. 正如@VidmantasBlazevicius所建议的那样,应该将基于角色的授权移动到每个服务中,但是再次在该服务内部您很可能拥有一些缓存,因此您必须再次考虑如何在必要时使它无效。

I see 2 way to do it as below, 我看到以下两种方法

  1. You can user reference token flow and invalidate token when changes occurs in your role/rights. 您可以在角色/权限发生更改时用户参考令牌流并使令牌无效。 Check link http://docs.identityserver.io/en/latest/topics/reference_tokens.html 检查链接http://docs.identityserver.io/en/latest/topics/reference_tokens.html

  2. Or as mentioned by @Vidmantas Blazevicius, move role based authorization job to respective service rather than relay on identity server. 或如@Vidmantas Blazevicius所述,将基于角色的授权作业移至各自的服务,而不是在身份服务器上进行中继。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 IdentityServer4 基于角色的授权正确使用 - IdentityServer4 role based authorization correct use 如何从IdentityServer4授权中获得角色? - How can I get a role from IdentityServer4 authorization? 使用Identity 2.0的Web froms中基于角色的安全授权 - Role-based Security Authorization in web froms using Identity 2.0 使用 .NET MVC 5 实现基于角色的授权 - Implementing role-based authorization using .NET MVC 5 使用 eShopOnContainers .NET 微服务架构 - 使用 AD B2C 而不是 IdentityServer4 进行微服务身份验证 - Using eShopOnContainers .NET microservices architecture - Use AD B2C instead of IdentityServer4 for microservice authentication 基于身份角色的授权不起作用 - Identity Role-based Authorization is not working IdentityServer4 基于角色的 Web API 授权与 ASP.NET Core 标识 - IdentityServer4 Role Based Authorization for Web API with ASP.NET Core Identity ASP.NET Core Identity的IdentityServer4基于角色的授权=访问被拒绝 - IdentityServer4 Role Based Authorization for ASP.NET Core Identity = Access Denied 使用 IdentityServer4 和 Keycloak 18 进行基于角色的身份验证 - Role based auth with IdentityServer4 and Keycloak 18 如何将 IdentityServer4 身份验证与授权分开 - How to seperate IdentityServer4 authentication from authorization
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM