Skip to content

Github 第三方登录插件#

功能介绍#

配置Github插件后,可以点击ArkID登录页面的Github图标,跳转到Github网站完成Oauth2认证,并和ArkID的用户绑定

创建Github应用#

X7Ew38.png

名称,主页URL和回调URL可以随意填写,回调URL后面步骤中会更改成ArkID自动生成的URL。 X7E0gS.png

X7EruQ.png

X7EBjg.png

创建ArkID第三方登录配置,获取回调URL#

X7Ef3T.png

X7E4vF.png

X7EhgU.png

更新Github应用回调URL,点击登录按钮#

X7EWCV.png

X7V4it.png

X7VfII.png

实现思路#

需要覆盖插件基类的抽象方法,插件基类见arkid.core.extension.extrnal_idp.ExternalIdpExtension

统一绑定和解绑说明#

请参见三方账号绑定

抽象方法实现:#

代码#

extension_root.com_longgui_external_idp_github.ExternalIdpGithubExtension (ExternalIdpExtension) #

Source code in extension_root/com_longgui_external_idp_github/__init__.py
class ExternalIdpGithubExtension(ExternalIdpExtension):
    def load(self):
        super().load()
        self.register_extend_field(GithubUser, "github_user_id")
        self.register_extend_field(GithubUser, "github_nickname")
        self.register_extend_field(GithubUser, "github_avatar")
        self.register_external_idp_schema("github", GithubConfigSchema)

    def get_img_url(self):
        """
        返回Github的图标URL
        """
        return IMG_URL

    def get_auth_code_from_request(self, request):
        code = request.GET.get("code", '')
        return code

    def get_authorize_url(self, config, callback_url, next_url):
        """
        Args:
            config (arkid.core.extension.TenantExtensionConfig): 第三方登录的插件运行时配置
            redirect_uri (str): 在ArkID中创建Github登录配置后返回的回调地址
        Returns:
            str: 返回用于向Github发起认证的URL
        """
        redirect_uri = "{}{}".format(callback_url, next_url)
        redirect_uri = quote(redirect_uri)
        url = "{}?client_id={}&redirect_uri={}".format(
            AUTHORIZE_URL,
            config.config.get("client_id"),
            redirect_uri,
        )
        return url

    def get_ext_token(self, config, code):
        """
        Args:
            config (arkid.core.extension.TenantExtensionConfig): 第三方登录的插件运行时配置
            code (str): Github返回的授权码
        Returns:
            str: 返回Github返回的access_token
        """
        response = requests.post(
            GET_TOKEN_URL,
            params={
                "code": code,
                "client_id": config.config.get("client_id"),
                "client_secret": config.config.get("client_secret"),
                "grant_type": "authorization_code",
            },
        ).__getattribute__("_content")
        result = dict(
            [(k, v[0]) for k, v in parse_qs(response.decode()).items()]
        )  # 将响应信息转换为字典
        return result["access_token"]

    def get_ext_user_info(self, config, code, token):
        """
        Args:
            config (arkid.core.extension.TenantExtensionConfig): 第三方登录的插件运行时配置
            code (str): Github返回的授权码
            token (str): Github返回的access_token
        Returns:
            tuple: 返回Github中用户信息中的id, login,avatar_url和所有用户信息
        """
        headers = {"Authorization": "token " + token}
        response = requests.get(
            GET_USERINFO_URL,
            params={"access_token": token},
            headers=headers,
        ).json()
        return response["id"], response["login"], response["avatar_url"], response

    def get_arkid_user(self, ext_id):
        """
        Args:
            ext_id (str): 从Github用户信息接口获取的用户标识
        Returns:
            arkid.core.models.User: 返回ext_id绑定的ArkID用户
        """
        github_user = GithubUser.valid_objects.filter(github_user_id=ext_id).first()
        if github_user:
            return github_user.target
        else:
            return None

    def bind_arkid_user(self, ext_id, user, data):
        """
        Args:
            ext_id (str): 从Github用户信息接口获取的用户标识
            user (arkid.core.models.User): 用于绑定的ArkID用户
            data (dict) request数据
        """
        user.github_user_id = ext_id
        user.github_nickname = data.get('ext_name', '')
        user.github_avatar = data.get('ext_icon', '')
        user.save()

    def get_img_and_redirect_url(self, config):
        return config.config.get("img_url", ""), config.config.get("login_url", "")

bind_arkid_user(self, ext_id, user, data) #

Parameters:

Name Type Description Default
ext_id str

从Github用户信息接口获取的用户标识

required
user arkid.core.models.User

用于绑定的ArkID用户

required
Source code in extension_root/com_longgui_external_idp_github/__init__.py
def bind_arkid_user(self, ext_id, user, data):
    """
    Args:
        ext_id (str): 从Github用户信息接口获取的用户标识
        user (arkid.core.models.User): 用于绑定的ArkID用户
        data (dict) request数据
    """
    user.github_user_id = ext_id
    user.github_nickname = data.get('ext_name', '')
    user.github_avatar = data.get('ext_icon', '')
    user.save()

get_arkid_user(self, ext_id) #

Parameters:

