Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import json
  2. import uuid
  3. from core.plugin.impl.base import BasePluginClient
  4. from extensions.ext_redis import redis_client
  5. class OAuthProxyService(BasePluginClient):
  6. # Default max age for proxy context parameter in seconds
  7. __MAX_AGE__ = 5 * 60 # 5 minutes
  8. __KEY_PREFIX__ = "oauth_proxy_context:"
  9. @staticmethod
  10. def create_proxy_context(
  11. user_id: str,
  12. tenant_id: str,
  13. plugin_id: str,
  14. provider: str,
  15. credential_id: str | None = None,
  16. ):
  17. """
  18. Create a proxy context for an OAuth 2.0 authorization request.
  19. This parameter is a crucial security measure to prevent Cross-Site Request
  20. Forgery (CSRF) attacks. It works by generating a unique nonce and storing it
  21. in a distributed cache (Redis) along with the user's session context.
  22. The returned nonce should be included as the 'proxy_context' parameter in the
  23. authorization URL. Upon callback, the `use_proxy_context` method
  24. is used to verify the state, ensuring the request's integrity and authenticity,
  25. and mitigating replay attacks.
  26. """
  27. context_id = str(uuid.uuid4())
  28. data = {
  29. "user_id": user_id,
  30. "plugin_id": plugin_id,
  31. "tenant_id": tenant_id,
  32. "provider": provider,
  33. }
  34. if credential_id:
  35. data["credential_id"] = credential_id
  36. redis_client.setex(
  37. f"{OAuthProxyService.__KEY_PREFIX__}{context_id}",
  38. OAuthProxyService.__MAX_AGE__,
  39. json.dumps(data),
  40. )
  41. return context_id
  42. @staticmethod
  43. def use_proxy_context(context_id: str):
  44. """
  45. Validate the proxy context parameter.
  46. This checks if the context_id is valid and not expired.
  47. """
  48. if not context_id:
  49. raise ValueError("context_id is required")
  50. # get data from redis
  51. key = f"{OAuthProxyService.__KEY_PREFIX__}{context_id}"
  52. data = redis_client.get(key)
  53. if not data:
  54. raise ValueError("context_id is invalid")
  55. redis_client.delete(key)
  56. return json.loads(data)