@@ -233,14 +233,26 @@ def verify(self, token: str, *, verify_signature: bool = True) -> Claims:
233233 if verify_signature and (not self .api_key or not self .api_secret ):
234234 raise ValueError ("api_key and api_secret must be set" )
235235
236- claims = jwt .decode (
237- token ,
238- key = self .api_secret or "" ,
239- issuer = self .api_key or "" ,
240- algorithms = ["HS256" ],
241- leeway = self ._leeway .total_seconds (),
242- options = {"verify_signature" : verify_signature },
243- )
236+ # First-party minters always set exp. Without this, a hand-rolled token
237+ # with a valid signature and no exp verifies forever (livekit/protocol#1706).
238+ if verify_signature :
239+ claims = jwt .decode (
240+ token ,
241+ key = self .api_secret or "" ,
242+ issuer = self .api_key or "" ,
243+ algorithms = ["HS256" ],
244+ leeway = self ._leeway .total_seconds (),
245+ options = {"verify_signature" : True , "require" : ["exp" ]},
246+ )
247+ else :
248+ claims = jwt .decode (
249+ token ,
250+ key = self .api_secret or "" ,
251+ issuer = self .api_key or "" ,
252+ algorithms = ["HS256" ],
253+ leeway = self ._leeway .total_seconds (),
254+ options = {"verify_signature" : False },
255+ )
244256 video_dict = claims .get ("video" , dict ())
245257 video_dict = {camel_to_snake (k ): v for k , v in video_dict .items ()}
246258 video_dict = {k : v for k , v in video_dict .items () if k in VideoGrants .__dataclass_fields__ }
0 commit comments