authentik实践之二、配置oAuth2/OIDC集成Showdoc 与 gitlab

oAuth2 集成 showdoc

authentik 创建 应用程序、提供程序(application、provider)

file
file
(Tips: 这里 应用的重定向地址,后面来补,因为要填写 具体应用的回调地址,一般要在 配置应用时才能看到)
file
(Tips: 授权绑定逻辑,要注意,默认不绑定 则所有用户 均有访问权限)
file

应用程序 绑定用户/用户组(作用:授权 用户/用户组 有权限访问 该应用)

file

将 authentik 提供程序 高级协议设置处 Subject 模式:改为用户名(见图)

file

authentik 对接 showdoc

## 需要获取的信息如下
    Client id:
    Client secret: 要点击 编辑才能看到
    Oauth host:
    Authorize path:
    AccessToken path:
    User info path:
    callback url(showdoc应用回调地址): https://wiki.atstm.cc/server/?s=/api/extLogin/oauth2

file

(Tips: 将 Showdoc 这里的回调地址,填写到 authentik provider 程序的重定向 处,如下图)
file
file

存在的问题(showdoc 3.4.1版本)

## 已向showdoc 提issue
     https://github.com/star7th/showdoc/issues/2350

## 问题一、当你按照上述对接后,确实能成功登录,但当你 authentik 用户 没有填写显示名称时,showdoc无法完成认证,因为showdoc会认为 未获取到用户信息,其authentik userinfo接口获取到信息格式如下
{
  "sub": "aaa",
  "email": "aaa@gmail.com",
  "email_verified": true,
  "name": "",
  "given_name": "",
  "preferred_username": "aaa",
  "nickname": "aaa",
  "groups": ["search"]
}

## 问题二、当 authentik 用户填写了显示名, showdoc 会将 用户名 和显示名称 都设置成为 你authentik 设置的显示名
    一般我们会将 authentik 用户名 设置为zhangsan, 显示名设置为 张三,但是你在 showdoc 这边却是 用户名 显示名都是张三

修复问题

## 修复方案,进入showdoc 容器,找到 ExtLoginController.class.php 文件,修改 getUserNameFromOAuth2 函数内容
     目的:实现 用 preferred_username 作为showdoc的用户名,用name或者given_name 作为显示名

## 进入showdoc 容器,查找名为 ExtLoginController.class.php 的文件,(会找到两个,其md5都是一样的)
    docker exec -it showdoc bash
    11f4124210ab:/showdoc_data/html# find / -name ExtLoginController.class.php
    /var/www/html/server/Application/Api/Controller/ExtLoginController.class.php
    /showdoc_data/html/server/Application/Api/Controller/ExtLoginController.class.php

    # 对比md5 发现是一样的
    11f4124210ab:/showdoc_data/html# md5sum /showdoc_data/html/server/Application/Api/Controller/ExtLoginController.class.php
    5353b683dd638e8d1c29b857d1197cdd  /showdoc_data/html/server/Application/Api/Controller/ExtLoginController.class.php
    11f4124210ab:/showdoc_data/html# md5sum /var/www/html/server/Application/Api/Controller/ExtLoginController.class.php
    5353b683dd638e8d1c29b857d1197cdd  /var/www/html/server/Application/Api/Controller/ExtLoginController.class.php

    # 备份一份,进行修改
    11f4124210ab:/showdoc_data/html# cp /showdoc_data/html/server/Application/Api/Controller/ExtLoginController.class.php ExtLoginController.class.php.bak

## 编辑 ExtLoginController.class.php 修改函数(上述两个文件都要修改,建议修改一个,然后用其覆盖另一个)
    vi /showdoc_data/html/server/Application/Api/Controller/ExtLoginController.class.php
## 原函数内容
    private function getUserNameFromOAuth2($array)                                                                                                                                                          
    {                                                                                                                                                                                                       
        $keysToCheck = ["preferred_username", "name", "username", "login"];                                                                                                                                 

        foreach ($array as $key => $value) {                                                                                                                                                                
            if (!is_array($value) && in_array($key, $keysToCheck, true)) {                                                                                                                                  
                return $value; // ....................................                                                                                                                                      
            }                                                                                                                                                                                               
        }                                                                                                                                                                                                   

        foreach ($array as $value) {                                                                                                                                                                        
            if (is_array($value)) {                                                                                                                                                                         
                $username = $this->getUserNameFromOAuth2($value); // .....................                                                                                                                  
                if ($username) {                                                                                                                                                                            
                    return $username; // ...........................                                                                                                                                        
                }                                                                                                                                                                                           
            }                                                                                                                                                                                               
        }                                                                                                                                                                                                   

        return false; // ........................... false                                                                                                                                                  
    }  

