Open Id Connect Doubts - Identity Server 4//如何将特定用户授予具体范围? [英] Open Id Connect Doubts - Identity Server 4 // How to grant specific users to concrete scopes?

查看:17
本文介绍了Open Id Connect Doubts - Identity Server 4//如何将特定用户授予具体范围?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读 Open Id 文档后,我有一些疑问.任何帮助将不胜感激.

I have some doubts after reading the Open Id docs. Any help will be much appreciated.

遵循任何 oidc 流程,您最终会获得一个 id_token 和一个 access_token.

Following any of the oidc flows you end by having an id_token and a access_token.

a)当您将 access_token 发送到受保护的 api 时,为什么或何时(示例)需要检索有关拥有它的用户的一些声明?也许如果受保护的 api 想要使用有关已验证用户的一些数据?

a)When you send the access_token to a protected api, why or when (example) it would need to retrieve some claims about the user who owns it? Maybe if the protected api wants to use some data about the authenticated user?

b) 为了获得声明,受保护的 api 需要与 UserEdnpoint 端点通信吗?它发送access_token?返回的 id_token 中包含哪些声明?/如果它要求更多声明用户具有同意访问权限,会发生什么?

b) For obtaining the claims the protected api will need to communicate with the UserEdnpoint endpoint? It sends the access_token? And which claims are contained in the returned id_token?/ What happens if it asks for more claims that the user has consent access?

c) 身份服务器 4:您定义要保护的资源.它们可以是身份资源"和api 资源".在定义 ApiResources 时,您可以在细粒度范围内定义.例如:

c)Identity server 4: You define resources to be protected. They could be "identity resources" and "api resources".While defining ApiResources you can define inside fine-grained scopes. For example:

  Scopes =
        {
            new Scope()
            {
                Name = "weather.api.full_access",
                DisplayName = "Full access to WEATHER API",
            },
            new Scope
            {
                Name = "weather.api.read_only",
                DisplayName = "Read only access to WEATHER API"
            }
        }

你还定义了客户端,以及他们有权访问的范围.您如何指定哪些用户可以访问特定资源?我不知道您将如何映射使用同一客户端的用户的特定权限.

Also you define the clients , and to which scopes they have access. How do yo you specify which users can access to specific resources? I don 't see how you will map specific permissions of users using the same client.

步骤如下:

  1. 授予客户端对两个范围的访问权限:"weather.api.full_access","weather.api.read_only"
  2. 现在......我如何授予,例如Billy"拥有weather.api.full_access"和Jhon"拥有weather.api.read_only"?他们使用的是同一个客户端.

非常感谢!!

推荐答案

IdentityServer 包含三个部分:

IdentityServer has three parts:

  1. ApiResource 配置
  2. 身份资源配置
  3. 用户信息(声明)

有两个令牌:访问令牌和身份令牌.访问令牌用于访问资源(api 和 UserInfo 端点),身份令牌包含有关用户的信息.

There are two tokens: the access token and the identity token. The access token is used to access resources (api and also UserInfo endpoint), the identity token contains information about the user.

虽然 IdentityServer 是关于对用户进行身份验证,但它也包含用于授权的配置.您可以使用 PolicyServer 之类的东西从 IdentityServer 中获取授权,但对于基本授权,您不必这样做.

While IdentityServer is about authenticating the user, it also contains configuration for authorization. You can use something like a PolicyServer to take the authorization out of IdentityServer, but for basic authorization you don't have to.

有两种类型的用户声明:

There are two types of user claims:

  1. 关于用户身份的声明,例如姓名、性别、生日等.
  2. 声明用户的权限,例如角色、employeeId 等.

第一组声明是身份令牌的一部分,告诉客户端用户是谁,其他声明是访问令牌的一部分,告诉 API 用户可以做什么.

The first set of claims are part of the identity token and tell the client about WHO the user is, the other claims are part of the access token and tell the API what the user is allowed to do.

关于身份令牌,您唯一可以依赖的是它始终包含 sub 声明(用户表中的 Id).这里的 filosophy 的简短版本是保持令牌小,因为您只需要那个声明.可以在 UserInfo 端点请求附加信息.身份令牌的内容可能会有所不同.例如.您可以强制将所有声明添加到第一个令牌 (AlwaysIncludeUserClaimsInIdToken) 以防止额外调用.

About the Identity Token, the only thing you can count on is the fact that it always contains the sub claim (the Id from the user table). The short version of the filosophy here is to keep the token small because all you need is that claim. Additional information can be requested at the UserInfo endpoint. The content of the identity tokencan vary. E.g. you can force to add all claims to the first token (AlwaysIncludeUserClaimsInIdToken) in order to prevent an additional call.

另一方面,如果用户选择不同意,那么身份令牌将保持为空(除了 sub 声明,因为需要 scope=openid).当从 UserInfo 端点请求时也是如此.

On the other hand, if the user chooses to not give consent then the identity token will remain empty (except for the sub claim, because scope=openid is required). Also when requested from the UserInfo endpoint.

