Pārlūkot izejas kodu

Feat: Add OAuth `state` parameter for CSRF protection (#7709)

### What problem does this PR solve?

Add OAuth `state` parameter for CSRF protection:
- Updated `get_authorization_url()` to accept an optional state
parameter
- Generated a unique state value during OAuth login and stored in
session
- Verified state parameter in callback to ensure request legitimacy

This PR follows OAuth 2.0 security best practices by ensuring that the
authorization request originates from the same user who initiated the
flow.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
tags/v0.19.0
Chaoxi Weng pirms 5 mēnešiem
vecāks
revīzija
6ed81d6774
Revīzijas autora e-pasta adrese nav piesaistīta nevienam kontam
2 mainītis faili ar 12 papildinājumiem un 2 dzēšanām
  1. 3
    1
      api/apps/auth/oauth.py
  2. 9
    1
      api/apps/user_app.py

+ 3
- 1
api/apps/auth/oauth.py Parādīt failu

@@ -45,7 +45,7 @@ class OAuthClient:
self.http_request_timeout = 7


def get_authorization_url(self):
def get_authorization_url(self, state=None):
"""
Generate the authorization URL for user login.
"""
@@ -56,6 +56,8 @@ class OAuthClient:
}
if self.scope:
params["scope"] = self.scope
if state:
params["state"] = state
authorization_url = f"{self.authorization_url}?{urllib.parse.urlencode(params)}"
return authorization_url


+ 9
- 1
api/apps/user_app.py Parādīt failu

@@ -146,7 +146,9 @@ def oauth_login(channel):
raise ValueError(f"Invalid channel name: {channel}")
auth_cli = get_auth_client(channel_config)

auth_url = auth_cli.get_authorization_url()
state = get_uuid()
session["oauth_state"] = state
auth_url = auth_cli.get_authorization_url(state)
return redirect(auth_url)


@@ -161,6 +163,12 @@ def oauth_callback(channel):
raise ValueError(f"Invalid channel name: {channel}")
auth_cli = get_auth_client(channel_config)

# Check the state
state = request.args.get("state")
if not state or state != session.get("oauth_state"):
return redirect("/?error=invalid_state")
session.pop("oauth_state", None)

# Obtain the authorization code
code = request.args.get("code")
if not code:

Notiek ielāde…
Atcelt
Saglabāt