## 改后函数内容
    private function getUserNameFromOAuth2($array)
    {
        $keysToCheck = ["preferred_username", "username", "name", "login", "email", "sub"];

        foreach ($array as $key => $value) {
            if (!is_array($value) && in_array($key, $keysToCheck, true)) {
                // 如果是 email,就拆掉 @domain,只取前缀
                if ($key === "email") {
                    return explode('@', $value)[0];
                }
                return $value;
            }
        }

        // 递归搜索嵌套数组
        foreach ($array as $value) {
            if (is_array($value)) {
                $username = $this->getUserNameFromOAuth2($value);
                if ($username) {
                    return $username;
                }
            }
        }

        return false;
    }

## 修改完成后,退出容器,重启容器(或者重新机器后再次验证,建议删除showdoc 这边之前同步的用户,重新认证,你会发现 用户名 和 显示名  都能一一匹配了)

file

Generic OAuth2 集成 gitlab

创建应用程序和提供程序(暂略)

authentik 对接 gitlab

## gitlab 官方参考文章(注意这里看 Generic OAuth2)
    https://archives.docs.gitlab.com/16.11/ee/integration/oauth2_generic.html?tab=Linux+package+%28Omnibus%29
    # 极狐官方的文档
    https://gitlab.cn/blog/2022/03/03/jihu-sso/

## 编辑 gitlab配置文件(我是docker compose 方式部署的)
    vi /opt/devops/gitlab/config/gitlab.rb

gitlab_rails['omniauth_allow_single_sign_on'] = ['oauth2_generic']
# 使用OAuth登录的用户无需管理员审批,自动创建GitLab用户
gitlab_rails['omniauth_block_auto_created_users'] = false
# 若希望首次 OAuth 登录自动创建账户,则开启如下这行
# gitlab_rails['omniauth_auto_link_user'] = true
gitlab_rails['omniauth_providers'] = [
  {
    "name" => "oauth2_generic",
    # 显示在GitLab登陆页面的SSO登录按钮的文字
    "label" => " 统一认证SSO平台 登录",
    "app_id" => "appxxxxxxxx",
    "app_secret" => "xxxxxxxxx",
    args: {
      client_options: {
        # authentik 的站点url
        site: "https://sso.xxxxx.cn",
        user_info_url: "/application/o/userinfo/",
        authorize_url: "/application/o/authorize/",
        token_url: "/application/o/token/"
      },
      user_response_structure: {
        root_path: [],
        # id_path 不建议写成 sub, 因为提供程序的sub 可以更改sub的类型,不能保证统一是username,故建议写成preferred_username
        id_path: ["preferred_username"],
        # 属性映射,如下是针对authentik的ouath2 做的映射适配
        attributes: {
          email: "email",
          name: "name"
        }
      },
      authorize_params: {
        scope: "openid profile email"
      },
      strategy_class: "OmniAuth::Strategies::OAuth2Generic"
    }
  }
]

## 重载gitlab
    docker exec -it gitlab bash
    gitlab-ctl reconfigure

## Tips: 若采用该验证方式登录,则git提交或者克隆代码前,需要自行在gitlab个人资料处创建访问令牌或者ssh密钥,(注意访问令牌有效期最大一年)

附、若需要将gitlab 原本地账户切为oAuth2 通用验证方式(没空实验,没写完)

## 老版本gitlab 我的是 极狐 v16.11.10-jh (去查并修改数据库)
    docker exec -it gitlab bash
    gitlab-psqlgitlab-psql

    # 根据用户名aaa查询ID
    SELECT id, username, email FROM users WHERE username = 'aaa';
 id | username |     email      
----+----------+----------------
 39 | aaa      | aaa@aaa.com
(1 row)

    # 根据得到的ID,查询当前登录方式
    SELECT * FROM identities WHERE user_id = 39;
 id |                  extern_uid                  | provider | user_id |         created_at         |         updated_at         | secondary_ext
ern_uid | saml_provider_id | trusted_extern_uid 
----+----------------------------------------------+----------+---------+----------------------------+----------------------------+--------------
--------+------------------+--------------------
  3 | uid=aaa,cn=users,cn=compat,dc=e2e,dc=cc | ldapmain |      39 | 2024-11-25 03:35:07.470157 | 2024-11-25 03:35:07.470157 |              
        |                  | t
(1 row)
声明:本文为原创,作者为 辣条①号,转载时请保留本声明及附带文章链接:https://boke.wsfnk.com/archives/1486.html
谢谢你请我吃辣条谢谢你请我吃辣条

如果文章对你有帮助,欢迎点击上方按钮打赏作者

最后编辑于:2025/6/13作者: 辣条①号

目标:网络规划设计师、系统工程师、ceph存储工程师、云计算工程师。 不负遇见,不谈亏欠!

暂无评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

arrow grin ! ? cool roll eek evil razz mrgreen smile oops lol mad twisted wink idea cry shock neutral sad ???

文章目录