@@ -531,6 +531,50 @@ class AuthInfo(BaseModel):
531531 api_key_info : Optional [APIKey ] = None
532532
533533
534+ def is_device_public (device_id : str ) -> bool :
535+ """
536+ Check if a device is public (doesn't require authentication).
537+ """
538+ device_id_part , device_name = get_device_parts (device_id )
539+ api_keys , owner = get_api_keys_by_device_id (device_id )
540+
541+ if len (api_keys ) == 0 :
542+ # No API keys found - device doesn't exist or is not configured
543+ return False
544+
545+ # Check if any API key for this device is marked as public (private_data=False)
546+ for api_key in api_keys :
547+ if api_key .device_id == device_id_part and api_key .device_name == device_name :
548+ if not api_key .private_data :
549+ return True
550+
551+ return False
552+
553+
554+ async def flexible_auth_optional (
555+ fief_user : Optional [FiefUserInfo ] = Depends (get_cached_fief_user_optional ()),
556+ api_key : Optional [str ] = Header (None , alias = "X-API-Key" ),
557+ ) -> Optional [AuthInfo ]:
558+ """
559+ Optional flexible authentication that accepts either Fief tokens or device API keys.
560+ Returns None if no authentication is provided (for public device access).
561+ """
562+ if fief_user :
563+ # Fief token authentication (now cached)
564+ return AuthInfo (auth_type = "fief" , fief_user = fief_user )
565+ elif api_key :
566+ # API key authentication
567+ user_and_key = get_user_by_api_key (api_key )
568+ if user_and_key is None :
569+ raise HTTPException (status_code = 403 , detail = "Invalid API key" )
570+
571+ user , api_key_info = user_and_key
572+ return AuthInfo (auth_type = "api_key" , user = user , api_key_info = api_key_info )
573+ else :
574+ # No authentication provided - this is OK for public devices
575+ return None
576+
577+
534578async def flexible_auth (
535579 fief_user : Optional [FiefUserInfo ] = Depends (get_cached_fief_user_optional ()),
536580 api_key : Optional [str ] = Header (None , alias = "X-API-Key" ),
@@ -554,10 +598,19 @@ async def flexible_auth(
554598 raise HTTPException (status_code = 401 , detail = "Authentication required" )
555599
556600
557- def validate_device_access_flexible (auth_info : AuthInfo , device_id : str ) -> bool :
601+ def validate_device_access_flexible (auth_info : Optional [ AuthInfo ] , device_id : str ) -> bool :
558602 """
559603 Validate device access for flexible authentication.
604+ Handles public devices (no auth required) and private devices (auth required).
560605 """
606+ # First check if the device is public
607+ if is_device_public (device_id ):
608+ return True
609+
610+ # Device is private, authentication is required
611+ if auth_info is None :
612+ return False
613+
561614 if auth_info .auth_type == "fief" :
562615 # Use existing Fief-based validation
563616 return device_id_is_allowed_for_user (device_id , user = auth_info .fief_user )
0 commit comments