Name Type Description Default
ext_id str

从Github用户信息接口获取的用户标识

required

Returns:

Type Description
arkid.core.models.User

返回ext_id绑定的ArkID用户

Source code in extension_root/com_longgui_external_idp_github/__init__.py
def get_arkid_user(self, ext_id):
    """
    Args:
        ext_id (str): 从Github用户信息接口获取的用户标识
    Returns:
        arkid.core.models.User: 返回ext_id绑定的ArkID用户
    """
    github_user = GithubUser.valid_objects.filter(github_user_id=ext_id).first()
    if github_user:
        return github_user.target
    else:
        return None

get_auth_code_from_request(self, request) #

抽象方法

Parameters:

Name Type Description Default
request HTTPRequest

第三方认证返回的用户标识

required

Returns:

Type Description
str

授权码

Source code in extension_root/com_longgui_external_idp_github/__init__.py
def get_auth_code_from_request(self, request):
    code = request.GET.get("code", '')
    return code

get_authorize_url(self, config, callback_url, next_url) #

Parameters:

Name Type Description Default
config arkid.core.extension.TenantExtensionConfig

第三方登录的插件运行时配置

required
redirect_uri str

在ArkID中创建Github登录配置后返回的回调地址

required

Returns:

Type Description
str

返回用于向Github发起认证的URL

Source code in extension_root/com_longgui_external_idp_github/__init__.py
def get_authorize_url(self, config, callback_url, next_url):
    """
    Args:
        config (arkid.core.extension.TenantExtensionConfig): 第三方登录的插件运行时配置
        redirect_uri (str): 在ArkID中创建Github登录配置后返回的回调地址
    Returns:
        str: 返回用于向Github发起认证的URL
    """
    redirect_uri = "{}{}".format(callback_url, next_url)
    redirect_uri = quote(redirect_uri)
    url = "{}?client_id={}&redirect_uri={}".format(
        AUTHORIZE_URL,
        config.config.get("client_id"),
        redirect_uri,
    )
    return url

get_ext_token(self, config, code) #

Parameters:

Name Type Description Default
config arkid.core.extension.TenantExtensionConfig

第三方登录的插件运行时配置

required
code str

Github返回的授权码

required

Returns:

Type Description
str

返回Github返回的access_token

Source code in extension_root/com_longgui_external_idp_github/__init__.py
def get_ext_token(self, config, code):
    """
    Args:
        config (arkid.core.extension.TenantExtensionConfig): 第三方登录的插件运行时配置
        code (str): Github返回的授权码
    Returns:
        str: 返回Github返回的access_token
    """
    response = requests.post(
        GET_TOKEN_URL,
        params={
            "code": code,
            "client_id": config.config.get("client_id"),
            "client_secret": config.config.get("client_secret"),
            "grant_type": "authorization_code",
        },
    ).__getattribute__("_content")
    result = dict(
        [(k, v[0]) for k, v in parse_qs(response.decode()).items()]
    )  # 将响应信息转换为字典
    return result["access_token"]

get_ext_user_info(self, config, code, token) #

Parameters:

Name Type Description Default
config arkid.core.extension.TenantExtensionConfig

第三方登录的插件运行时配置

required
code str

Github返回的授权码

required
token str

Github返回的access_token

required

Returns:

Type Description
tuple

返回Github中用户信息中的id, login,avatar_url和所有用户信息

Source code in extension_root/com_longgui_external_idp_github/__init__.py
def get_ext_user_info(self, config, code, token):
    """
    Args:
        config (arkid.core.extension.TenantExtensionConfig): 第三方登录的插件运行时配置
        code (str): Github返回的授权码
        token (str): Github返回的access_token
    Returns:
        tuple: 返回Github中用户信息中的id, login,avatar_url和所有用户信息
    """
    headers = {"Authorization": "token " + token}
    response = requests.get(
        GET_USERINFO_URL,
        params={"access_token": token},
        headers=headers,
    ).json()
    return response["id"], response["login"], response["avatar_url"], response

get_img_and_redirect_url(self, config) #

返回前端渲染第三方登录的按钮 抽象方法

Parameters:

Name Type Description Default
config arkid.extension.models.TenantExtensionConfig

第三方认证提供的Client_ID,

required

Returns:

Type Description
tuple

返回图片url和跳转地址('image_url', 'redirect_url')

Source code in extension_root/com_longgui_external_idp_github/__init__.py
def get_img_and_redirect_url(self, config):
    return config.config.get("img_url", ""), config.config.get("login_url", "")

get_img_url(self) #

返回Github的图标URL

Source code in extension_root/com_longgui_external_idp_github/__init__.py
def get_img_url(self):
    """
    返回Github的图标URL
    """
    return IMG_URL

load(self) #

抽象方法,插件加载的入口方法

Source code in extension_root/com_longgui_external_idp_github/__init__.py
def load(self):
    super().load()
    self.register_extend_field(GithubUser, "github_user_id")
    self.register_extend_field(GithubUser, "github_nickname")
    self.register_extend_field(GithubUser, "github_avatar")
    self.register_external_idp_schema("github", GithubConfigSchema)

评论