Skip to content
Snippets Groups Projects
Commit 3d7f3f09 authored by Mohammad Torkashvand's avatar Mohammad Torkashvand
Browse files

Implement OIDCUser exception for self-authenticating callback endpoint

parent c9fd0e09
No related branches found
No related tags found
No related merge requests found
Pipeline #85409 failed
......@@ -16,6 +16,7 @@ docs/build
docs/vale/styles/*
!docs/vale/styles/config/
!docs/vale/styles/custom/
.DS_Store
.idea
.venv
``gso.products``
================
``gso.auth``
============
.. automodule:: gso.auth
:members:
......
......@@ -19,6 +19,7 @@ Subpackages
:titlesonly:
module/api/index
module/auth/index
module/cli/index
module/products/index
module/schedules/index
......
......@@ -16,8 +16,9 @@ from json import JSONDecodeError
from typing import Any, ClassVar, cast
from fastapi.exceptions import HTTPException
from fastapi.param_functions import Depends
from fastapi.param_functions import Depends, Security
from fastapi.requests import Request
from fastapi.security import APIKeyHeader
from fastapi.security.http import HTTPBearer
from httpx import AsyncClient, NetworkError
from pydantic import BaseModel
......@@ -30,6 +31,18 @@ logger = get_logger(__name__)
HTTPX_SSL_CONTEXT = ssl.create_default_context() # https://github.com/encode/httpx/issues/838
_CALLBACK_STEP_API_URL_PATTERN = re.compile(
(
r"^/api/processes/([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})"
r"/callback/([0-9a-zA-Z\-_]+)$"
)
)
def _is_callback_step_endpoint(request: Request) -> bool:
"""Check if the request is a callback step API call."""
return re.match(_CALLBACK_STEP_API_URL_PATTERN, request.url.path) is not None
class InvalidScopeValueError(ValueError):
"""Exception raised for invalid scope values in OIDC."""
......@@ -176,13 +189,13 @@ class OIDCUser(HTTPBearer):
resource_server_secret: str
def __init__(
self,
openid_url: str,
resource_server_id: str,
resource_server_secret: str,
*,
auto_error: bool = True,
scheme_name: str | None = None,
self,
openid_url: str,
resource_server_id: str,
resource_server_secret: str,
*,
auto_error: bool = True,
scheme_name: str | None = None,
):
"""Set up OIDCUser with specified OpenID Connect configurations and credentials."""
super().__init__(auto_error=auto_error)
......@@ -192,7 +205,7 @@ class OIDCUser(HTTPBearer):
self.scheme_name = scheme_name or self.__class__.__name__
async def __call__( # type: ignore[override]
self, request: Request, token: str | None = None
self, request: Request, token: str | None = None
) -> OIDCUserModel | None:
"""Return the OIDC user from OIDC introspect endpoint.
......@@ -219,6 +232,10 @@ class OIDCUser(HTTPBearer):
if not credentials:
return None
token = credentials.credentials
elif _is_callback_step_endpoint(request):
logger.debug("callback step endpoint is called. verification will be done by endpoint itself.",
url=request.url)
return None
intercepted_token = await self.introspect_token(async_request, token)
......@@ -354,11 +371,11 @@ def _evaluate_decision(decision: OPAResult, *, auto_error: bool, **context: dict
def opa_decision(
opa_url: str,
oidc_security: OIDCUser,
*,
auto_error: bool = True,
opa_kwargs: Mapping[str, str] | None = None,
opa_url: str,
oidc_security: OIDCUser,
*,
auto_error: bool = True,
opa_kwargs: Mapping[str, str] | None = None,
) -> Callable[[Request, OIDCUserModel, AsyncClient], Awaitable[bool | None]]:
"""Create a decision function for Open Policy Agent (OPA) authorization checks.
......@@ -379,9 +396,9 @@ def opa_decision(
"""
async def _opa_decision(
request: Request,
user_info: OIDCUserModel = Depends(oidc_security), # noqa: B008
async_request: AsyncClient = Depends(_make_async_client), # noqa: B008
request: Request,
user_info: OIDCUserModel = Depends(oidc_security), # noqa: B008
async_request: AsyncClient = Depends(_make_async_client), # noqa: B008
) -> bool | None:
"""Check OIDCUserModel against the OPA policy.
......@@ -394,6 +411,7 @@ def opa_decision(
user_info: The OIDCUserModel object that will be checked
async_request: The :term:`httpx` client.
"""
return None
if not (oauth2lib_settings.OAUTH2_ACTIVE and oauth2lib_settings.OAUTH2_AUTHORIZATION_ACTIVE):
return None
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment