Open Id Connect疑问-Identity Server 4//如何向特定用户授予具体作用域? [英] Open Id Connect Doubts - Identity Server 4 // How to grant specific users to concrete scopes?

查看:89
本文介绍了Open Id Connect疑问-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. IdentityResource配置
  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).此处的简短形式是使令牌保持较小,因为您所需要的只是该声明.可以在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.

另一方面,如果用户选择不同意,则身份令牌将保持为空(子声明除外,因为必须使用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流中,没有用户(因此也不会有身份令牌),而在其他流程中,客户端将代表用户进行操作.第一个流程与其他流程之间的区别是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.api.full_access"和"weather.api.read_only"(作为资源天气"的一部分).

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完全访问权限,请添加 http://api/admin (值:true)声明为比利对于Jhon,在subscriptions表中添加一条记录.

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疑问-Identity Server 4//如何向特定用户授予具体作用域?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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