diff --git a/api/apps/auth/README.md b/api/apps/auth/README.md index 5dca3218c..3071c422d 100644 --- a/api/apps/auth/README.md +++ b/api/apps/auth/README.md @@ -32,8 +32,16 @@ oidc_config = { "redirect_uri": "https://your-app.com/v1/user/oauth/callback/" } +# Github OAuth configuration +github_config = { + "type": "github" + "client_id": "your_client_id", + "client_secret": "your_client_secret", + "redirect_uri": "https://your-app.com/v1/user/oauth/callback/" +} + # Get client instance -client = get_auth_client(oauth_config) # or oidc_config +client = get_auth_client(oauth_config) ``` ### Authentication Flow diff --git a/api/apps/auth/__init__.py b/api/apps/auth/__init__.py index 3a6437f30..f989b6d2e 100644 --- a/api/apps/auth/__init__.py +++ b/api/apps/auth/__init__.py @@ -16,11 +16,13 @@ from .oauth import OAuthClient from .oidc import OIDCClient +from .github import GithubOAuthClient CLIENT_TYPES = { "oauth2": OAuthClient, - "oidc": OIDCClient + "oidc": OIDCClient, + "github": GithubOAuthClient } diff --git a/api/apps/auth/github.py b/api/apps/auth/github.py new file mode 100644 index 000000000..5d46b277d --- /dev/null +++ b/api/apps/auth/github.py @@ -0,0 +1,63 @@ +# +# Copyright 2025 The InfiniFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import requests +from .oauth import OAuthClient, UserInfo + + +class GithubOAuthClient(OAuthClient): + def __init__(self, config): + """ + Initialize the GithubOAuthClient with the provider's configuration. + """ + config.update({ + "authorization_url": "https://github.com/login/oauth/authorize", + "token_url": "https://github.com/login/oauth/access_token", + "userinfo_url": "https://api.github.com/user", + "scope": "user:email" + }) + super().__init__(config) + + + def fetch_user_info(self, access_token, **kwargs): + """ + Fetch github user info. + """ + user_info = {} + try: + headers = {"Authorization": f"Bearer {access_token}"} + # user info + response = requests.get(self.userinfo_url, headers=headers, timeout=self.http_request_timeout) + response.raise_for_status() + user_info.update(response.json()) + # email info + response = requests.get(self.userinfo_url+"/emails", headers=headers, timeout=self.http_request_timeout) + response.raise_for_status() + email_info = response.json() + user_info["email"] = next( + (email for email in email_info if email["primary"]), None + )["email"] + return self.normalize_user_info(user_info) + except requests.exceptions.RequestException as e: + raise ValueError(f"Failed to fetch github user info: {e}") + + + def normalize_user_info(self, user_info): + email = user_info.get("email") + username = user_info.get("login", str(email).split("@")[0]) + nickname = user_info.get("name", username) + avatar_url = user_info.get("avatar_url", "") + return UserInfo(email=email, username=username, nickname=nickname, avatar_url=avatar_url) diff --git a/api/apps/user_app.py b/api/apps/user_app.py index be6eb5c10..ddca41018 100644 --- a/api/apps/user_app.py +++ b/api/apps/user_app.py @@ -233,6 +233,8 @@ def oauth_callback(channel): @manager.route("/github_callback", methods=["GET"]) # noqa: F821 def github_callback(): """ + **Deprecated**, Use `/oauth/callback/` instead. + GitHub OAuth callback endpoint. --- tags: diff --git a/conf/service_conf.yaml b/conf/service_conf.yaml index 45f4e9685..39e48bc7e 100644 --- a/conf/service_conf.yaml +++ b/conf/service_conf.yaml @@ -64,9 +64,12 @@ redis: # base_url: '' # oauth: # github: +# type: github +# icon: github +# display_name: "Github" # client_id: xxxxxxxxxxxxxxxxxxxxxxxxx -# secret_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxx -# url: https://github.com/login/oauth/access_token +# client_secret: xxxxxxxxxxxxxxxxxxxxxxxx +# redirect_uri: https://your-app.com/v1/user/oauth/callback/github # feishu: # app_id: cli_xxxxxxxxxxxxxxxxxxx # app_secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxx diff --git a/docker/service_conf.yaml.template b/docker/service_conf.yaml.template index 42a699833..74fbc6e99 100644 --- a/docker/service_conf.yaml.template +++ b/docker/service_conf.yaml.template @@ -76,9 +76,12 @@ redis: # image2text_model: '' # oauth: # github: +# type: github +# icon: github +# display_name: "Github" # client_id: xxxxxxxxxxxxxxxxxxxxxxxxx -# secret_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxx -# url: https://github.com/login/oauth/access_token +# client_secret: xxxxxxxxxxxxxxxxxxxxxxxx +# redirect_uri: https://your-app.com/v1/user/oauth/callback/github # feishu: # app_id: cli_xxxxxxxxxxxxxxxxxxx # app_secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxx