@@ -151,6 +151,28 @@ pub struct Claims {
151151 pub room_config : Option < livekit_protocol:: RoomConfiguration > ,
152152}
153153
154+ impl Claims {
155+ pub fn with_unverified ( token : & str ) -> Result < Self , AccessTokenError > {
156+ let mut validation = jsonwebtoken:: Validation :: new ( jsonwebtoken:: Algorithm :: HS256 ) ;
157+ validation. validate_exp = true ;
158+ #[ cfg( test) ]
159+ {
160+ validation. validate_exp = false ;
161+ }
162+ validation. validate_nbf = true ;
163+ validation. set_required_spec_claims :: < String > ( & [ ] ) ;
164+ validation. insecure_disable_signature_validation ( ) ;
165+
166+ let token = jsonwebtoken:: decode :: < Claims > (
167+ token,
168+ & DecodingKey :: from_secret ( & [ ] ) ,
169+ & validation,
170+ ) ?;
171+
172+ Ok ( token. claims )
173+ }
174+ }
175+
154176#[ derive( Clone ) ]
155177pub struct AccessToken {
156178 api_key : String ,
@@ -320,7 +342,7 @@ impl TokenVerifier {
320342mod tests {
321343 use std:: time:: Duration ;
322344
323- use super :: { AccessToken , TokenVerifier , VideoGrants } ;
345+ use super :: { AccessToken , Claims , TokenVerifier , VideoGrants } ;
324346
325347 const TEST_API_KEY : & str = "myapikey" ;
326348 const TEST_API_SECRET : & str = "thiskeyistotallyunsafe" ;
@@ -383,4 +405,44 @@ mod tests {
383405 claims
384406 ) ;
385407 }
408+
409+ #[ test]
410+ fn test_unverified_token ( ) {
411+ let claims = Claims :: with_unverified ( TEST_TOKEN ) . expect ( "Failed to parse token" ) ;
412+
413+ assert_eq ! ( claims. sub, "identity" ) ;
414+ assert_eq ! ( claims. name, "name" ) ;
415+ assert_eq ! ( claims. iss, TEST_API_KEY ) ;
416+ assert_eq ! (
417+ claims. room_config,
418+ Some ( livekit_protocol:: RoomConfiguration {
419+ agents: vec![ livekit_protocol:: RoomAgentDispatch {
420+ agent_name: "test-agent" . to_string( ) ,
421+ metadata: "test-metadata" . to_string( ) ,
422+ } ] ,
423+ ..Default :: default ( )
424+ } )
425+ ) ;
426+
427+ let token = AccessToken :: with_api_key ( TEST_API_KEY , TEST_API_SECRET )
428+ . with_ttl ( Duration :: from_secs ( 60 ) )
429+ . with_identity ( "test" )
430+ . with_name ( "test" )
431+ . with_grants ( VideoGrants { room_join : true , room : "test-room" . to_string ( ) , ..Default :: default ( ) } )
432+ . to_jwt ( )
433+ . unwrap ( ) ;
434+
435+ let claims = Claims :: with_unverified ( & token) . expect ( "Failed to parse fresh token" ) ;
436+ assert_eq ! ( claims. sub, "test" ) ;
437+ assert_eq ! ( claims. name, "test" ) ;
438+ assert_eq ! ( claims. video. room, "test-room" ) ;
439+ assert ! ( claims. video. room_join) ;
440+
441+ let parts: Vec < & str > = token. split ( '.' ) . collect ( ) ;
442+ let malformed_token = format ! ( "{}.{}.wrongsignature" , parts[ 0 ] , parts[ 1 ] ) ;
443+
444+ let claims = Claims :: with_unverified ( & malformed_token) . expect ( "Failed to parse token with wrong signature" ) ;
445+ assert_eq ! ( claims. sub, "test" ) ;
446+ assert_eq ! ( claims. name, "test" ) ;
447+ }
386448}
0 commit comments