使用 OpenID Connect 配置 Elastic Stack 的单点登录
编辑使用 OpenID Connect 配置 Elastic Stack 的单点登录
编辑Elastic Stack 支持通过 Kibana 使用 OpenID Connect 进行单点登录 (SSO),其中 Elasticsearch 作为后端服务,拥有大部分功能。Kibana 和 Elasticsearch 一起代表一个 OpenID Connect 依赖方 (RP),支持 OpenID Connect 规范中定义的授权码流和隐式流。
本指南假设您拥有一个 OpenID Connect 提供程序,将在其中注册 Elastic Stack 依赖方。
Kibana 中的 OpenID Connect 领域支持的设计预期是它将成为该 Kibana 实例用户的主要身份验证方法。配置 Kibana 部分描述了这意味着什么,以及如何在必要时设置它来支持其他领域。
OpenID Connect 提供程序
编辑OpenID Connect 提供程序 (OP) 是 OpenID Connect 中的实体,负责对用户进行身份验证,并授予带有身份验证和用户信息(供依赖方使用)的必要令牌。
为了让 Elastic Stack 能够使用您的 OpenID Connect 提供程序进行身份验证,需要在 OP 和 RP 之间建立信任关系。在 OpenID Connect 提供程序中,这意味着将 RP 注册为客户端。OpenID Connect 定义了一个动态客户端注册协议,但这通常是针对实时客户端注册,而不是跨安全域单点登录的信任建立过程。所有 OP 还允许通过用户界面或(较少情况下)通过使用元数据文档手动注册 RP 作为客户端。
注册 Elastic Stack RP 的过程因 OP 而异,遵循提供商的相关文档是谨慎的。您通常需要为注册提供的 RP 信息如下
-
依赖方名称
:依赖方的任意标识符。规范和 Elastic Stack 实现都没有对此值施加任何约束。 -
重定向 URI
:这是 OP 在身份验证后将用户浏览器重定向到的 URI。此值的适当值取决于您的设置以及 Kibana 是否位于代理或负载均衡器之后。它通常是${kibana-url}/api/security/oidc/callback
(对于授权码流)或${kibana-url}/api/security/oidc/implicit
(对于隐式流),其中 ${kibana-url} 是您的 Kibana 实例的基本 URL。您可能还会看到它被称为回调 URI
。
在注册过程结束时,OP 将为 RP(Elastic Stack)分配一个客户端标识符和一个客户端密钥以供使用。记下这两个值,因为它们将在 Elasticsearch 配置中使用。
为 OpenID Connect 身份验证配置 Elasticsearch
编辑以下是启用 Elasticsearch 中使用 OpenID Connect 进行身份验证所需的配置步骤摘要
为 HTTP 启用 TLS
编辑如果您的 Elasticsearch 集群在生产模式下运行,那么在启用 OpenID Connect 身份验证之前,您必须配置 HTTP 接口以使用 SSL/TLS。
有关更多信息,请参阅 加密 Elasticsearch 的 HTTP 客户端通信。
启用令牌服务
编辑Elasticsearch OpenID Connect 实现使用了 Elasticsearch 令牌服务。如果您在 HTTP 接口上配置了 TLS,则此服务会自动启用,也可以通过在 elasticsearch.yml
文件中包含以下内容来显式配置
xpack.security.authc.token.enabled: true
创建 OpenID Connect 领域
编辑通过在 Elasticsearch 的身份验证链中配置适当的领域来启用基于 OpenID Connect 的身份验证。
此领域有一些强制性设置和一些可选设置。可用设置在 OpenID Connect 领域设置中有详细描述。本指南将探讨最常见的设置。
在您的 elasticsearch.yml
文件中创建一个 OpenID Connect(领域类型为 oidc
)领域,类似于下面所示
下面使用的值旨在作为示例,并非旨在适用于所有用例。配置片段下方的详细信息提供了见解和建议,以帮助您根据 OP 配置选择适当的值。
xpack.security.authc.realms.oidc.oidc1: order: 2 rp.client_id: "the_client_id" rp.response_type: code rp.redirect_uri: "https://kibana.example.org:5601/api/security/oidc/callback" op.issuer: "https://op.example.org" op.authorization_endpoint: "https://op.example.org/oauth2/v1/authorize" op.token_endpoint: "https://op.example.org/oauth2/v1/token" op.jwkset_path: oidc/jwkset.json op.userinfo_endpoint: "https://op.example.org/oauth2/v1/userinfo" op.endsession_endpoint: "https://op.example.org/oauth2/v1/logout" rp.post_logout_redirect_uri: "https://kibana.example.org:5601/security/logged_out" claims.principal: sub claims.groups: "http://example.info/claims/groups"
上面示例中使用的配置值是
- xpack.security.authc.realms.oidc.oidc1
- 这定义了一个名为“oidc1”的新
oidc
身份验证领域。有关领域的更多解释,请参阅 领域。 - order
- 您应该在身份验证链中的每个领域上定义一个唯一的顺序。建议将 OpenID Connect 领域放在身份验证链的底部(即,它具有最高顺序)。
- rp.client_id
- 这个通常是不透明的任意字符串,是 OP 在注册时分配给 Elastic Stack RP 的客户端标识符。
- rp.response_type
-
这是一个标识符,用于控制此 RP 支持哪个 OpenID Connect 身份验证流,以及此 RP 请求 OP 应遵循哪个流。支持的值为
-
code
,这意味着 RP 要使用授权码流。如果您的 OP 支持授权码流,则应选择此项而不是隐式流。 -
id_token token
,这意味着 RP 要使用隐式流,并且我们还要求 OP 提供 oAuth2 访问令牌,我们可以将其用于后续请求(UserInfo)。如果 OP 在其配置中提供 UserInfo 端点,或者如果您知道用于角色映射的声明在 ID 令牌中不可用,则应选择此项。 -
id_token
,这意味着 RP 要使用隐式流,但不感兴趣获取 oAuth2 令牌。如果您确定所有必要的声明都将包含在 ID 令牌中,或者 OP 不提供用户信息端点,则选择此项。
-
- rp.redirect_uri
- OP 在身份验证后将浏览器重定向到的重定向 URI。这需要与在注册时向 OP 配置的 URI完全相同,并且通常是
${kibana-url}/api/security/oidc/callback
,其中 ${kibana-url} 是您的 Kibana 实例的基本 URL - op.issuer
- 您的 OpenID Connect 提供程序的可验证标识符。颁发者标识符通常是区分大小写的 URL。此设置的值应由您的 OpenID Connect 提供程序提供。
- op.authorization_endpoint
- OP 中授权端点的 URL。这是将用户浏览器重定向以开始身份验证过程的位置。此设置的值应由您的 OpenID Connect 提供程序提供。
- op.token_endpoint
- OpenID Connect 提供程序中令牌端点的 URL。这是 Elasticsearch 将向其发送请求以将代码交换为 ID 令牌的端点。当您使用隐式流时,此设置是可选的。此设置的值应由您的 OpenID Connect 提供程序提供。
- op.jwkset_path
- 包含 JSON Web 密钥集的文件的路径或 URL,该密钥集包含 OpenID Connect 提供程序用于签名令牌和声明响应的密钥材料。如果设置了路径,则相对于 Elasticsearch 配置目录解析该路径。Elasticsearch 将自动监视此文件的更改,并在更新时重新加载配置。您的 OpenID Connect 提供程序应为您提供此文件或它可用的 URL。
- op.userinfo_endpoint
- (可选)OpenID Connect 提供程序中用户信息端点的 URL。这是 OP 的端点,如果需要,可以查询该端点以获取更多用户信息。此设置的值应由您的 OpenID Connect 提供程序提供。
- op.endsession_endpoint
- (可选)OpenID Connect 提供程序中结束会话端点的 URL。如果将领域配置为 RP 发起的单点注销并且 OP 支持它,则这是在本地注销后将用户浏览器重定向到的端点。此设置的值应由您的 OpenID Connect 提供程序提供。
- rp.post_logout_redirect_uri
- (可选)在成功单点注销后,OpenID Connect 提供程序应将用户重定向到的重定向 URL(假设也设置了上面的
op.endsession_endpoint
)。应将其设置为不会触发新的 OpenID Connect 身份验证的值,例如${kibana-url}/security/logged_out
或${kibana-url}/login?msg=LOGGED_OUT
,其中 ${kibana-url} 是您的 Kibana 实例的基本 URL。 - claims.principal
- 请参阅 声明映射。
- claims.groups
- 请参阅 声明映射。
OpenID Connect 领域配置的最后一步是设置在 OP 中注册期间分配给 RP 的 Client Secret
。这是一个安全设置,因此不在 elasticsearch.yml
的领域配置中定义,而是添加到 Elasticsearch 密钥库中。例如:
bin/elasticsearch-keystore add xpack.security.authc.realms.oidc.oidc1.rp.client_secret
更改 client_secret
需要重启 Elasticsearch 节点才能生效。
根据 OpenID Connect 规范,OP 还应该在其众所周知的 URL 上提供其配置,该 URL 是其 Issuer
值与 .well-known/openid-configuration
字符串的串联。例如:https://op.org.com/.well-known/openid-configuration
。该文档应包含配置 Elasticsearch 中的 OpenID Connect 领域所需的所有信息。
声明映射
编辑声明和作用域
编辑使用 OpenID Connect 验证 Kibana 的身份时,OP 将以 OpenID Connect 声明的形式提供有关用户的信息,这些声明可以包含在 ID 令牌中,或者从 OP 的 UserInfo 端点检索。声明被定义为 OP 为已验证用户断言的一段信息。简单来说,声明是包含有关用户信息的名称/值对。与声明相关,我们还有 OpenID Connect 作用域的概念。作用域是用于请求访问特定声明列表的标识符。标准定义了一组可以请求的作用域标识符。唯一强制的是 openid
,而常用的作用域是 profile
和 email
。profile
作用域请求访问 name
、family_name
、given_name
、middle_name
、nickname
、preferred_username
、profile
、picture
、website
、gender
、birthdate
、zoneinfo
、locale
和 updated_at
声明。email
作用域请求访问 email
和 email_verified
声明。其流程是,RP 在身份验证请求期间请求特定的作用域。如果 OP 隐私政策允许并且验证用户同意,则相关的声明将返回给 RP(在 ID 令牌中或作为 UserInfo 响应)。
支持的声明列表将因您使用的 OP 而异,但您可以预期 标准声明 将在很大程度上得到支持。
将声明映射到用户属性
编辑声明映射的目标是配置 Elasticsearch,以便能够将指定的返回声明的值映射到 Elasticsearch 支持的 用户属性之一。然后,这些用户属性用于在 Kibana UI 或审计日志中标识用户,也可以用于创建 角色映射规则。
配置 OpenID 声明映射的推荐步骤如下:
- 查阅您的 OP 配置,查看它可能支持哪些声明。请注意,OP 的元数据或 OP 配置页面中提供的列表是可能支持的声明列表。但是,出于隐私原因,它可能不是一个完整的列表,或者并非所有受支持的声明都可用于所有已验证的用户。
- 通读 Elasticsearch 支持的 用户属性列表,并确定其中哪些对您有用,并且可以通过 OP 以声明的形式提供。至少需要
principal
用户属性。 -
配置您的 OP 以将这些声明“释放”到您的 Elastic Stack 依赖方。此过程因提供商而异。您可以使用静态配置,而其他提供商将支持 RP 请求与身份验证时要“释放”的声明相对应的作用域。有关如何配置要请求的作用域的详细信息,请参阅
rp.requested_scopes
。为了确保互操作性并最大限度地减少错误,您应该仅请求 OP 支持且您打算映射到 Elasticsearch 用户属性的作用域。NOTE: You can only map claims with values that are strings, numbers, boolean values or an array of the aforementioned.
-
在 Elasticsearch 中配置 OpenID Connect 领域,以将 Elasticsearch 用户属性(请参阅下面的 列表)与您的 OP 将释放的声明名称相关联。在上面的示例中,我们已按如下方式配置
principal
和groups
用户属性:-
claims.principal: sub
:这指示 Elasticsearch 在 OP 为用户颁发的 ID 令牌(或在 UserInfo 响应中)中查找名为sub
的 OpenID Connect 声明,并将此声明的值分配给principal
用户属性。sub
是 principal 属性常用的声明,因为它是 OP 中用户的标识符,并且也是 ID 令牌的必需声明,从而保证了它的可用性。但是,这里仅用作示例,OP 可能会提供另一个更适合您需求的声明。 -
claims.groups: "http://example.info/claims/groups"
:同样,这指示 Elasticsearch 在 ID 令牌或 UserInfo 响应中查找名为http://example.info/claims/groups
的声明(请注意,这是一个 URI - 标识符,被视为字符串,而不是指向将被检索的位置的 URL),并将其值映射到 Elasticsearch 中的用户属性groups
。规范中没有用于表示 OP 中已验证用户的角色或组成员资格的标准声明,因此此处应映射的声明名称在提供商之间差异很大。有关更多详细信息,请参阅您的 OP 文档。
-
Elasticsearch 用户属性
编辑可以配置 Elasticsearch OpenID Connect 领域,以将 OpenID Connect 声明映射到已验证用户的以下属性:
- principal
-
(必需)这是将应用于针对此领域进行身份验证的用户的用户名。
principal
出现在诸如 Elasticsearch 审计日志之类的地方。
如果 principal 属性未能从声明中映射,则身份验证将失败。
- groups
-
(推荐)如果您希望使用 OP 的组或角色概念作为用户 Elasticsearch 权限的基础,则应使用此属性对其进行映射。
groups
将直接传递到您的 角色映射规则。 - name
- (可选)用户的全名。
- (可选)用户的电子邮件地址。
- dn
- (可选)用户的 X.500 专有名称。
从 OpenID Connect 声明中提取部分值
编辑在某些情况下,声明的值可能包含比您希望在 Elasticsearch 中使用的更多信息。一个常见的例子是 OP 专门使用电子邮件地址,但您希望用户的 principal
使用电子邮件地址的本地名称部分。例如,如果他们的电子邮件地址是 [email protected]
,那么您希望他们的 principal 只是 james.wong
。
这可以使用 Elasticsearch 领域中的 claim_patterns
设置来实现,如下面的领域配置所示:
xpack.security.authc.realms.oidc.oidc1: order: 2 rp.client_id: "the_client_id" rp.response_type: code rp.redirect_uri: "https://kibana.example.org:5601/api/security/oidc/callback" op.authorization_endpoint: "https://op.example.org/oauth2/v1/authorize" op.token_endpoint: "https://op.example.org/oauth2/v1/token" op.userinfo_endpoint: "https://op.example.org/oauth2/v1/userinfo" op.endsession_endpoint: "https://op.example.org/oauth2/v1/logout" op.issuer: "https://op.example.org" op.jwkset_path: oidc/jwkset.json claims.principal: email_verified claim_patterns.principal: "^([^@]+)@staff\\.example\\.com$"
在这种情况下,用户的 principal
从 email_verified
声明映射而来,但在将该值分配给用户之前,会对该值应用正则表达式。如果正则表达式匹配,则将第一个组的结果用作有效值。如果正则表达式不匹配,则声明映射失败。
在此示例中,电子邮件地址必须属于 staff.example.com
域,然后将本地部分(@
之前的任何内容)用作 principal。任何尝试使用其他电子邮件域登录的用户都会失败,因为正则表达式不会与其电子邮件地址匹配,因此他们的 principal 用户属性(这是强制性的)将不会被填充。
这些正则表达式中的小错误可能会产生重大的安全后果。例如,如果我们意外地从上面的示例中省略了尾随的 $
,那么我们将匹配域以 staff.example.com
开头的任何电子邮件地址,这将接受诸如 [email protected]
之类的电子邮件地址。请务必确保您的正则表达式尽可能精确,以免无意中打开用户模拟攻击的途径。
第三方发起的单点登录
编辑Elasticsearch 中的 Open ID Connect 领域支持 相关规范中描述的第三方发起的登录。
这允许 OP 本身或除 RP 之外的另一个第三方启动身份验证过程,同时请求使用 OP 进行身份验证。请注意,Elastic Stack RP 应该已经为此 OP 配置,以便此过程成功。
OpenID Connect 注销
编辑Elasticsearch 中的 OpenID Connect 领域支持 规范相关部分中描述的 RP 发起的注销功能。
在此过程中,OpenID Connect RP(在本例中为 Elastic Stack)将在成功完成本地注销后,将用户的浏览器重定向到 OP 的预定义 URL。然后,OP 也可以根据配置注销用户,最后应该将用户重定向回 RP。领域配置中的 op.endsession_endpoint
确定浏览器将被重定向到的 OP 中的 URL。rp.post_logout_redirect_uri
设置确定 OP 注销用户后将用户重定向回的 URL。
配置 rp.post_logout_redirect_uri
时,应注意不要将其指向会触发用户重新身份验证的 URL。 例如,当使用 OpenID Connect 来支持 Kibana 的单点登录时,可以将其设置为 ${kibana-url}/security/logged_out
,这将向用户显示友好的消息,或者设置为 ${kibana-url}/login?msg=LOGGED_OUT
,这将使用户进入 Kibana 中的登录选择器。
OpenID Connect Realm SSL 配置
编辑OpenID Connect 依赖于 TLS 来提供诸如传输中加密和端点身份验证之类的安全属性。RP 需要与 OP 建立后通道通信,以便在授权码授予流程中交换代码以获取 ID 令牌,并从 UserInfo 端点获取其他用户信息。此外,如果将 op.jwks_path
配置为 URL,Elasticsearch 将需要从托管在那里的文件中获取 OP 的签名密钥。因此,Elasticsearch 可以验证并信任 OP 用于 TLS 的服务器证书非常重要。由于系统信任库用于传出 https 连接的客户端上下文,如果您的 OP 使用来自受信任 CA 的证书,则无需其他配置。
但是,如果 OP 证书的颁发者不受运行 Elasticsearch 的 JVM 的信任(例如,它使用组织 CA),则必须配置 Elasticsearch 以信任该 CA。假设您在 Elasticsearch 配置目录的 `/oidc/company-ca.pem` 文件中存储了签署 OP 用于 TLS 的证书的 CA 证书,则需要在 realm 配置中设置以下属性
xpack.security.authc.realms.oidc.oidc1: order: 1 ... ssl.certificate_authorities: ["/oidc/company-ca.pem"]
配置角色映射
编辑当用户使用 OpenID Connect 进行身份验证时,他们会被识别为 Elastic Stack 用户,但这不会自动授予他们执行任何操作或访问任何数据的权限。
除非为您的 OpenID Connect 用户分配角色,否则他们将无法执行任何操作。这可以通过 添加角色映射 API 或使用授权 realm 来完成。
您不能使用 角色映射文件向通过 OpenID Connect 验证身份的用户授予角色。
这是一个简单的角色映射示例,该映射将 example_role
角色授予针对 oidc1
OpenID Connect realm 进行身份验证的任何用户
resp = client.security.put_role_mapping( name="oidc-example", roles=[ "example_role" ], enabled=True, rules={ "field": { "realm.name": "oidc1" } }, ) print(resp)
const response = await client.security.putRoleMapping({ name: "oidc-example", roles: ["example_role"], enabled: true, rules: { field: { "realm.name": "oidc1", }, }, }); console.log(response);
PUT /_security/role_mapping/oidc-example { "roles": [ "example_role" ], "enabled": true, "rules": { "field": { "realm.name": "oidc1" } } }
通过 realm 配置映射的用户属性用于处理角色映射规则,这些规则确定授予用户的角色。
提供给角色映射的用户字段派生自 OpenID Connect 声明,如下所示
-
username
:principal
用户属性 -
dn
:dn
用户属性 -
groups
:groups
用户属性 -
metadata
:请参阅用户元数据
有关更多信息,请参阅将用户和组映射到角色和角色映射。
如果您的 OP 能够通过使用 OpenID 声明向 RP 提供组或角色,那么您应该将此声明映射到 Elasticsearch realm 中的 claims.groups
设置(请参阅 将声明映射到用户属性),然后在角色映射中按以下示例使用它。
此映射将 Elasticsearch 的 finance_data
角色授予通过 oidc1
realm 进行身份验证且具有 finance-team
组成员身份的任何用户。
resp = client.security.put_role_mapping( name="oidc-finance", roles=[ "finance_data" ], enabled=True, rules={ "all": [ { "field": { "realm.name": "oidc1" } }, { "field": { "groups": "finance-team" } } ] }, ) print(resp)
const response = await client.security.putRoleMapping({ name: "oidc-finance", roles: ["finance_data"], enabled: true, rules: { all: [ { field: { "realm.name": "oidc1", }, }, { field: { groups: "finance-team", }, }, ], }, }); console.log(response);
PUT /_security/role_mapping/oidc-finance { "roles": [ "finance_data" ], "enabled": true, "rules": { "all": [ { "field": { "realm.name": "oidc1" } }, { "field": { "groups": "finance-team" } } ] } }
如果您的用户也存在于 Elasticsearch 可以直接访问的存储库中(例如 LDAP 目录),则可以使用授权 realm 而不是角色映射。
在这种情况下,请执行以下步骤
- 在您的 OpenID Connect realm 中,通过配置
claims.principal
设置来分配一个声明作为查找用户 ID。 - 创建一个新的 realm,该 realm 可以从您的本地存储库(例如
ldap
realm)查找用户。 - 在您的 OpenID Connect realm 中,将
authorization_realms
设置为您在步骤 2 中创建的 realm 的名称。
用户元数据
编辑默认情况下,通过 OpenID Connect 进行身份验证的用户将有一些额外的元数据字段。这些字段将包括身份验证响应中提供的每个 OpenID 声明(无论它是否映射到 Elasticsearch 用户属性)。例如,在元数据字段 oidc(claim_name)
中,“claim_name” 是该声明在 ID 令牌或用户信息响应中包含的名称。请注意,这些将包括所有与身份验证事件相关的 ID 令牌声明,而不是用户本身。
可以通过在 oidc realm 中添加 populate_user_metadata: false
作为设置来禁用此行为。
配置 Kibana
编辑Kibana 中的 OpenID Connect 身份验证除了标准的 Kibana 安全配置之外,还需要少量其他设置。Kibana 安全文档提供了您可以应用的可用配置选项的详细信息。
特别是,由于您的 Elasticsearch 节点已配置为在 HTTP 接口上使用 TLS,因此您必须配置 Kibana 以使用 https
URL 连接到 Elasticsearch,并且您可能需要配置 elasticsearch.ssl.certificateAuthorities
以信任 Elasticsearch 已配置为使用的证书。
Kibana 中的 OpenID Connect 身份验证受 kibana.yml
中的以下超时设置约束
您可能需要根据您的安全要求调整这些超时。
以下显示了支持 OpenID Connect 所需的三个附加设置
xpack.security.authc.providers: oidc.oidc1: order: 0 realm: "oidc1"
上面示例中使用的配置值是
-
xpack.security.authc.providers
- 添加
oidc
提供程序,以指示 Kibana 使用 OpenID Connect 单点登录作为身份验证方法。如果用户尚未进行身份验证,这将指示 Kibana 在用户尝试访问 Kibana 中的 URL 时尝试启动 SSO 流程。如果您还希望允许用户使用用户名和密码登录,则还必须启用basic
身份验证提供程序。例如
xpack.security.authc.providers: oidc.oidc1: order: 0 realm: "oidc1" basic.basic1: order: 1
这将允许尚未通过 OpenID Connect 进行身份验证的用户使用 Kibana 登录表单登录。
-
xpack.security.authc.providers.oidc.<provider-name>.realm
- Elasticsearch 中应为此 Kibana 实例处理身份验证的 OpenID Connect realm 的名称。
不使用 Kibana 的 OpenID Connect
编辑OpenID Connect realm 旨在允许用户对 Kibana 进行身份验证,因此,以上指南的大部分内容都假设使用了 Kibana。本节介绍自定义 Web 应用程序如何使用相关的 OpenID Connect REST API,以便使用 OpenID Connect 对用户进行 Elasticsearch 身份验证。
诸如 OpenID Connect 和 SAML 之类的单点登录 realm 利用 Elasticsearch 中的令牌服务,并且原则上将 SAML 或 OpenID Connect 身份验证响应交换为 Elasticsearch 访问令牌和刷新令牌。访问令牌用作后续对 Elasticsearch 的调用的凭据。刷新令牌允许用户在当前令牌过期后获取新的 Elasticsearch 访问令牌。
可以将 Elasticsearch 令牌服务视为最小的 oAuth2 授权服务器,并且上述访问令牌和刷新令牌是仅与此授权服务器相关的令牌。它们仅由 Elasticsearch 生成和使用,并且与 OpenID Connect 提供程序颁发的令牌(访问令牌和 ID 令牌)无关。
向 OpenID Connect 提供程序注册 RP
编辑需要将依赖方(Elasticsearch 和自定义 Web 应用程序)作为客户端注册到 OpenID Connect 提供程序。请注意,注册 Redirect URI
时,它必须是自定义 Web 应用程序中的 URL。
OpenID Connect Realm
编辑需要在 Elasticsearch 中创建并配置相应的 OpenID Connect realm。请参阅配置 Elasticsearch 以进行 OpenID Connect 身份验证
用于访问 API 的服务帐户用户
编辑realm 的设计假设需要有一个特权实体充当身份验证代理。在这种情况下,自定义 Web 应用程序是身份验证代理,负责处理最终用户的身份验证(更正确地说,是将身份验证“委托”给 OpenID Connect 提供程序)。OpenID Connect API 需要身份验证和经过身份验证的用户的必要授权级别。因此,需要创建一个服务帐户用户,并为其分配一个具有 manage_oidc
集群权限的角色。在身份验证发生后,将需要使用 manage_token
集群权限,以便用户可以保持访问权限或随后注销。
resp = client.security.put_role( name="facilitator-role", cluster=[ "manage_oidc", "manage_token" ], ) print(resp)
const response = await client.security.putRole({ name: "facilitator-role", cluster: ["manage_oidc", "manage_token"], }); console.log(response);
POST /_security/role/facilitator-role { "cluster" : ["manage_oidc", "manage_token"] }
resp = client.security.put_user( username="facilitator", password="<somePasswordHere>", roles=[ "facilitator-role" ], ) print(resp)
const response = await client.security.putUser({ username: "facilitator", password: "<somePasswordHere>", roles: ["facilitator-role"], }); console.log(response);
POST /_security/user/facilitator { "password" : "<somePasswordHere>", "roles" : [ "facilitator-role"] }
处理身份验证流程
编辑在较高级别上,自定义 Web 应用程序需要执行以下步骤,才能使用 OpenID Connect 对用户进行身份验证
-
使用
facilitator
用户进行身份验证,向_security/oidc/prepare
发出 HTTP POST 请求,并在请求正文中使用 Elasticsearch 配置中 OpenID Connect realm 的名称。有关更多详细信息,请参阅OpenID Connect 准备身份验证。resp = client.security.oidc_prepare_authentication( body={ "realm": "oidc1" }, ) print(resp)
const response = await client.security.oidcPrepareAuthentication({ body: { realm: "oidc1", }, }); console.log(response);
POST /_security/oidc/prepare { "realm" : "oidc1" }
- 处理对
/_security/oidc/prepare
的响应。来自 Elasticsearch 的响应将包含 3 个参数:redirect
、state
、nonce
。自定义 Web 应用程序需要在用户的会话中存储state
和nonce
的值(客户端在 cookie 中或服务器端,如果会话信息以此方式持久保存),并将用户的浏览器重定向到redirect
值中包含的 URL。 -
处理来自 OP 的后续响应。用户成功通过 OpenID Connect 提供程序身份验证后,他们将被重定向回回调/重定向 URI。接收到此 HTTP GET 请求后,自定义 Web 应用程序需要向
_security/oidc/authenticate
发出 HTTP POST 请求,再次以facilitator
用户身份进行身份验证 - 传递用户浏览器被重定向到的 URL 作为参数,以及之前在用户会话中保存的nonce
和state
的值。如果配置了多个 OpenID Connect 领域,自定义 Web 应用程序可以指定用于处理此操作的领域名称,但此参数是可选的。有关更多详细信息,请参阅 OpenID Connect 身份验证。resp = client.security.oidc_authenticate( body={ "redirect_uri": "https://oidc-kibana.elastic.co:5603/api/security/oidc/callback?code=jtI3Ntt8v3_XvcLzCFGq&state=4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I", "state": "4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I", "nonce": "WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM", "realm": "oidc1" }, ) print(resp)
const response = await client.security.oidcAuthenticate({ body: { redirect_uri: "https://oidc-kibana.elastic.co:5603/api/security/oidc/callback?code=jtI3Ntt8v3_XvcLzCFGq&state=4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I", state: "4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I", nonce: "WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM", realm: "oidc1", }, }); console.log(response);
POST /_security/oidc/authenticate { "redirect_uri" : "https://oidc-kibana.elastic.co:5603/api/security/oidc/callback?code=jtI3Ntt8v3_XvcLzCFGq&state=4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I", "state" : "4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I", "nonce" : "WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM", "realm" : "oidc1" }
Elasticsearch 将验证此请求,如果一切正确,将响应一个访问令牌,该令牌可以用作后续请求的
Bearer
令牌,以及一个刷新令牌,该刷新令牌稍后可用于刷新给定的访问令牌,如 获取令牌 中所述。 -
在必要时,自定义 Web 应用程序可以通过使用 OIDC 注销 API 并将访问令牌和刷新令牌作为参数传递来注销用户。例如
resp = client.security.oidc_logout( body={ "token": "dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvbmx5IHRlc3QgZGF0YS4gZG8gbm90IHRyeSB0byByZWFkIHRva2VuIQ==", "refresh_token": "vLBPvmAB6KvwvJZr27cS" }, ) print(resp)
const response = await client.security.oidcLogout({ body: { token: "dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvbmx5IHRlc3QgZGF0YS4gZG8gbm90IHRyeSB0byByZWFkIHRva2VuIQ==", refresh_token: "vLBPvmAB6KvwvJZr27cS", }, }); console.log(response);
POST /_security/oidc/logout { "token" : "dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvbmx5IHRlc3QgZGF0YS4gZG8gbm90IHRyeSB0byByZWFkIHRva2VuIQ==", "refresh_token": "vLBPvmAB6KvwvJZr27cS" }
如果领域配置正确,这可能会导致响应中包含一个
redirect
参数,指示用户需要重定向到 OP 的位置以完成注销过程。