{{< details >}}

  • Tier: 基础版,专业版,旗舰版
  • Offering: 私有化部署

{{< /details >}}

使用 OpenID Connect 作为认证提供者

您可以将极狐 GitLab 用作 OpenID Connect 的客户端应用程序。

要启用 OpenID Connect OmniAuth 提供者,您必须将您的应用程序注册到 OpenID Connect 提供者。OpenID Connect 提供者会为您提供客户端的详细信息和密钥以供使用。

  1. 在您的极狐 GitLab 服务器上,打开配置文件。

    对于 Linux 软件包安装:

    sudo editor /etc/gitlab/gitlab.rb
    

    对于自编译安装:

    cd /home/git/gitlab
    sudo -u git -H editor config/gitlab.yml
    
  2. 配置 common settings 以添加 openid_connect 作为单点登录提供者。这为没有现有极狐 GitLab 账户的用户启用 Just-In-Time 账户配置。

  3. 添加提供者配置。

    对于 Linux 软件包安装:

    gitlab_rails['omniauth_providers'] = [
      {
        name: "openid_connect", # do not change this parameter
        label: "Provider name", # optional label for login button, defaults to "Openid Connect"
        icon: "<custom_provider_icon>",
        args: {
          name: "openid_connect",
          scope: ["openid","profile","email"],
          response_type: "code",
          issuer: "<your_oidc_url>",
          discovery: true,
          client_auth_method: "query",
          uid_field: "<uid_field>",
          send_scope_to_token_endpoint: "false",
          pkce: true,
          client_options: {
            identifier: "<your_oidc_client_id>",
            secret: "<your_oidc_client_secret>",
            redirect_uri: "<your_gitlab_url>/users/auth/openid_connect/callback"
          }
        }
      }
    ]
    

    对于具有多个身份提供者的 Linux 软件包安装:

    { 'name' => 'openid_connect',
      'label' => '...',
      'icon' => '...',
      'args' => {
        'name' => 'openid_connect',
        'strategy_class': 'OmniAuth::Strategies::OpenIDConnect',
        'scope' => ['openid', 'profile', 'email'],
        'discovery' => true,
        'response_type' => 'code',
        'issuer' => 'https://...',
        'client_auth_method' => 'query',
        'uid_field' => '...',
        'client_options' => {
          `identifier`: "<your_oidc_client_id>",
          `secret`: "<your_oidc_client_secret>",
          'redirect_uri' => 'https://.../users/auth/openid_connect/callback'
       }
     }
    },
    { 'name' => 'openid_connect_2fa',
      'label' => '...',
      'icon' => '...',
      'args' => {
        'name' => 'openid_connect_2fa',
        'strategy_class': 'OmniAuth::Strategies::OpenIDConnect',
        'scope' => ['openid', 'profile', 'email'],
        'discovery' => true,
        'response_type' => 'code',
        'issuer' => 'https://...',
        'client_auth_method' => 'query',
        'uid_field' => '...',
        'client_options' => {
         ...
         'redirect_uri' => 'https://.../users/auth/openid_connect_2fa/callback'
       }
     }
    }
    

    对于自编译安装:

      - { name: 'openid_connect', # do not change this parameter
          label: 'Provider name', # optional label for login button, defaults to "Openid Connect"
          icon: '<custom_provider_icon>',
          args: {
            name: 'openid_connect',
            scope: ['openid','profile','email'],
            response_type: 'code',
            issuer: '<your_oidc_url>',
            discovery: true,
            client_auth_method: 'query',
            uid_field: '<uid_field>',
            send_scope_to_token_endpoint: false,
            pkce: true,
            client_options: {
              identifier: '<your_oidc_client_id>',
              secret: '<your_oidc_client_secret>',
              redirect_uri: '<your_gitlab_url>/users/auth/openid_connect/callback'
            }
          }
        }
    
  4. 对于提供者配置,更改提供者的值以匹配您的 OpenID Connect 客户端设置。使用以下作为指南:

    • <your_oidc_label> 是登录页面上显示的标签。
    • <custom_provider_icon>(可选)是登录页面上显示的图标。极狐 GitLab 包含大多数主要社交登录平台的图标,但您可以通过指定此参数来覆盖这些图标。极狐 GitLab 接受本地路径和绝对 URL。
      • 对于本地绝对路径,配置提供者设置为 icon: <path>/<to>/<your-icon>
        • 将图标文件存储在 /opt/gitlab/embedded/service/gitlab-rails/public/<path>/<to>/<your-icon>
        • https://gitlab.example/<path>/<to>/<your-icon> 访问图标文件。
      • 对于本地相对路径,配置提供者设置为 icon: <your-icon>
        • 将图标文件存储在 /opt/gitlab/embedded/service/gitlab-rails/public/images/<your-icon>
        • https://gitlab.example.com/images/<your-icon> 访问图标文件。
    • <your_oidc_url>(可选)是指向 OpenID Connect 提供者的 URL(例如,https://example.com/auth/realms/your-realm)。如果未提供此值,URL 将从 client_options 构造,格式为:<client_options.scheme>://<client_options.host>:<client_options.port>
    • 如果 discovery 设置为 true,则 OpenID Connect 提供者会尝试使用 <your_oidc_url>/.well-known/openid-configuration 自动发现客户端选项。默认值为 false
    • client_auth_method(可选)指定用于与 OpenID Connect 提供者进行身份验证的方法。
      • 支持的值有:
        • basic - HTTP Basic Authentication。
        • jwt_bearer - 基于 JWT 的身份验证(私钥和客户端密钥签名)。
        • mtls - 相互 TLS 或 X.509 证书验证。
        • 任何其他值都会在请求体中发布客户端 ID 和密钥。
      • 如果未指定,此值默认为 basic
    • <uid_field>(可选)是 user_info.raw_attributes 中的字段名称,用于定义 uid 的值(例如,preferred_username)。如果未提供此值,或者配置的字段在 user_info.raw_attributes 详细信息中缺失,uid 使用 sub 字段。
    • send_scope_to_token_endpoint 默认为 true,因此通常在请求 token 端点时包含 scope 参数。但是,如果您的 OpenID Connect 提供者不接受此类请求中的 scope 参数,请将其设置为 false
    • pkce(可选):启用 Proof Key for Code Exchange。在极狐 GitLab 15.9 中可用。
    • client_options 是 OpenID Connect 客户端特定的选项。特别是:
      • identifier 是在 OpenID Connect 服务提供者中配置的客户端标识符。
      • secret 是在 OpenID Connect 服务提供者中配置的客户端密钥。例如,OmniAuth OpenID Connect 需要此项。如果服务提供者不需要密钥,则提供任何值并将其忽略。
      • redirect_uri 是成功登录后重定向用户的极狐 GitLab URL(例如,http://example.com/users/auth/openid_connect/callback)。
      • end_session_endpoint(可选)是结束会话的端点的 URL。可以在自动发现被禁用或不成功时提供此 URL。
      • 以下 client_options 是可选的,除非自动发现被禁用或不成功:
        • authorization_endpoint 是授权最终用户的端点的 URL。
        • token_endpoint 是提供 Access Token 的端点的 URL。
        • userinfo_endpoint 是提供用户信息的端点的 URL。
        • jwks_uri 是 Token 签名者发布其密钥的端点的 URL。
  5. 保存配置文件。
  6. 为了使更改生效,如果您:

在登录页面上,您在常规登录表单下方有一个 OpenID Connect 选项。选择此选项以开始认证过程。如果客户端需要确认,OpenID Connect 提供者会要求您登录并授权极狐 GitLab 应用程序。您将被重定向到极狐 GitLab 并登录。

示例配置

以下配置展示了如何在使用 Linux 软件包安装时与不同提供者一起设置 OpenID。

配置 Microsoft Azure

Microsoft Azure 的 OpenID Connect (OIDC) 协议使用 Microsoft identity platform (v2) endpoints。 要开始,请登录 Azure Portal。对于您的应用,您需要以下信息:

  • 一个租户 ID。您可能已经有一个。
  • 一个客户端 ID 和一个客户端密钥。按照 Microsoft Quickstart Register an Application 文档中的说明为您的应用程序获取租户 ID、客户端 ID 和客户端密钥。

当您注册 Microsoft Azure 应用程序时,必须授予 API 权限以允许极狐 GitLab 检索所需的详细信息。您必须至少提供 openidprofileemail 权限。

{{< alert type=”note” >}}

所有由 Azure 配置的账户必须定义一个电子邮件地址。如果没有定义电子邮件地址,Azure 会分配一个随机生成的地址。如果您已经配置了 domain sign-up restrictions,此随机地址可能会阻止创建账户。

{{< /alert >}}

Linux 软件包安装示例配置块:

gitlab_rails['omniauth_providers'] = [
  {
    name: "openid_connect", # do not change this parameter
    label: "Azure OIDC", # optional label for login button, defaults to "Openid Connect"
    args: {
      name: "openid_connect",
      scope: ["openid", "profile", "email"],
      response_type: "code",
      issuer:  "https://login.microsoftonline.com/<YOUR-TENANT-ID>/v2.0",
      client_auth_method: "query",
      discovery: true,
      uid_field: "preferred_username",
      pkce: true,
      client_options: {
        identifier: "<YOUR APP CLIENT ID>",
        secret: "<YOUR APP CLIENT SECRET>",
        redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
      }
    }
  }
]

Microsoft 已经记录了其平台如何与 OIDC 协议配合使用。

Microsoft Entra 自定义签名密钥

如果您的应用程序有自定义签名密钥,因为您使用了 SAML claims-mapping feature ,您必须以下列方式配置 OpenID 提供者:

  • 通过省略 args.discovery 或将其设置为 false 来禁用 OpenID Connect Discovery。
  • client_options 中,指定以下内容:
    • 带有 appid 查询参数的 jwks_urihttps://login.microsoftonline.com/<YOUR-TENANT-ID>/discovery/v2.0/keys?appid=<YOUR APP CLIENT ID>
    • end_session_endpoint
    • authorization_endpoint
    • userinfo_endpoint

Linux 软件包安装示例配置:

gitlab_rails['omniauth_providers'] = [
 {
    name: "openid_connect", # do not change this parameter
    label: "Azure OIDC", # optional label for login button, defaults to "Openid Connect"
    args: {
      name: "openid_connect",
      scope: ["openid", "profile", "email"],
      response_type: "code",
      issuer:  "https://login.microsoftonline.com/<YOUR-TENANT-ID>/v2.0",
      client_auth_method: "basic",
      discovery: false,
      uid_field: "preferred_username",
      pkce: true,
      client_options: {
        identifier: "<YOUR APP CLIENT ID>",
        secret: "<YOUR APP CLIENT SECRET>",
        redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback",
        end_session_endpoint: "https://login.microsoftonline.com/<YOUR-TENANT-ID>/oauth2/v2.0/logout",
        authorization_endpoint: "https://login.microsoftonline.com/<YOUR-TENANT-ID>/oauth2/v2.0/authorize",
        token_endpoint: "https://login.microsoftonline.com/<YOUR-TENANT-ID>/oauth2/v2.0/token",
        userinfo_endpoint: "https://graph.microsoft.com/oidc/userinfo",
        jwks_uri: "https://login.microsoftonline.com/<YOUR-TENANT-ID>/discovery/v2.0/keys?appid=<YOUR APP CLIENT ID>"
      }
    }
  }
]

如果您看到 KidNotFound 消息的认证失败,很可能是因为缺少或错误的 appid 查询参数。极狐 GitLab 会在 Microsoft 返回的 ID token 无法通过 jwks_uri 端点提供的密钥进行验证时引发此错误。

迁移到通用 OpenID Connect 配置

您可以从 azure_activedirectory_v2azure_oauth2 迁移到通用 OpenID Connect 配置。

首先,设置 uid_fielduid_field 和您可以选择为 uid_fieldsub 声明因提供者而异。未设置 uid_field 的情况下登录会导致在极狐 GitLab 内创建额外的身份,需要手动修改:

Provider uid_field Supporting information
omniauth-azure-oauth2 sub 其他属性 oidtidinfo 对象中提供。
omniauth-azure-activedirectory-v2 oid 迁移时必须将 oid 配置为 uid_field
omniauth_openid_connect sub 指定 uid_field 以使用其他字段。

要迁移到通用 OpenID Connect 配置,您必须更新配置。

对于 Linux 软件包安装,更新配置如下:

{{< tabs >}}

{{< tab title=”Azure OAuth 2.0” >}}

gitlab_rails['omniauth_providers'] = [
  {
    name: "azure_oauth2",
    label: "Azure OIDC", # optional label for login button, defaults to "Openid Connect"
    args: {
      name: "azure_oauth2", # this matches the existing azure_oauth2 provider name, and only the strategy_class immediately below configures OpenID Connect
      strategy_class: "OmniAuth::Strategies::OpenIDConnect",
      scope: ["openid", "profile", "email"],
      response_type: "code",
      issuer:  "https://login.microsoftonline.com/<YOUR-TENANT-ID>/v2.0",
      client_auth_method: "query",
      discovery: true,
      uid_field: "sub",
      send_scope_to_token_endpoint: "false",
      client_options: {
        identifier: "<YOUR APP CLIENT ID>",
        secret: "<YOUR APP CLIENT SECRET>",
        redirect_uri: "https://gitlab.example.com/users/auth/azure_oauth2/callback"
      }
    }
  }
]

{{< /tab >}}

{{< tab title=”Azure Active Directory v2” >}}

gitlab_rails['omniauth_providers'] = [
  {
    name: "azure_activedirectory_v2",
    label: "Azure OIDC", # optional label for login button, defaults to "Openid Connect"
    args: {
      name: "azure_activedirectory_v2",
      strategy_class: "OmniAuth::Strategies::OpenIDConnect",
      scope: ["openid", "profile", "email"],
      response_type: "code",
      issuer:  "https://login.microsoftonline.com/<YOUR-TENANT-ID>/v2.0",
      client_auth_method: "query",
      discovery: true,
      uid_field: "oid",
      send_scope_to_token_endpoint: "false",
      client_options: {
        identifier: "<YOUR APP CLIENT ID>",
        secret: "<YOUR APP CLIENT SECRET>",
        redirect_uri: "https://gitlab.example.com/users/auth/azure_activedirectory_v2/callback"
      }
    }
  }
]

{{< /tab >}}

{{< /tabs >}}

对于 Helm 安装:

在 YAML 文件中添加 provider’s configuration(例如 provider.yaml):

{{< tabs >}}

{{< tab title=”Azure OAuth 2.0” >}}

{
  "name": "azure_oauth2",
  "args": {
    "name": "azure_oauth2",
    "strategy_class": "OmniAuth::Strategies::OpenIDConnect",
    "scope": [
      "openid",
      "profile",
      "email"
    ],
    "response_type": "code",
    "issuer": "https://login.microsoftonline.com/<YOUR-TENANT-ID>/v2.0",
    "client_auth_method": "query",
    "discovery": true,
    "uid_field": "sub",
    "send_scope_to_token_endpoint": false,
    "client_options": {
      "identifier": "<YOUR APP CLIENT ID>",
      "secret": "<YOUR APP CLIENT SECRET>",
      "redirect_uri": "https://gitlab.example.com/users/auth/azure_oauth2/callback"
    }
  }
}

{{< /tab >}}

{{< tab title=”Azure Active Directory v2” >}}

{
  "name": "azure_activedirectory_v2",
  "args": {
    "name": "azure_activedirectory_v2",
    "strategy_class": "OmniAuth::Strategies::OpenIDConnect",
    "scope": [
      "openid",
      "profile",
      "email"
    ],
    "response_type": "code",
    "issuer": "https://login.microsoftonline.com/<YOUR-TENANT-ID>/v2.0",
    "client_auth_method": "query",
    "discovery": true,
    "uid_field": "sub",
    "send_scope_to_token_endpoint": false,
    "client_options": {
      "identifier": "<YOUR APP CLIENT ID>",
      "secret": "<YOUR APP CLIENT SECRET>",
      "redirect_uri": "https://gitlab.example.com/users/auth/activedirectory_v2/callback"
    }
  }
}

{{< /tab >}}

{{< /tabs >}}

在升级到极狐 GitLab 17.0 或以上版本的一部分中,将 azure_oauth2 迁移到 omniauth_openid_connect,为您的组织设置的 sub 声明值可能会有所不同。azure_oauth2 使用 Microsoft V1 端点,而 azure_activedirectory_v2omniauth_openid_connect 都使用 Microsoft V2 端点,并具有相同的 sub 值。

  • 对于在 Entra ID 中具有电子邮件地址的用户,要允许退回到电子邮件地址并更新用户的身份,请配置以下内容:
  • 对于没有电子邮件地址的用户,管理员必须采取以下操作之一:

    • 设置其他认证方法或启用使用极狐 GitLab 用户名和密码登录。然后用户可以登录并使用他们的个人资料手动链接他们的 Azure 身份。
    • 实现 OpenID Connect 作为现有 azure_oauth2 的新提供者,以便用户可以通过 OAuth2 登录,并链接他们的 OpenID Connect 身份(类似于前一种方法)。此方法对于拥有电子邮件地址的用户也有效,只要启用了 auto_link_user
    • 手动更新 extern_uid。要执行此操作,请使用 API 或 Rails 控制台 更新每个用户的 extern_uid。如果实例已经升级到 17.0 或更高版本,并且用户尝试登录,可能需要使用这种方法。

{{< alert type=”note” >}}

如果在配置极狐 GitLab 账户时缺少或为空,azure_oauth2 可能已经使用了 Entra ID 的 upn 声明作为电子邮件地址。

{{< /alert >}}

配置 Microsoft Azure Active Directory B2C

极狐 GitLab 需要特殊配置才能与 Azure Active Directory B2C 一起使用。要开始,请登录 Azure Portal。对于您的应用,您需要从 Azure 获取以下信息:

  • 一个租户 ID。您可能已经有一个。
  • 一个客户端 ID 和一个客户端密钥。
  • 用户流或策略名称。

配置应用程序:

  1. 设置应用程序的 Redirect URI。例如,如果您的极狐 GitLab 域是 gitlab.example.com,请将应用程序的 Redirect URI 设置为 https://gitlab.example.com/users/auth/openid_connect/callback

  2. 启用 ID tokens。

  3. 向应用程序添加以下 API 权限:

    • openid
    • offline_access

配置自定义策略

Azure B2C 提供两种定义用户登录业务逻辑的方法:

  • 用户流
  • 自定义策略

需要自定义策略,因为标准的 Azure B2C 用户流不发送 OpenID email 声明。因此,标准用户流无法与 allow_single_sign_onauto_link_user 参数 一起工作。使用标准 Azure B2C 策略,极狐 GitLab 无法创建新账户或链接到具有电子邮件地址的现有账户。

首先,创建自定义策略。

Microsoft 指南在 custom policy starter pack 中使用 SocialAndLocalAccounts,但 LocalAccounts 对本地 Active Directory 账户进行身份验证。在您上传策略之前,请执行以下操作:

  1. 要导出 email 声明,请修改 SignUpOrSignin.xml。替换以下行:

    <OutputClaim ClaimTypeReferenceId="email" />
    

    用:

    <OutputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="email" />
    
  2. 为使 OIDC 发现与 B2C 一起工作,请使用符合 OIDC 规范的发行者配置策略。在 TrustFrameworkBase.xml 中的 JwtIssuer 下,将 IssuanceClaimPattern 设置为 AuthorityWithTfp

    <ClaimsProvider>
      <DisplayName>Token Issuer</DisplayName>
      <TechnicalProfiles>
        <TechnicalProfile Id="JwtIssuer">
          <DisplayName>JWT Issuer</DisplayName>
          <Protocol Name="None" />
          <OutputTokenFormat>JWT</OutputTokenFormat>
          <Metadata>
            <Item Key="IssuanceClaimPattern">AuthorityWithTfp</Item>
            ...
    
  3. 上传策略。如果您正在更新现有策略,请覆盖现有文件。

  4. 要确定发行者 URL,请使用登录策略。发行者 URL 的格式为:

    https://<YOUR-DOMAIN>/tfp/<YOUR-TENANT-ID>/<YOUR-SIGN-IN-POLICY-NAME>/v2.0/
    

    URL 中的策略名称为小写。例如,B2C_1A_signup_signin 策略显示为 b2c_1a_signup_sigin

    确保包含尾部正斜杠。

  5. 验证 OIDC 发现 URL 和发行者 URL 的操作,并在发行者 URL 后附加 .well-known/openid-configuration

    https://<YOUR-DOMAIN>/tfp/<YOUR-TENANT-ID>/<YOUR-SIGN-IN-POLICY-NAME>/v2.0/.well-known/openid-configuration
    

    例如,如果 domainexample.b2clogin.com 且租户 ID 是 fc40c736-476c-4da1-b489-ee48cee84386,您可以使用 curljq 提取发行者:

    $ curl --silent "https://example.b2clogin.com/tfp/fc40c736-476c-4da1-b489-ee48cee84386/b2c_1a_signup_signin/v2.0/.well-known/openid-configuration" | jq .issuer
    "https://example.b2clogin.com/tfp/fc40c736-476c-4da1-b489-ee48cee84386/b2c_1a_signup_signin/v2.0/"
    
  6. 使用 signup_signin 的自定义策略配置发行者 URL。例如,这是使用 b2c_1a_signup_signin 自定义策略进行 Linux 软件包安装的配置:

    gitlab_rails['omniauth_providers'] = [
    {
      name: "openid_connect", # do not change this parameter
      label: "Azure B2C OIDC", # optional label for login button, defaults to "Openid Connect"
      args: {
        name: "openid_connect",
        scope: ["openid"],
        response_mode: "query",
        response_type: "id_token",
        issuer:  "https://<YOUR-DOMAIN>/tfp/<YOUR-TENANT-ID>/b2c_1a_signup_signin/v2.0/",
        client_auth_method: "query",
        discovery: true,
        send_scope_to_token_endpoint: true,
        pkce: true,
        client_options: {
          identifier: "<YOUR APP CLIENT ID>",
          secret: "<YOUR APP CLIENT SECRET>",
          redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
        }
      }
    }]
    

Azure B2C 故障排除

  • 确保 XML 策略文件中的所有 yourtenant.onmicrosoft.comProxyIdentityExperienceFrameworkAppIdIdentityExperienceFrameworkAppId 的出现与您的 B2C 租户主机名和相应的客户端 ID 匹配。
  • https://jwt.ms 添加为应用程序的重定向 URI,并使用 custom policy tester。确保有效负载包含与用户电子邮件访问匹配的 email
  • 启用自定义策略后,用户可能在尝试登录后看到 Invalid username or password。这可能是 IdentityExperienceFramework 应用程序的配置问题。建议您检查应用程序清单是否包含以下设置:

    • "accessTokenAcceptedVersion": null
    • "signInAudience": "AzureADMyOrg"

此配置与创建 IdentityExperienceFramework 应用程序时使用的 Supported account types 设置相对应。

配置 Keycloak

极狐 GitLab 与使用 HTTPS 的 OpenID 提供者一起工作。虽然您可以设置一个使用 HTTP 的 Keycloak 服务器,但极狐 GitLab 只能与使用 HTTPS 的 Keycloak 服务器通信。

配置 Keycloak 使用公钥加密算法(例如,RSA256 或 RSA512)而不是对称密钥加密算法(例如,HS256 或 HS358)来签署 token。公钥加密算法:

  • 更容易配置。
  • 更安全,因为泄露私钥会产生严重的安全后果。
  1. 打开 Keycloak 管理控制台。
  2. 选择 Realm 设置 > 令牌 > 默认签名算法
  3. 配置签名算法。

Linux 软件包安装示例配置块:

gitlab_rails['omniauth_providers'] = [
  {
    name: "openid_connect", # do not change this parameter
    label: "Keycloak", # optional label for login button, defaults to "Openid Connect"
    args: {
      name: "openid_connect",
      scope: ["openid", "profile", "email"],
      response_type: "code",
      issuer:  "https://keycloak.example.com/realms/myrealm",
      client_auth_method: "query",
      discovery: true,
      uid_field: "preferred_username",
      pkce: true,
      client_options: {
        identifier: "<YOUR CLIENT ID>",
        secret: "<YOUR CLIENT SECRET>",
        redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
      }
    }
  }
]

配置使用对称密钥算法的 Keycloak

{{< alert type=”warning” >}}

以下说明仅为完整性考虑而包含,但只有在绝对必要时才使用对称密钥加密。

{{< /alert >}}

要使用对称密钥加密:

  1. 从 Keycloak 数据库中提取密钥。Keycloak 不在 Web 界面中暴露此值。Web 界面中看到的客户端密钥是 OAuth 2.0 客户端密钥,与用于签署 JSON Web Tokens 的密钥不同。

    例如,如果您将 PostgreSQL 用作 Keycloak 的后端数据库:

    • 登录到数据库控制台。
    • 运行以下 SQL 查询以提取密钥:

      $ psql -U keycloak
      psql (13.3 (Debian 13.3-1.pgdg100+1))
      Type "help" for help.
      
      keycloak=# SELECT c.name, value FROM component_config CC INNER JOIN component C ON(CC.component_id = C.id) WHERE C.realm_id = 'master' and provider_id = 'hmac-generated' AND CC.name = 'secret';
      -[ RECORD 1 ]---------------------------------------------------------------------------------
      name  | hmac-generated
      value | lo6cqjD6Ika8pk7qc3fpFx9ysrhf7E62-sqGc8drp3XW-wr93zru8PFsQokHZZuJJbaUXvmiOftCZM3C4KW3-g
      -[ RECORD 2 ]---------------------------------------------------------------------------------
      name  | fallback-HS384
      value | UfVqmIs--U61UYsRH-NYBH3_mlluLONpg_zN7CXEwkJcO9xdRNlzZfmfDLPtf2xSTMvqu08R2VhLr-8G-oZ47A
      

      在此示例中,有两个私钥:一个用于 HS256 (hmac-generated) 和另一个用于 HS384 (fallback-HS384)。我们使用第一个 value 配置极狐 GitLab。

  2. value 转换为标准 base64。value 使用 RFC 4648 的 Base 64 Encoding with URL and Filename Safe Alphabet。必须将其转换为 RFC 2045 中定义的标准 base64。以下 Ruby 脚本可实现此目的:

    require 'base64'
    
    value = "lo6cqjD6Ika8pk7qc3fpFx9ysrhf7E62-sqGc8drp3XW-wr93zru8PFsQokHZZuJJbaUXvmiOftCZM3C4KW3-g"
    Base64.encode64(Base64.urlsafe_decode64(value))
    

    这将产生以下值:

    lo6cqjD6Ika8pk7qc3fpFx9ysrhf7E62+sqGc8drp3XW+wr93zru8PFsQokH\nZZuJJbaUXvmiOftCZM3C4KW3+g==\n
    
  3. jwt_secret_base64 中指定此 base64 编码的密钥。例如:

    gitlab_rails['omniauth_providers'] = [
      {
        name: "openid_connect", # do not change this parameter
        label: "Keycloak", # optional label for login button, defaults to "Openid Connect"
        args: {
          name: "openid_connect",
          scope: ["openid", "profile", "email"],
          response_type: "code",
          issuer:  "https://keycloak.example.com/auth/realms/myrealm",
          client_auth_method: "query",
          discovery: true,
          uid_field: "preferred_username",
          jwt_secret_base64: "<YOUR BASE64-ENCODED SECRET>",
          pkce: true,
          client_options: {
            identifier: "<YOUR CLIENT ID>",
            secret: "<YOUR CLIENT SECRET>",
            redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
          }
        }
      }
    ]
    

如果您看到 JSON::JWS::VerificationFailed 错误,说明您指定了错误的密钥。

Casdoor

极狐 GitLab 与使用 HTTPS 的 OpenID 提供者一起工作。使用 HTTPS 通过 Casdoor 将极狐 GitLab 连接到 OpenID。

对于您的应用,请在 Casdoor 上完成以下步骤:

  1. 获取客户端 ID 和客户端密钥。
  2. 添加您的极狐 GitLab 重定向 URL。例如,如果您的极狐 GitLab 域是 gitlab.example.com,请确保 Casdoor 应用程序具有以下 Redirect URIhttps://gitlab.example.com/users/auth/openid_connect/callback

Linux 软件包安装的示例配置(文件路径:/etc/gitlab/gitlab.rb):

gitlab_rails['omniauth_providers'] = [
    {
        name: "openid_connect", # do not change this parameter
        label: "Casdoor", # optional label for login button, defaults to "Openid Connect"
        args: {
            name: "openid_connect",
            scope: ["openid", "profile", "email"],
            response_type: "code",
            issuer:  "https://<CASDOOR_HOSTNAME>",
            client_auth_method: "query",
            discovery: true,
            uid_field: "sub",
            client_options: {
                identifier: "<YOUR CLIENT ID>",
                secret: "<YOUR CLIENT SECRET>",
                redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
            }
        }
    }
]

自编译安装的示例配置(文件路径:config/gitlab.yml):

  - { name: 'openid_connect', # do not change this parameter
      label: 'Casdoor', # optional label for login button, defaults to "Openid Connect"
      args: {
        name: 'openid_connect',
        scope: ['openid', 'profile', 'email'],
        response_type: 'code',
        issuer: 'https://<CASDOOR_HOSTNAME>',
        discovery: true,
        client_auth_method: 'query',
        uid_field: 'sub',
        client_options: {
          identifier: '<YOUR CLIENT ID>',
          secret: '<YOUR CLIENT SECRET>',
          redirect_uri: 'https://gitlab.example.com/users/auth/openid_connect/callback'
        }
      }
    }

配置多个 OpenID Connect 提供者

您可以将应用程序配置为使用多个 OpenID Connect (OIDC) 提供者。您可以通过在配置文件中显式设置 strategy_class 来实现这一点。

您应该在以下任一情况下执行此操作:

以下示例配置展示了如何提供不同级别的身份验证,一个选项带有 2FA,一个不带 2FA。

对于 Linux 软件包安装:

gitlab_rails['omniauth_providers'] = [
  {
    name: "openid_connect",
    label: "Provider name", # optional label for login button, defaults to "Openid Connect"
    icon: "<custom_provider_icon>",
    args: {
      name: "openid_connect",
      strategy_class: "OmniAuth::Strategies::OpenIDConnect",
      scope: ["openid","profile","email"],
      response_type: "code",
      issuer: "<your_oidc_url>",
      discovery: true,
      client_auth_method: "query",
      uid_field: "<uid_field>",
      send_scope_to_token_endpoint: "false",
      pkce: true,
      client_options: {
        identifier: "<your_oidc_client_id>",
        secret: "<your_oidc_client_secret>",
        redirect_uri: "<your_gitlab_url>/users/auth/openid_connect/callback"
      }
    }
  },
  {
    name: "openid_connect_2fa",
    label: "Provider name 2FA", # optional label for login button, defaults to "Openid Connect"
    icon: "<custom_provider_icon>",
    args: {
      name: "openid_connect_2fa",
      strategy_class: "OmniAuth::Strategies::OpenIDConnect",
      scope: ["openid","profile","email"],
      response_type: "code",
      issuer: "<your_oidc_url>",
      discovery: true,
      client_auth_method: "query",
      uid_field: "<uid_field>",
      send_scope_to_token_endpoint: "false",
      pkce: true,
      client_options: {
        identifier: "<your_oidc_client_id>",
        secret: "<your_oidc_client_secret>",
        redirect_uri: "<your_gitlab_url>/users/auth/openid_connect_2fa/callback"
      }
    }
  }
]

对于自编译安装的实例:

  - { name: 'openid_connect',
      label: 'Provider name', # optional label for login button, defaults to "Openid Connect"
      icon: '<custom_provider_icon>',
      args: {
        name: 'openid_connect',
        strategy_class: "OmniAuth::Strategies::OpenIDConnect",
        scope: ['openid', 'profile', 'email'],
        response_type: 'code',
        issuer: '<your_oidc_url>',
        discovery: true,
        client_auth_method: 'query',
        uid_field: '<uid_field>',
        send_scope_to_token_endpoint: false,
        pkce: true,
        client_options: {
          identifier: '<your_oidc_client_id>',
          secret: '<your_oidc_client_secret>',
          redirect_uri: '<your_gitlab_url>/users/auth/openid_connect/callback'
        }
      }
    }
  - { name: 'openid_connect_2fa',
      label: 'Provider name 2FA', # optional label for login button, defaults to "Openid Connect"
      icon: '<custom_provider_icon>',
      args: {
        name: 'openid_connect_2fa',
        strategy_class: "OmniAuth::Strategies::OpenIDConnect",
        scope: ['openid', 'profile', 'email'],
        response_type: 'code',
        issuer: '<your_oidc_url>',
        discovery: true,
        client_auth_method: 'query',
        uid_field: '<uid_field>',
        send_scope_to_token_endpoint: false,
        pkce: true,
        client_options: {
          identifier: '<your_oidc_client_id>',
          secret: '<your_oidc_client_secret>',
          redirect_uri: '<your_gitlab_url>/users/auth/openid_connect_2fa/callback'
        }
      }
    }

在这个用例中,您可能希望根据公司目录中现有的已知标识符在不同提供商之间同步 extern_uid

为此,您需要设置 uid_field。以下示例代码展示了如何执行此操作:

def sync_missing_provider(self, user: User, extern_uid: str)
  existing_identities = []
  for identity in user.identities:
      existing_identities.append(identity.get("provider"))

  local_extern_uid = extern_uid.lower()
  for provider in ("openid_connect_2fa", "openid_connect"):
      identity = [
          identity
          for identity in user.identities
          if identity.get("provider") == provider
          and identity.get("extern_uid").lower() != local_extern_uid
      ]
      if provider not in existing_identities or identity:
          if identity and identity[0].get("extern_uid") != "":
              logger.error(f"Found different identity for provider {provider} for user {user.id}")
              continue
          else:
              logger.info(f"Add identity 'provider': {provider}, 'extern_uid': {extern_uid} for user {user.id}")
              user.provider = provider
              user.extern_uid = extern_uid
              user = self.save_user(user)
  return user

基于 OIDC 群组成员身份配置用户

{{< details >}}

  • Tier: 专业版,旗舰版
  • Offering: JihuLab.com,极狐GitLab 私有化部署,极狐GitLab 专属

{{< /details >}}

{{< history >}}

  • 引入于极狐GitLab 15.10。

{{< /history >}}

您可以配置 OIDC 群组成员身份以:

  • 要求用户成为特定群组的成员。
  • 根据群组成员身份分配用户 external、管理员或 审计员 角色。

极狐GitLab 在每次登录时检查这些群组,并根据需要更新用户属性。此功能不允许您自动将用户添加到极狐GitLab 群组

必需的群组

您的身份提供商 (IdP) 必须在 OIDC 响应中向极狐GitLab 传递群组信息。要使用此响应要求用户成为某个群组的成员,请配置极狐GitLab以识别:

  • 在 OIDC 响应中查找群组的位置,使用 groups_attribute 设置。
  • 哪个群组成员身份是登录所需的,使用 required_groups 设置。

如果您没有设置 required_groups 或将设置留空,则任何通过 OIDC 由 IdP 认证的用户都可以使用极狐GitLab。

{{< tabs >}}

{{< tab title=”Linux 软件包(Omnibus)” >}}

  1. 编辑 /etc/gitlab/gitlab.rb

    gitlab_rails['omniauth_providers'] = [
      {
        name: "openid_connect",
        label: "Provider name",
        args: {
          name: "openid_connect",
          scope: ["openid","profile","email"],
          response_type: "code",
          issuer: "<your_oidc_url>",
          discovery: true,
          client_auth_method: "query",
          uid_field: "<uid_field>",
          client_options: {
            identifier: "<your_oidc_client_id>",
            secret: "<your_oidc_client_secret>",
            redirect_uri: "<your_gitlab_url>/users/auth/openid_connect/callback",
            gitlab: {
              groups_attribute: "groups",
              required_groups: ["Developer"]
            }
          }
        }
      }
    ]
    
  2. 保存文件并 重新配置极狐GitLab 使更改生效。

{{< /tab >}}

{{< tab title=”自编译(源代码)” >}}

  1. 编辑 /home/git/gitlab/config/gitlab.yml

    production: &base
      omniauth:
        providers:
         - { name: 'openid_connect',
             label: 'Provider name',
          args: {
            name: 'openid_connect',
            scope: ['openid','profile','email'],
            response_type: 'code',
            issuer: '<your_oidc_url>',
            discovery: true,
            client_auth_method: 'query',
            uid_field: '<uid_field>',
            client_options: {
              identifier: '<your_oidc_client_id>',
              secret: '<your_oidc_client_secret>',
              redirect_uri: '<your_gitlab_url>/users/auth/openid_connect/callback',
              gitlab: {
                groups_attribute: "groups",
                required_groups: ["Developer"]
              }
            }
          }
        }
    
  2. 保存文件并 重新配置极狐GitLab 使更改生效。

{{< /tab >}}

{{< /tabs >}}

外部群组

您的 IdP 必须在 OIDC 响应中向极狐GitLab 传递群组信息。要使用此响应根据群组成员身份识别用户为 external users,请配置极狐GitLab以识别:

  • 在 OIDC 响应中查找群组的位置,使用 groups_attribute 设置。
  • 哪些群组成员身份应识别用户为 external user,使用 external_groups 设置。

{{< tabs >}}

{{< tab title=”Linux 软件包(Omnibus)” >}}

  1. 编辑 /etc/gitlab/gitlab.rb

    gitlab_rails['omniauth_providers'] = [
      {
        name: "openid_connect",
        label: "Provider name",
        args: {
          name: "openid_connect",
          scope: ["openid","profile","email"],
          response_type: "code",
          issuer: "<your_oidc_url>",
          discovery: true,
          client_auth_method: "query",
          uid_field: "<uid_field>",
          client_options: {
            identifier: "<your_oidc_client_id>",
            secret: "<your_oidc_client_secret>",
            redirect_uri: "<your_gitlab_url>/users/auth/openid_connect/callback",
            gitlab: {
              groups_attribute: "groups",
              external_groups: ["Freelancer"]
            }
          }
        }
      }
    ]
    
  2. 保存文件并 重新配置极狐GitLab 使更改生效。

{{< /tab >}}

{{< tab title=”自编译(源代码)” >}}

  1. 编辑 /home/git/gitlab/config/gitlab.yml

    production: &base
      omniauth:
        providers:
         - { name: 'openid_connect',
             label: 'Provider name',
          args: {
            name: 'openid_connect',
            scope: ['openid','profile','email'],
            response_type: 'code',
            issuer: '<your_oidc_url>',
            discovery: true,
            client_auth_method: 'query',
            uid_field: '<uid_field>',
            client_options: {
              identifier: '<your_oidc_client_id>',
              secret: '<your_oidc_client_secret>',
              redirect_uri: '<your_gitlab_url>/users/auth/openid_connect/callback',
              gitlab: {
                groups_attribute: "groups",
                external_groups: ["Freelancer"]
              }
            }
          }
        }
    
  2. 保存文件并 重新配置极狐GitLab 使更改生效。

{{< /tab >}}

{{< /tabs >}}

审计员群组

{{< details >}}

  • Tier: 专业版, 旗舰版
  • Offering: 私有化部署

{{< /details >}}

你的 IdP 必须在 OIDC 响应中向极狐GitLab 传递群组信息。要使用此响应基于群组成员资格将用户分配为审计员,请配置极狐GitLab 以识别:

  • 使用 groups_attribute 设置在 OIDC 响应中查找群组的位置。
  • 使用 auditor_groups 设置,哪些群组成员资格授予用户审计员访问权限。

{{< tabs >}}

{{< tab title=”Linux package (Omnibus)” >}}

  1. 编辑 /etc/gitlab/gitlab.rb:

    gitlab_rails['omniauth_providers'] = [
      {
        name: "openid_connect",
        label: "Provider name",
        args: {
          name: "openid_connect",
          scope: ["openid","profile","email","groups"],
          response_type: "code",
          issuer: "<your_oidc_url>",
          discovery: true,
          client_auth_method: "query",
          uid_field: "<uid_field>",
          client_options: {
            identifier: "<your_oidc_client_id>",
            secret: "<your_oidc_client_secret>",
            redirect_uri: "<your_gitlab_url>/users/auth/openid_connect/callback",
            gitlab: {
              groups_attribute: "groups",
              auditor_groups: ["Auditor"]
            }
          }
        }
      }
    ]
    
  2. 保存文件并重新配置极狐GitLab以使更改生效。

{{< /tab >}}

{{< tab title=”Self-compiled (source)” >}}

  1. 编辑 /home/git/gitlab/config/gitlab.yml:

    production: &base
      omniauth:
        providers:
         - { name: 'openid_connect',
             label: 'Provider name',
          args: {
            name: 'openid_connect',
            scope: ['openid','profile','email','groups'],
            response_type: 'code',
            issuer: '<your_oidc_url>',
            discovery: true,
            client_auth_method: 'query',
            uid_field: '<uid_field>',
            client_options: {
              identifier: '<your_oidc_client_id>',
              secret: '<your_oidc_client_secret>',
              redirect_uri: '<your_gitlab_url>/users/auth/openid_connect/callback',
              gitlab: {
                groups_attribute: "groups",
                auditor_groups: ["Auditor"]
              }
            }
          }
        }
    
  2. 保存文件并重新配置极狐GitLab以使更改生效。

{{< /tab >}}

{{< /tabs >}}

管理员群组

你的 IdP 必须在 OIDC 响应中向极狐GitLab 传递群组信息。要使用此响应基于群组成员资格将用户分配为管理员,请配置极狐GitLab 以识别:

  • 使用 groups_attribute 设置在 OIDC 响应中查找群组的位置。
  • 使用 admin_groups 设置,哪些群组成员资格授予用户管理员访问权限。

{{< tabs >}}

{{< tab title=”Linux package (Omnibus)” >}}

  1. 编辑 /etc/gitlab/gitlab.rb:

    gitlab_rails['omniauth_providers'] = [
      {
        name: "openid_connect",
        label: "Provider name",
        args: {
          name: "openid_connect",
          scope: ["openid","profile","email"],
          response_type: "code",
          issuer: "<your_oidc_url>",
          discovery: true,
          client_auth_method: "query",
          uid_field: "<uid_field>",
          client_options: {
            identifier: "<your_oidc_client_id>",
            secret: "<your_oidc_client_secret>",
            redirect_uri: "<your_gitlab_url>/users/auth/openid_connect/callback",
            gitlab: {
              groups_attribute: "groups",
              admin_groups: ["Admin"]
            }
          }
        }
      }
    ]
    
  2. 保存文件并重新配置极狐GitLab以使更改生效。

{{< /tab >}}

{{< tab title=”Self-compiled (source)” >}}

  1. 编辑 /home/git/gitlab/config/gitlab.yml:

    production: &base
      omniauth:
        providers:
         - { name: 'openid_connect',
             label: 'Provider name',
          args: {
            name: 'openid_connect',
            scope: ['openid','profile','email'],
            response_type: 'code',
            issuer: '<your_oidc_url>',
            discovery: true,
            client_auth_method: 'query',
            uid_field: '<uid_field>',
            client_options: {
              identifier: '<your_oidc_client_id>',
              secret: '<your_oidc_client_secret>',
              redirect_uri: '<your_gitlab_url>/users/auth/openid_connect/callback',
              gitlab: {
                groups_attribute: "groups",
                admin_groups: ["Admin"]
              }
            }
          }
        }
    
  2. 保存文件并重新配置极狐GitLab以使更改生效。

{{< /tab >}}

{{< /tabs >}}

配置 ID 令牌的自定义持续时间

{{< details >}}

  • Tier: 基础版, 专业版, 旗舰版
  • Offering: 私有化部署

{{< /details >}}

{{< history >}}

  • 引入于极狐GitLab 17.8。

{{< /history >}}

默认情况下,极狐GitLab ID 令牌在 120 秒后过期。

要为您的 ID 令牌配置自定义持续时间:

{{< tabs >}}

{{< tab title=”Linux package (Omnibus)” >}}

  1. 编辑 /etc/gitlab/gitlab.rb:

    gitlab_rails['oidc_provider_openid_id_token_expire_in_seconds'] = 3600
    
  2. 保存文件并重新配置极狐GitLab以使更改生效。

{{< /tab >}}

{{< tab title=”Self-compiled (source)” >}}

  1. 编辑 /home/git/gitlab/config/gitlab.yml:

    production: &base
      oidc_provider:
       openid_id_token_expire_in_seconds: 3600
    
  2. 保存文件并重新配置极狐GitLab以使更改生效。

{{< /tab >}}

{{< /tabs >}}

管理模式的升级认证

{{< details >}}

  • Tier: 基础版, 专业版, 旗舰版
  • Offering: 私有化部署
  • Status: Experiment

{{< /details >}}

{{< history >}}

  • 引入于极狐GitLab 17.11,使用名为 omniauth_step_up_auth_for_admin_mode功能标志。默认禁用。

{{< /history >}}

{{< alert type=”flag” >}}

此功能的可用性由功能标志控制。有关更多信息,请参阅历史记录。此功能可用于测试,但尚未准备好用于生产环境。

{{< /alert >}}

在某些情况下,默认认证方法不能充分保护关键资源或高风险操作。升级认证为特权操作或敏感操作添加额外的认证层,例如访问管理员区域。

通过升级认证,用户必须提供额外的凭证才能访问某些功能或执行特定操作。这些额外的方法可以包括诸如两因素认证 (2FA)、生物认证或一次性密码 (OTP) 等方法。

OIDC 标准包括认证上下文类引用 (ACR)。ACR 概念帮助配置和实施适用于不同场景的升级认证,例如管理模式。

此功能是一个实验,可能会在没有通知的情况下进行更改。此功能尚未准备好用于生产环境。如果您希望使用此功能,应首先在生产环境之外进行测试。

启用管理模式的升级认证

要启用管理模式的升级认证:

  1. 编辑您的极狐GitLab 配置文件 (gitlab.yml/etc/gitlab/gitlab.rb) 以为特定的 OmniAuth 提供者启用升级认证。

    production: &base
      omniauth:
        providers:
        - { name: 'openid_connect',
            label: 'Provider name',
            args: {
              name: 'openid_connect',
              # ...
              allow_authorize_params: ["claims"], # 将此与 `step_up_auth => admin_mode => params` 中定义的参数匹配
            },
            step_up_auth: {
              admin_mode: {
                id_token: {
                  # `required` 字段声明 ID 令牌中需要完全匹配的声明。
                  # 在此示例中,'acr' (认证上下文类引用) 声明必须具有值 'gold' 才能通过升级认证挑战。
                  # 这确保了特定的认证保证水平。
                  required: {
                    acr: 'gold'
                  }
                },
                # `params` 字段定义在认证过程中发送的任何附加参数。
                # 在此示例中,`claims` 参数被添加到授权请求中,并指示身份提供者在 ID 令牌中包含值为 'gold' 的 'acr' 声明。
                # 'essential: true' 表示此声明是成功认证所必需的。
                params: {
                  claims: {
                    id_token: {
                      acr: {
                        essential: true,
                        values: ['gold']
                      }
                    }
                  }
                }
              },
            }
          }
    
  2. 保存配置文件并重新启动极狐GitLab 以使更改生效。

{{< alert type=”note” >}}

虽然 OIDC 是标准化的,但不同的身份提供者 (IdPs) 可能有独特的要求。params 设置允许一个灵活的哈希定义升级认证所需的参数。这些值可能会根据每个 IdP 的要求而有所不同。

{{< /alert >}}

使用 Keycloak 启用管理模式的升级认证

Keycloak 支持通过定义认证级别和自定义浏览器登录流程来实现升级认证。

要在极狐GitLab 中使用 Keycloak 配置管理模式的升级认证:

  1. 在极狐GitLab 中配置 Keycloak

  2. 遵循 Keycloak 文档中的步骤在 Keycloak 中创建具有升级认证的浏览器登录流程。

  3. 编辑您的极狐GitLab 配置文件 (gitlab.yml/etc/gitlab/gitlab.rb) 以在 Keycloak OIDC 提供者配置中启用升级认证。

    Keycloak 定义了两个不同的认证级别:silvergold。以下示例使用 gold 来表示增加的安全级别。

    production: &base
      omniauth:
        providers:
        - { name: 'openid_connect',
            label: 'Keycloak',
            args: {
              name: 'openid_connect',
              # ...
              allow_authorize_params: ["claims"] # 将此与 `step_up_auth => admin_mode => params` 中定义的参数匹配
            },
            step_up_auth: {
              admin_mode: {
                id_token: {
                  # 在此示例中,'acr' 声明必须具有值 'gold',这在 Keycloak 文档中也有定义。
                  required: {
                    acr: 'gold'
                  }
                },
                params: {
                  claims: { id_token: { acr: { essential: true, values: ['gold'] } } }
                }
              },
            }
          }
    
  4. 保存配置文件并重新启动极狐GitLab 以使更改生效。