mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-08-10 21:39:02 +08:00
Feat: Add /login/channels
route and improve auth logic for frontend third-party login integration (#7521)
### What problem does this PR solve? Add `/login/channels` route and improve auth logic to support frontend integration with third-party login providers: - Add `/login/channels` route to provide authentication channel list with `display_name` and `icon` - Optimize user info parsing logic by prioritizing `avatar_url` and falling back to `picture` - Simplify OIDC token validation by removing unnecessary `kid` checks - Ensure `client_id` is safely cast to string during `audience` validation - Fix typo --- - Related pull request: #7379 ### Type of change - [x] New Feature (non-breaking change which adds functionality) - [x] Documentation Update
This commit is contained in:
parent
014a1535f2
commit
e349635a3d
@ -20,7 +20,7 @@ oauth_config = {
|
||||
"authorization_url": "https://provider.com/oauth/authorize",
|
||||
"token_url": "https://provider.com/oauth/token",
|
||||
"userinfo_url": "https://provider.com/oauth/userinfo",
|
||||
"redirect_uri": "https://your-app.com/oauth/callback/<channel>"
|
||||
"redirect_uri": "https://your-app.com/v1/user/oauth/callback/<channel>"
|
||||
}
|
||||
|
||||
# OIDC configuration
|
||||
@ -29,7 +29,7 @@ oidc_config = {
|
||||
"issuer": "https://provider.com/v1/oidc",
|
||||
"client_id": "your_client_id",
|
||||
"client_secret": "your_client_secret",
|
||||
"redirect_uri": "https://your-app.com/oauth/callback/<channel>"
|
||||
"redirect_uri": "https://your-app.com/v1/user/oauth/callback/<channel>"
|
||||
}
|
||||
|
||||
# Get client instance
|
||||
|
@ -102,5 +102,7 @@ class OAuthClient:
|
||||
email = user_info.get("email")
|
||||
username = user_info.get("username", str(email).split("@")[0])
|
||||
nickname = user_info.get("nickname", username)
|
||||
avatar_url = user_info.get("avatar_url", None)
|
||||
if avatar_url is None:
|
||||
avatar_url = user_info.get("picture", "")
|
||||
return UserInfo(email=email, username=username, nickname=nickname, avatar_url=avatar_url)
|
||||
|
@ -39,6 +39,7 @@ class OIDCClient(OAuthClient):
|
||||
})
|
||||
|
||||
super().__init__(config)
|
||||
self.issuer = config['issuer']
|
||||
self.jwks_uri = config['jwks_uri']
|
||||
|
||||
|
||||
@ -60,11 +61,8 @@ class OIDCClient(OAuthClient):
|
||||
Parse and validate OIDC ID Token (JWT format) with signature verification.
|
||||
"""
|
||||
try:
|
||||
# Decode JWT header to extract key ID (kid) without verifying signature
|
||||
# Decode JWT header without verifying signature
|
||||
headers = jwt.get_unverified_header(id_token)
|
||||
kid = headers.get("kid")
|
||||
if not kid:
|
||||
raise ValueError("ID Token missing 'kid' in header")
|
||||
|
||||
# OIDC usually uses `RS256` for signing
|
||||
alg = headers.get("alg", "RS256")
|
||||
@ -79,7 +77,7 @@ class OIDCClient(OAuthClient):
|
||||
id_token,
|
||||
key=signing_key,
|
||||
algorithms=[alg],
|
||||
audience=self.client_id,
|
||||
audience=str(self.client_id),
|
||||
issuer=self.issuer,
|
||||
)
|
||||
return decoded_token
|
||||
|
@ -116,7 +116,30 @@ def login():
|
||||
)
|
||||
|
||||
|
||||
@manager.route("/login/<channel>") # noqa: F821
|
||||
@manager.route("/login/channels", methods=["GET"]) # noqa: F821
|
||||
def get_login_channels():
|
||||
"""
|
||||
Get all supported authentication channels.
|
||||
"""
|
||||
try:
|
||||
channels = []
|
||||
for channel, config in settings.OAUTH_CONFIG.items():
|
||||
channels.append({
|
||||
"channel": channel,
|
||||
"display_name": config.get("display_name", channel.title()),
|
||||
"icon": config.get("icon", "sso"),
|
||||
})
|
||||
return get_json_result(data=channels)
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
return get_json_result(
|
||||
data=[],
|
||||
message=f"Load channels failure, error: {str(e)}",
|
||||
code=settings.RetCode.EXCEPTION_ERROR
|
||||
)
|
||||
|
||||
|
||||
@manager.route("/login/<channel>", methods=["GET"]) # noqa: F821
|
||||
def oauth_login(channel):
|
||||
channel_config = settings.OAUTH_CONFIG.get(channel)
|
||||
if not channel_config:
|
||||
@ -171,7 +194,7 @@ def oauth_callback(channel):
|
||||
users = user_register(
|
||||
user_id,
|
||||
{
|
||||
"access_token": access_token,
|
||||
"access_token": get_uuid(),
|
||||
"email": user_info.email,
|
||||
"avatar": avatar,
|
||||
"nickname": user_info.nickname,
|
||||
@ -189,7 +212,7 @@ def oauth_callback(channel):
|
||||
# Try to log in
|
||||
user = users[0]
|
||||
login_user(user)
|
||||
return redirect(f"/?auth_success=true&user_id={user.get_id()}")
|
||||
return redirect(f"/?auth={user.get_id()}")
|
||||
|
||||
except Exception as e:
|
||||
rollback_user_registration(user_id)
|
||||
@ -201,8 +224,9 @@ def oauth_callback(channel):
|
||||
user.access_token = get_uuid()
|
||||
login_user(user)
|
||||
user.save()
|
||||
return redirect(f"/?auth_success=true&user_id={user.get_id()}")
|
||||
return redirect(f"/?auth={user.get_id()}")
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
return redirect(f"/?error={str(e)}")
|
||||
|
||||
|
||||
|
@ -75,11 +75,13 @@ redis:
|
||||
# grant_type: 'authorization_code'
|
||||
# custom_channel:
|
||||
# type: oidc
|
||||
# icon: sso
|
||||
# display_name: "Custom Channel"
|
||||
# issuer: https://provider.com/v1/oidc
|
||||
# client_id: xxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
# client_secret: xxxxxxxxxxxxxxxxxxxxxxxx
|
||||
# scope: "openid email profile"
|
||||
# redirect_uri: https://your-app.com/oauth/callback/custom_channel
|
||||
# redirect_uri: https://your-app.com/v1/user/oauth/callback/custom_channel
|
||||
# authentication:
|
||||
# client:
|
||||
# switch: false
|
||||
|
@ -87,11 +87,13 @@ redis:
|
||||
# grant_type: 'authorization_code'
|
||||
# custom_channel:
|
||||
# type: oidc
|
||||
# icon: sso
|
||||
# display_name: "Custom Channel"
|
||||
# issuer: https://provider.com/v1/oidc
|
||||
# client_id: xxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
# client_secret: xxxxxxxxxxxxxxxxxxxxxxxx
|
||||
# scope: "openid email profile"
|
||||
# redirect_uri: https://your-app.com/oauth/callback/custom_channel
|
||||
# redirect_uri: https://your-app.com/v1/user/oauth/callback/custom_channel
|
||||
# authentication:
|
||||
# client:
|
||||
# switch: false
|
||||
|
Loading…
x
Reference in New Issue
Block a user