那么问题是,您将如何使用身份令牌?代币有多少价值?您不应使用它来访问资源(这是访问令牌的用途),并且它可能不包含请求的信息.

So the question is, how are you going to use the identity token? How much value does the token have? You shouldn't use it to access resources (that's where the access token is for) and it may not contain the requested information.

关于访问令牌,这是实际上使客户端可以访问资源(api)的令牌.在 client_credentials 流中,没有用户(因此也不会有身份令牌),而在其他 flwos 中,客户端将代表用户进行操作.第一个流程与其他流程之间的区别在于 sub 声明.这会告诉 Api 代表客户端请求访问的人.

About the access token, this is the token that actually make it possible for the client to access a resource (api). In the client_credentials flow, there is no user (so there won't be an identity token as well), while in other flwos the client will act on behalf of the user. The difference between the first flow and the others is the sub claim. That tells the Api on who's behalf the client requests access.

对于访问令牌计数相同,如果用户不同意,则客户端将无法访问资源.

For access tokens counts the same, if the user doesn't give consent then the client will not be able to access the resource.

关于资源和范围.资源是资源的逻辑名称.我的意思是,您可能有多个属于同一资源的 Api.没关系.因为一种资源可以有多个作用域.在示例中它是 1:1,但是当您真正使用范围​​时,您会看到范围实际上定义了资源中的某个功能.像微服务.

About resources and scopes. A resource is a logical name of a resource. By that I mean that it is possible that you have multiple Api's that are part of the same resource. That's fine. Because one resource can have many scopes. In the examples it is 1:1, but when you are really using scopes, then you'll see that a scope actually defines a certain piece of functionality within the resource. Like micro services.

回到 IdentityServer.IdentityServer 的一项重要工作是过滤声明.因为用户可以有很多声明,但您只在需要时才需要.因此,每个令牌都会添加请求的声明.

Back to IdentityServer. An important job of IdentityServer is to filter claims. Because the user can have many claims, but you only want them when you need them. So per token the requested claims are added.

身份令牌声明可以说明用户是谁.但还有更多,这些声明与上下文无关.他们永远是真的.你的名字在任何地方都是一样的,你的生日也是如此.使用 IdentityResource 表来定义范围,例如openid、个人资料、电子邮件.

The Identity Token claims tell something about who the user is. But there is more, these claims are not context dependent. They are always true. Your name is everywhere the same, so is your birthday, etc. Use the IdentityResource table to define the scopes, e.g. openid, profile, email.

访问令牌中的声明取决于上下文.因为只有 API 知道声明的含义.使用命名空间类型来区分声明.

The claims in the access token are context dependent. Because only the API knows what a claim means. Use namespace types to distinct between claims.

如何设置 Api 资源并不重要,只要记住,当一个范围被请求时,来自该资源(包括该资源中的其他范围)的所有声明都被添加到请求过滤器中,而当一个范围被请求时请求,只有该范围的声明被添加到请求过滤器中.用于将来自用户的所有匹配声明添加到令牌的请求过滤器.

It doesn't really matter how the Api resource is setup, just remember that when a scope is requested all claims from the resource (including the other scopes in that resource) are added to the request filter, while when a scope is requested, only the claims for that scope are added to the request filter. The request filter that is used to add all matching claims from the user to the token.

现在你有了一个访问令牌.令牌必须包含有关范围的信息.为什么?因为您不希望客户端访问不允许的资源.通过定义每个客户端的范围来限制访问.由于范围是一项功能,您知道客户端需要哪些范围.在 IdentityServer 中,您配置相同的范围以匹配客户端.永远不要相信客户.

So now you have an access token. The token must contain information about the scopes. Why? Because you don't want clients to access resources that are not allowed. Limit access by defining the scopes per client. As a scope is a piece of functionality, you know which scopes the client needs. In the IdentityServer you configure the same scopes in order to match the client. Never trust a client.

访问令牌包含来自请求的范围/资源的所有声明.这意味着使用该令牌可以使用该令牌访问资源/范围内的所有 api,而无需为每个 api 获取新令牌.

The access token contains all claims from the requested scope/resources. That means that with that token all api's within the resource/scope can be accessed with that token, without having to obtain a new token per api.

这也意味着令牌可以变得非常大.在达到限制之前你应该避免的事情.这就是为什么您不想要令牌中的权限.如果您需要权限,请实现您自己的授权服务器.

This also means that the token can become quite large. Something you should avoid before hitting limits. That is why you don't want permissions in the token. If you want permissions, then implement your own authorization server.

另一方面,您需要权限吗?给定一个设计,其中 Api(资源)知道允许用户访问什么,使用策略(某种业务规则)和基于资源的授权.您可以实现一个包含权限信息的本地用户表.

On the other hand, do you need permissions? Given a design where the Api (resource) knows what a user is allowed to access, use policies (sort of business rules) and resource based authorization. You can implement a local user table that contains information about the permissions.

此外,您真的需要对每个对象都具有 CRUD 权限吗?通过策略,您有机会定义更复杂的授权,而不仅仅是比较字符串值.

Also, do you really need CRUD permissions on every object? With policies you have the chance to define more complex authorization than just comparing string values.

对于用户来说,用户是身份的资源.但对作用域一无所知.所以你不能将范围绑定到用户.客户端有作用域,它打开了 api 的大门,但 api 决定用户是否真正拥有访问权限.

As for the user, the user is the resource for the identity. But knows nothing about scopes. So you can't bind scopes to users. The client has scopes, which opens the door to the api, but the api decides whether the user actually has access.

现在回答您的问题:

a) 来自用户的与请求的声明类型匹配的所有声明都被添加到访问令牌中.请求的声明类型取自请求的范围.添加与请求范围相关的所有 ApiResource 声明类型以及请求范围本身的声明类型.

