配置 Neo4j 单点登录 (SSO)

Neo4j 通过实现 OpenID Connect (OIDC) 标准的身份提供者支持 SSO 身份验证和授权。此页面提供了有关如何为多个身份提供者配置单点登录 (SSO) 的详细示例。它还介绍了在配置 SSO 时遇到的常见问题的常见问题解答和解决方案。

以下配置适用于在 https://#:7474/browser/ 上运行的 Neo4j 浏览器(在 localhost 上启动数据库时的默认 URL)。

因此,在身份提供者中复制它们时,您必须修改重定向 URI 以包含提供 Neo4j 浏览器应用程序的 URI。例如:

https://#:7474/browser/?idp_id={provider}&auth_flow_step=redirect_uri

SSO 以以下方式工作:

  1. 服务器(Neo4j DBMS)联系身份提供者(Okta、Entra ID、Google 等)并从提供者获取 JSON Web 密钥 (JWK)。

  2. 客户端(例如 Bloom、Neo4j 浏览器等)向用户索要凭据并联系身份提供者。

  3. 身份提供者会返回一个 JSON Web 令牌 (JWT),这是一个包含与用户相关字段(声明)的 JSON 文件(电子邮件、受众、组等)。

  4. 客户端向服务器提供 JWT,服务器使用 JWK 验证其签名。

  5. 在 5.24 中引入 可选地,您可以通过将 neo4j.conf 文件中的 dbms.security.require_local_user 设置为 true 以及使用 Cypher 设置要控制其身份验证和授权的用户,来控制用户级别的身份验证和授权。此设置要求与相关身份验证提供者关联的用户必须存在于数据库中,才能使用该身份验证提供者进行身份验证和授权。有关如何在该模式下修改或创建用户的详细信息,请参阅 管理用户
    此模式允许您使用 Cypher 执行以下操作:

    1. 暂停 SSO 用户。

    2. 为 SSO 用户设置主数据库。

    3. 为 SSO 用户设置一个用户友好的名称(而不是依赖于外部标识符)。

    4. 为 SSO 用户设置密码。

    5. 为 SSO 用户设置密码更改要求。

有关更多信息和示例,请参阅 使用身份验证提供者在用户级别配置 SSO

即使使用不同的声明作为 username,JWT 也必须始终包含 sub 的值。它是唯一保证唯一且稳定的声明。其他声明,例如 emailpreferred_username 安全性较低,可能会随时间发生变化。它们不应用于身份验证。Neo4j 可能会根据此用户名值在混合授权配置中向用户分配权限。因此,不建议将用户名声明从 sub 更改。

Okta

访问令牌

