2323from httpx import AsyncClient , NetworkError
2424from pydantic import BaseModel
2525from starlette .requests import ClientDisconnect , HTTPConnection
26+ from starlette .status import HTTP_403_FORBIDDEN
2627from starlette .websockets import WebSocket
2728from structlog import get_logger
2829
@@ -137,22 +138,18 @@ class IdTokenExtractor(ABC):
137138 """
138139
139140 @abstractmethod
140- async def extract (self , request : Request , auto_error : bool = True ) -> Optional [str ]:
141+ async def extract (self , request : Request ) -> Optional [str ]:
141142 pass
142143
143144
144145class HttpBearerExtractor (IdTokenExtractor ):
145146 """Extracts bearer tokens using FastAPI's HTTPBearer.
146147
147148 Specifically designed for HTTP Authorization header token extraction.
148-
149- By default, if an HTTP Bearer token is not provided in the `Authorization` header,
150- the `extract` method will cancel the request and send an error unless `auto_error`
151- is set to `False`, allowing optional or multiple authentication methods.
152149 """
153150
154- async def extract (self , request : Request , auto_error : bool = True ) -> Optional [str ]:
155- http_bearer = HTTPBearer (auto_error = auto_error )
151+ async def extract (self , request : Request ) -> Optional [str ]:
152+ http_bearer = HTTPBearer (auto_error = False )
156153 credential = await http_bearer (request )
157154
158155 return credential .credentials if credential else None
@@ -218,7 +215,11 @@ async def authenticate(self, request: HTTPConnection, token: Optional[str] = Non
218215 return None
219216
220217 if token is None :
221- token_or_extracted_id_token = await self .id_token_extractor .extract (request , auto_error = True ) or ""
218+ extracted_id_token = await self .id_token_extractor .extract (request )
219+ if not extracted_id_token :
220+ raise HTTPException (status_code = HTTP_403_FORBIDDEN , detail = "Not authenticated" )
221+
222+ token_or_extracted_id_token = extracted_id_token
222223 else :
223224 token_or_extracted_id_token = token
224225
@@ -262,7 +263,7 @@ class Authorization(ABC):
262263 """
263264
264265 @abstractmethod
265- async def authorize (self , request : HTTPConnection , user : OIDCUserModel ) -> Optional [bool ]:
266+ async def authorize (self , request : HTTPConnection , user : Optional [ OIDCUserModel ] = None ) -> Optional [bool ]:
266267 pass
267268
268269
@@ -273,7 +274,7 @@ class GraphqlAuthorization(ABC):
273274 """
274275
275276 @abstractmethod
276- async def authorize (self , request : RequestPath , user : OIDCUserModel ) -> Optional [bool ]:
277+ async def authorize (self , request : RequestPath , user : Optional [ OIDCUserModel ] = None ) -> Optional [bool ]:
277278 pass
278279
279280
@@ -323,7 +324,7 @@ class OPAAuthorization(Authorization, OPAMixin):
323324 Uses OAUTH2 settings and request information to authorize actions.
324325 """
325326
326- async def authorize (self , request : HTTPConnection , user_info : OIDCUserModel ) -> Optional [bool ]:
327+ async def authorize (self , request : HTTPConnection , user_info : Optional [ OIDCUserModel ] = None ) -> Optional [bool ]:
327328 if not (oauth2lib_settings .OAUTH2_ACTIVE and oauth2lib_settings .OAUTH2_AUTHORIZATION_ACTIVE ):
328329 return None
329330
@@ -379,7 +380,7 @@ def __init__(self, opa_url: str, auto_error: bool = False, opa_kwargs: Union[Map
379380 # By default don't raise HTTP 403 because partial results are preferred
380381 super ().__init__ (opa_url , auto_error , opa_kwargs )
381382
382- async def authorize (self , request : RequestPath , user_info : OIDCUserModel ) -> Optional [bool ]:
383+ async def authorize (self , request : RequestPath , user_info : Optional [ OIDCUserModel ] = None ) -> Optional [bool ]:
383384 if not (oauth2lib_settings .OAUTH2_ACTIVE and oauth2lib_settings .OAUTH2_AUTHORIZATION_ACTIVE ):
384385 return None
385386
0 commit comments