a) All claims from the user that match the requested claim types are added to the access token. Where requested claim types are taken from the requested scopes. Where all ApiResource claim types that are related to the requested scopes are added and the claim types of the requested scopes themselves.

如果 Api 需要有关用户的信息,那么它可以使用访问令牌来调用 UserInfo 端点.默认身份令牌仅包含 sub 声明(用户无法拒绝或撤销).

If the Api needs information about the user, then it can use the access token to call the UserInfo endpoint. The default identity token only contains the sub claim (something the user can't deny or revoke).

b) 通过向客户端添加范围来请求令牌.默认情况下添加 openid,配置文件范围.客户端凭据不会收到身份令牌,并且有一个额外的令牌,即刷新令牌.请注意,并非所有流都可以使用此令牌.要请求刷新令牌,请添加 offline_access 范围.您可以在哪里离线访问文字.这是一个令牌,允许客户端请求新的访问令牌,而无需用户输入.因此,即使用户离线,服务仍可继续.

b) The tokens are requested by adding scopes to the client. By default the openid, profile scopes are added. The client credentials will not receive an identity token and there is one additional token, the refresh token. Please note that this token is not available to all flows. To request the refresh token add the offline_access scope. Where you can take offline access literal. This is a token that allows the client to request new access tokens, without requiring user input. So in case the user is offline, the service can still proceed.

当需要用户同意时,某些信息或选项可能不可用.例如.如果用户不想离线访问,则该服务(例如某些同步服务)将无法运行.当用户撤销给定的同意时也会发生这种情况.请求新的访问令牌将导致未经授权的响应.

When user consent is required then it is possible that certain information or options are not available. E.g. if the user doesn't want offline access, then the service (e.g. some synchronization service) will not be able to run. This also occurs when the user revokes a given consent. Requesting new access token will result in an unauthorized response.

为了绕过丢失的用户信息,只需向用户询问信息并将其存储在本地即可.无论如何,您很可能在那里需要它.

In order to bypass missing user information, simply ask the user for information and store it locally. You are most likely going to need it there anyway.

c) 忘记权限,使用策略和基于资源的授权.在 Api 中实现它.那是知道确切上下文的地方.客户端可以打开 api 的大门,但是否可以访问资源取决于用户(声明、本地授权信息).

c) Forget permissions, use policies and resource based authorization. Implement this in the Api. That's the place where the exact context is known. The client can open the door to the api, but it depends on the user (claims, local authorization info) if the resource can be accessed.

假设您有资源weather"和范围weather.api.full_access"和weather.api.read_only"(作为资源weather"的一部分).

Suppose you have the resource 'weather' and scopes 'weather.api.full_access' and 'weather.api.read_only' (as part of the resource 'weather').

请注意,名称weather.api.full_access"并未说明访问级别,仅说明了预期的功能.

Please note that the name 'weather.api.full_access' doesn't say anything about the level of access, only about the expected functionality.

实际访问级别应基于来自资源或策略的本地信息,例如用户具有阅读订阅或管理员角色.

The actual access level should be based on local information from the resource or policies, e.g. user has a read subscription or an admin role.

为了给 Billy 完全访问权限,向 Billy 添加 http://api/admin(值:true)声明.并为 Jhon 在订阅表中添加一条记录.

In order to give Billy full access add the http://api/admin (value: true) claim to Billy. And for Jhon add a record in the subscriptions table.

为了将资源划分到多个 api(每个范围),请使用事件来验证范围.您不希望客户端在仅请求读取范围时访问 full_access 功能.

In order to divide a resource over multiple api's (per scope), use events to validate the scope. You don't want a client to access the full_access functionality when only the read scope was requested.

我希望这对您有意义.很难给出一个简短而完整的答案.如果您对此答案有任何疑问,请告诉我.

I hope this makes sense to you. It's hard to give a short and complete answer. Let me know if you have questions about this answer.

简而言之,IdentityServer 可以实现这一切.如果您需要权限,请查看策略服务器.

In short, IdentityServer can implement it all. If you want permissions then take a look at the policy server.

这篇关于Open Id Connect Doubts - Identity Server 4//如何将特定用户授予具体范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