此示例演示如何使用访问令牌配置 Okta 以进行身份验证和授权。

  1. 使用相应的重定向 URI 配置客户端。您可以跳过此步骤中的组分配。

    oidc okta client creation
    图 1. Okta OIDC 客户端创建
    oidc okta client config a
    图 2. Okta OIDC 客户端配置
  2. 记下客户端 ID 和 Okta 域。您稍后在配置 Okta 参数和 neo4j.conf 文件中的知名 OpenID Connect 端点时需要它们。

    oidc okta client config b
    图 3. Okta OIDC 客户端配置
  3. 在 Okta 中创建组,将用户分配给组(用户可以在用户创建时或编辑组时添加到组),并将它们在 neo4j.conf 中映射到本机组。

    oidc okta server groups
    图 4. Okta OIDC 服务器组
  4. 配置默认授权服务器(显示 api://default 作为受众的服务器)以在访问令牌中返回 groups 声明。

    oidc okta authz server
    图 5. Okta OIDC 授权服务器
    oidc okta server claims
    图 6. Okta OIDC 服务器声明
  5. 通过在 neo4j.conf 文件中配置以下设置,配置 Neo4j 使用 Okta 身份验证。

    dbms.security.authentication_providers=oidc-okta
    dbms.security.authorization_providers=oidc-okta
    dbms.security.oidc.okta.display_name=Okta
    dbms.security.oidc.okta.auth_flow=pkce
    dbms.security.oidc.okta.well_known_discovery_uri=https://dev-21056049.okta.com/oauth2/default/.well-known/openid-configuration
    dbms.security.oidc.okta.audience=api://default
    dbms.security.oidc.okta.claims.username=sub
    dbms.security.oidc.okta.claims.groups=groups
    dbms.security.oidc.okta.params=client_id=0oa3oq6uw3uSOBf8y5d7;response_type=code;scope=openid profile email
    dbms.security.oidc.okta.authorization.group_to_role_mapping= "engineers" = admin; \
                                                                 "collaborators" = reader

    省略了 token_type_principaltoken_type_authentication,这意味着使用访问令牌。

  6. 使用 engineer 角色用户的电子邮件(在数据库中导致 admin 角色)使用 Okta SSO 凭据登录。

    oidc okta successful login
    图 7. Okta OIDC 成功登录

ID 令牌

此示例演示如何使用 ID 令牌配置 Okta 以进行身份验证和授权。

  1. 按照 访问令牌 说明中的前两个步骤操作。

  2. 创建如指示的那样创建声明。

    okta claims
    图 8. Okta 声明创建面板

    在访问令牌的情况下,默认的 sub 会自动提供。但是,对于 ID 令牌,您为声明提供的名称也需要在配置 dbms.security.oidc.okta.claims.username=userid 中指示。

  3. 按照指示配置默认授权服务器(显示 api://default 作为受众的服务器)。

    dbms.security.authentication_providers=oidc-okta, native
    dbms.security.authorization_providers=oidc-okta
    dbms.security.oidc.okta.display_name=Okta
    dbms.security.oidc.okta.auth_flow=pkce
    dbms.security.oidc.okta.well_known_discovery_uri=https://trial-2696363.okta.com/oauth2/default/.well-known/openid-configuration
    dbms.security.oidc.okta.audience=0oa42hwrygsUCFlLO697
    dbms.security.oidc.okta.claims.username=userid
    dbms.security.oidc.okta.claims.groups=groups
    dbms.security.oidc.okta.params=client_id=0oa42hwrygsUCFlLO697;response_type=code;scope=openid profile email
    dbms.security.oidc.okta.authorization.group_to_role_mapping="admin_group" = admin;
    dbms.security.oidc.okta.config=token_type_principal=id_token;token_type_authentication=id_token
  4. 您现在应该在 Okta 的登录选项卡下找到受众。

    okta sign on tab
    图 9. Okta 的登录选项卡
  5. 在 5.24 中引入(可选)如果您想在用户级别控制身份验证和授权,请将 neo4j.conf 文件中的 dbms.security.require_local_user 配置为 true。此设置要求与相关身份验证提供者关联的用户必须存在于数据库中,才能使用该身份验证提供者进行身份验证和授权。有关如何在该模式下创建用户的详细信息,请参阅 创建用户

    例如,要创建可以使用 nativeokta 进行身份验证并使用 Okta 进行授权(如步骤 3 中配置)的用户 jake,您可以使用以下 Cypher 查询。

    CREATE USER jake
    SET HOME DATABASE 'jakesHomeDb'
    SET AUTH 'oidc-okta' {SET ID 'jakesUniqueOktaUserId'} // `jakesUniqueOktaUserId` must match the value of the claim that you configured via dbms.security.oidc.okta.claims.username
    SET AUTH 'native' {SET PASSWORD 'changeme' SET PASSWORD CHANGE REQUIRED}

    有关更多示例,请参阅 使用身份验证提供者在用户级别配置 SSO

Microsoft Entra ID(以前称为 Azure Active Directory)

访问令牌

此示例演示如何使用访问令牌配置 Entra ID 以进行身份验证和授权。

  1. 在 Azure 中成功创建 SSO 应用程序后,打开**令牌配置**选项卡以配置令牌。

    1. 单击**添加组声明**。

    2. 选择要包含在访问令牌中的**安全组**。

    3. 保存您的更改。

  2. 打开**公开 API**选项卡,然后选择**添加范围**。

    1. 如果您第一次单击**添加范围**按钮,您将看到一个新的窗格,说明您需要在继续之前添加应用程序 ID URI

      您可以在应用程序的**概述**页面上找到它。

      azure id
      图 10. GUID 用于在 Azure 中标识特定资源或实例。您可以在应用程序注册页面上找到它。
    2. 设置应用程序 ID URI 后,单击**保存并继续**。

  3. 在**添加范围**窗格中填写所有必填字段。

    1. 输入新的**范围名称**、**管理同意显示名称**和**管理同意说明**。

    2. 确保已选择**启用**范围状态。

    3. 再次选择**添加范围**按钮以创建新的范围。您可以添加 API 支持的所有范围。

      创建范围后,记下它们以备后用。

  4. 通过在 neo4j.conf 文件中配置以下设置,配置 Neo4j 使用 Entra ID 进行身份验证。

    # Configure the access_token
    dbms.security.oidc.azure.config=principal=unique_name;code_challenge_method=S256;token_type_principal=access_token;token_type_authentication=access_token
    # Configure the OIDC token endpoint with the Directory (tenant) ID
    dbms.security.oidc.azure.token_endpoint=https://login.microsoftonline.com/54e85725-ed2a-49a4-a19e-11c8d29f9a0f/oauth2/v2.0/token
    # Configure the iss claim in the id token with the Directory (tenant) ID
    # Make sure you add the trailing slash (`/`) at the end of the URL, or this operation might fail.
    dbms.security.oidc.azure.issuer=https://sts.windows.net/54e85725-ed2a-49a4-a19e-11c8d29f9a0f/
    # Provide the Entra ID parameters, such as client_id, response_type, scope, etc.
    dbms.security.oidc.azure.params=client_id=4376dc8b-b5af-424f-9ada-c1c1b2d416b9;response_type=code;scope=openid profile email api://4376dc8b-b5af-424f-9ada-c1c1b2d416b9/access-token

    如前所述,此处的 GUID 也是目录(租户)ID。确保在末尾添加尾随斜杠 (/),否则此操作可能会失败。

    访问令牌的受众参数通常在前面设置有 api://

ID 令牌

此示例演示如何使用 ID 令牌配置 Entra ID 以进行身份验证和授权。

注册应用程序

  1. 登录到 Azure 门户

  2. 导航到**Microsoft Entra ID > 概述**。

  3. 从**添加**下拉菜单中选择**应用程序注册**,并填写以下信息以创建您的 SSO 应用程序。

    oidc azure client creation
    图 11. Entra OIDC 客户端创建

    重定向 URI https://#:7474/browser/?idp_id=azure&auth_flow_step=redirect_uri 是在成功身份验证后接受返回的令牌响应的 URI。

  4. 单击**注册**。

配置 Neo4j

  1. 成功创建应用程序后,在应用程序的**概述**页面上,找到应用程序(客户端)ID 值。使用它在 neo4j.conf 文件中配置以下属性。

    dbms.security.oidc.azure.audience=c2830ff5-86d9-4e38-8a2b-9efad6f3d06d
    dbms.security.oidc.azure.params=client_id=c2830ff5-86d9-4e38-8a2b-9efad6f3d06d;response_type=code;scope=openid profile email
  2. 导航到**端点**,以找到 OpenID Connect 元数据文档。使用它在 neo4j.conf 文件中配置 well_known_discovery_uri

    oidc azure client config
    图 12. Entra OIDC 客户端配置
    dbms.security.oidc.azure.well_known_discovery_uri=https://login.microsoftonline.com/ce976899-299d-4a01-91e5-a5fee8f98626/v2.0/.well-known/openid-configuration
  3. 通过在 neo4j.conf 文件中配置以下设置,配置 Neo4j 使用 Entra ID 进行身份验证。

    dbms.security.authentication_providers=oidc-azure
    dbms.security.authorization_providers=oidc-azure
    dbms.security.oidc.azure.display_name=Azure
    dbms.security.oidc.azure.auth_flow=pkce
    dbms.security.oidc.azure.config=token_type_principal=id_token;token_type_authentication=id_token
  4. 配置应使用哪个 JWT 声明作为用户名。可能的值是 subemailpreferred_username

    sub 是唯一保证唯一且稳定的声明。有关详细信息,请参阅 Microsoft 文档 以及 OpenId 规范

    dbms.security.oidc.azure.claims.username=sub

将 Entra 组映射到 Neo4j 角色

决定您是想直接使用 Entra 组还是 Entra 应用程序角色。

如果您已经将用户分配到这些组,并且想要在 Neo4j 设置中执行组到角色的映射,那么直接使用 Entra 组可能很方便。

Entra 应用程序角色允许在 Neo4j 角色和组之间进行一层分离。使用应用程序角色时,只有与 Neo4j 相关的角色才会发送到 JWT 令牌中。这可以防止在应用程序之间泄露权限。JWT 令牌还对每个用户每个令牌的 200 个角色有限制,这可以通过只发送相关的应用程序角色来避免。

有关 Entra ID 应用程序角色的详细信息,请参阅 Microsoft 文档

直接使用 Entra 组

  1. 配置服务器以在 JWT 身份令牌中返回组对象 ID。为此,在注册应用程序的清单中将 groupMembershipClaims 设置为 SecurityGroup

    oidc azure server claims
    图 13. Entra OIDC 服务器声明
  2. 在 Entra AD 控制台中创建组并将用户分配给它们。记下“对象 ID”列。在下一步中,您必须将它们映射到 Neo4j 设置中的用户角色。

    oidc azure server groups
    图 14. Entra OIDC 服务器组
  3. 配置从 Entra 组对象 ID 到 Neo4j 角色的映射。有关详细信息,请参阅 将身份提供者组映射到 Neo4j 角色

    dbms.security.oidc.azure.authorization.group_to_role_mapping= "e8b6ddfa-688d-4ace-987d-6cc5516af188" = admin; \
                                                                  "9e2a31e1-bdd1-47fe-844d-767502bd138d" = reader
  4. 配置 Neo4j 以使用 JWT 令牌中的 groups 字段。

    dbms.security.oidc.azure.claims.groups=groups

使用 Entra ID 应用程序角色

  1. 在应用程序的主页上,导航到“应用程序角色”并将 Neo4j 角色添加到 Microsoft Entra ID。

    oidc azure app roles
    图 15. Entra OIDC 应用程序角色配置
  2. 应用程序角色配置中的“值”列必须与 Neo4j 角色相对应,或者在 neo4j.conf 文件中进行映射。有关详细信息,请参阅 将身份提供者组映射到 Neo4j 角色

    dbms.security.oidc.azure.authorization.group_to_role_mapping= "managers" = admin; \
                                                                  "engineers" = reader
  3. 配置 Neo4j 以使用 JWT 令牌中的 roles 字段。

    dbms.security.oidc.azure.claims.groups=roles
  4. 在 5.24 中引入(可选)如果您想在用户级别控制身份验证和授权,请将 neo4j.conf 文件中的 dbms.security.require_local_user 配置为 true。此设置要求与相关身份验证提供者关联的用户必须存在于数据库中,才能使用该身份验证提供者进行身份验证和授权。有关如何在该模式下创建用户的详细信息,请参阅 创建用户

    例如,要创建一个可以使用 Azure 进行身份验证和授权的用户 jake,可以使用以下 Cypher 查询

    CREATE USER jake
    SET HOME DATABASE 'jakesHomeDb'
    SET AUTH 'oidc-azure' {SET ID 'jakesUniqueAzureUserId'} // `jakesUniqueAzureUserId` must match the value of the claim that you configured via dbms.security.oidc.azure.claims.username

    有关更多示例,请参阅 使用身份验证提供者在用户级别配置 SSO

谷歌

ID 令牌

此示例演示如何使用 Google OpenID Connect 进行身份验证(使用 ID 令牌)以及本机授权。

  1. 配置客户端和重定向 URI

    oidc google client creation
    图 16. 创建 Google OIDC 客户端
    oidc google client config
    图 17. Google OIDC 客户端配置

    SSO 授权不适用于 Google,因为 Google 返回的 JWT 不包含有关用户所属组的信息,也无法进行配置。因此,建议通过在 Neo4j 中创建用户的本机版本来使用本机(或其他)授权。

  2. 通过在 neo4j.conf 文件中设置以下配置,配置 Neo4j 以使用 Google 身份验证

    dbms.security.authentication_providers=oidc-google
    dbms.security.authorization_providers=native
    dbms.security.oidc.google.display_name=Google
    dbms.security.oidc.google.auth_flow=pkce
    dbms.security.oidc.google.well_known_discovery_uri=https://#/.well-known/openid-configuration
    dbms.security.oidc.google.audience=345461137297-v9brpjmgbvbm3d5s9fq65tktevosd3rn.apps.googleusercontent.com
    dbms.security.oidc.google.claims.username=email
    dbms.security.oidc.google.params=client_id=345461137297-v9brpjmgbvbm3d5s9fq65tktevosd3rn.apps.googleusercontent.com;response_type=code;scope=openid profile email
    dbms.security.oidc.google.token_params=client_secret=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
    dbms.security.oidc.google.config=token_type_principal=id_token;token_type_authentication=id_token
  3. 使用以下选项之一,在数据库中创建一个用户,该用户可以以本机方式进行身份验证和授权,以便能够授予用户来自本机授权的角色。

    在 5.24 版中引入

    此方法依赖于存在一个可以以本机方式进行身份验证的管理员用户,然后通过 身份验证提供者创建特权较低的用户,这些用户只能使用 oidc-google 进行身份验证,但将收到使用 native 授权授予他们的角色。

    当数据库 首次启动时,默认情况下会创建一个名为 neo4j 的管理员用户。

    1. neo4j.conf 文件中,暂时仅为 admin 用户启用本机身份验证,并启用用户级身份验证和授权控制

      dbms.security.authentication_providers=oidc-google, native
      dbms.security.require_local_user=true

      这将切换到用户身份验证提供者模式,在这种模式下,用户只有在数据库中具有相应的身份验证提供者时才能进行身份验证和授权。

    2. 创建一个只能使用 oidc-google 进行身份验证和授权的用户

      CREATE USER jake
      SET HOME DATABASE 'jakesHomeDb'
      SET AUTH 'oidc-google' {SET ID 'jakesUniqueGoogleUserId'} (1)
      1 jakesUniqueGoogleUserId 必须与您通过 dbms.security.oidc.google.claims.username 配置的声明的值匹配。
    3. 授予用户 jake 角色,例如 reader

      GRANT ROLE reader TO jake

      用户隐式地接收 native 授权,因为 native 在授权提供者列表中,并且您已明确授予用户角色。

    4. 以这种方式设置用户后,可以完全禁用数据库的本机身份验证。这将阻止包括管理员在内的所有用户使用用户名和密码登录。

      dbms.security.authentication_providers=oidc-google

    或者,如果您不使用身份验证提供者,则可以暂时启用 native 身份验证以创建一个 SSO 身份验证的管理员用户 alice,然后该用户可以创建其他用户,这些用户只能使用 SSO 进行身份验证。

    1. 暂时启用 native 身份验证

      dbms.security.authentication_providers=oidc-google, native
    2. 创建一个 SSO 身份验证的 admin 用户(在本例中,必须在 Google SSO 提供者中设置 alice@neo4j-test.com 的等效项,并且必须知道其凭据)

      CREATE USER `alice@neo4j-test.com` SET PASSWORD 'secretpassword';
      GRANT ROLE admin to `alice@neo4j-test.com`;
    3. 禁用数据库的本机身份验证以阻止用户使用用户名和密码登录

      dbms.security.authentication_providers=oidc-google
    4. 通过 Google SSO 以 alice@neo4j-test.comadmin 用户)的身份登录。

    5. 创建其他用户,这些用户只能使用 oidc-google 进行身份验证,并将接收使用 native 授权授予他们的角色。

      CREATE USER jakesUniqueGoogleUserId (1)
      SET HOME DATABASE 'jakesHomeDb'
      SET PASSWORD 'secretpassword' SET PASSWORD CHANGE NOT
      REQUIRED
      1 jakesUniqueGoogleUserId 必须与您通过 dbms.security.oidc.google.claims.username 配置的声明的值匹配。
    6. 使用本机授权授予用户角色

      GRANT ROLE reader TO jakesUniqueGoogleUserId

常见问题解答

何时应将 pkce 用作身份验证流程?

假设客户端(Neo4j 浏览器或 Bloom)可以通过公共互联网访问,始终使用 pkce 身份验证流程而不是 implicit,因为后者要求客户端的密钥对公共客户端可用。一般而言,如果两种流程都可用,建议选择 pkce,因为它比 implicit 更安全。

如果 Google 身份验证在配置中列出了客户端密钥,它是否安全?

是的。Google 使用 pkce 流程,但身份提供者有时也会使用客户端密钥来确保请求令牌的客户端是使用该密钥的客户端(pkce 不能保证这一点)。客户端密钥不会增加任何额外的安全性,因为它对公众公开,但 pkce 流程提供了足够的安全性。

无法解析类型为“访问令牌”的 JWT

当在浏览器上收到消息 Failed to get credentials: Could not parse JWT of type "access_token" 时,可能意味着提供者只接受 ID 令牌。

oidc access token error
图 18. 无法解析类型为访问令牌的 JWT

在您的 neo4j.conf 中更改为 ID 令牌

dbms.security.oidc.{{provider}}.config=token_type_principal=id_token;token_type_authentication=id_token

何时应使用身份令牌与访问令牌?

由于访问令牌的生存期较短,因此在可能的情况下使用访问令牌通常更安全。如果身份提供者的授权权限发生更改,Neo4j 将无法进行授权。Neo4j 浏览器将尝试重新连接并比使用 ID 令牌更快地反映更改的权限。

JWT 声明的调试日志记录

在设置 OIDC 集成时,有时需要执行故障排除。在这些情况下,查看身份提供者提供的 JWT 中包含的声明可能会有所帮助。要在安全日志中以 DEBUG 级别启用这些声明的日志记录,请将 dbms.security.logs.oidc.jwt_claims_at_debug_level_enabled 设置为 true,并将安全日志级别设置为 DEBUG

确保将 dbms.security.logs.oidc.jwt_claims_at_debug_level_enabled 恢复为 false,以便在生产环境中避免不必要的日志记录潜在的敏感信息。此外,请记住,身份提供者在 JWT 中提供的声明集可能会随着时间的推移而发生变化。

如何调试配置的其他问题

除了 Neo4j 路径中的 logs/debug.loglogs/security.log 中的日志之外,您还可以使用 Web 浏览器中的 Web 开发控制台在使用 Bloom 或 Neo4j 浏览器执行 SSO 身份验证流程时。这可以揭示潜在的问题,例如使用示例身份提供者和跨域请求策略出现的问题。

oidc cors error
图 19. CORS 错误

解决方案包括将重定向域添加到提供者中允许的域列表(在本例中为 localhost:8080)。

oidc cors error solution
图 20. CORS 错误解决方案,允许提供者上的重定向域