showdoc icon indicating copy to clipboard operation
showdoc copied to clipboard

对接authetik oauth2 认证时,用户名 和 显示名字段 修复

Open wsfnk opened this issue 7 months ago • 2 comments

测试版本:authetik 2025.4.1 、showdoc 3.4.1

测试问题1:当 authetik 系统内 用户 不写 显示名称,只写 用户名称时,showdoc 无法获取 用户名称,

Image

Image

此时 userinfo接口返回数据,格式如下

{
  "sub": "aaa",
  "email": "[email protected]",
  "email_verified": true,
  "name": "",
  "given_name": "",
  "preferred_username": "aaa",
  "nickname": "aaa",
  "groups": ["search"]
}

测试问题2:当 authetik 填写 用户名 aaa 、显示名 张三 ,showdoc 能成功联动登录,不过show 这边展示的用户名 和 显示名 都是 张三, 建议改成 用户名用 aaa,显示名 用 张三。(即 userinfo 返回接口要是 有preferred_username 就把这个作为 用户名)

如下是 对 server/Application/Api/Controller/ExtLoginController.class.php 文件 getUserNameFromOAuth2 函数的修改,可以实现该 效果,麻烦维护者看看 是否可以采纳,兼容更多的场景

## 原函数内容
    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;
    }

wsfnk avatar Jun 01 '25 09:06 wsfnk

我已经提交代码了。没有采用你的修改方式。我只要判空就好。name空的话会被忽略,使用preferred_username

star7th avatar Jun 02 '25 04:06 star7th

哦哦,好的,这样的话,问题一对应的场景 应该是没问题了,问题二对应的场景对于这俩应用对接时可能不算太完美,不过已经很好了,authentik可以用属性映射解决,多谢多谢

wsfnk avatar Jun 02 '25 05:06 wsfnk