WIP: Update token module to support server api

Nathan Sobo created

Change summary

crates/capture/src/main.rs                    | 21 ++++++-
crates/live_kit_server/Cargo.toml             |  2 
crates/live_kit_server/src/api.rs             |  2 
crates/live_kit_server/src/live_kit_server.rs |  4 
crates/live_kit_server/src/token.rs           | 52 ++++++++++----------
5 files changed, 47 insertions(+), 34 deletions(-)

Detailed changes

crates/capture/src/main.rs 🔗

@@ -39,8 +39,14 @@ fn main() {
             let user1_token = live_kit_server::token::create(
                 &live_kit_key,
                 &live_kit_secret,
-                "test-room",
-                "test-participant-1",
+                Some("test-participant-1"),
+                live_kit_server::token::VideoGrant {
+                    room: Some("test-room"),
+                    room_join: Some(true),
+                    can_publish: Some(true),
+                    can_subscribe: Some(true),
+                    ..Default::default()
+                },
             )
             .unwrap();
             let room1 = Room::new();
@@ -49,10 +55,17 @@ fn main() {
             let user2_token = live_kit_server::token::create(
                 &live_kit_key,
                 &live_kit_secret,
-                "test-room",
-                "test-participant-2",
+                Some("test-participant-2"),
+                live_kit_server::token::VideoGrant {
+                    room: Some("test-room"),
+                    room_join: Some(true),
+                    can_publish: Some(true),
+                    can_subscribe: Some(true),
+                    ..Default::default()
+                },
             )
             .unwrap();
+
             let room2 = Room::new();
             room2.connect(&live_kit_url, &user2_token).await.unwrap();
             cx.add_window(Default::default(), |cx| ScreenCaptureView::new(room2, cx));

crates/live_kit_server/Cargo.toml 🔗

@@ -12,7 +12,7 @@ doctest = false
 anyhow = "1.0.38"
 hmac = "0.12"
 jwt = "0.16"
-hyper = "0.14"
+hyper = { version = "0.14", features = ["client", "http1"] }
 prost = "0.8"
 prost-types = "0.8"
 serde = { version = "1.0", features = ["derive", "rc"] }

crates/live_kit_server/src/api.rs 🔗

@@ -31,6 +31,6 @@ impl Client {
             .build();
 
         // token::create(api_key, secret_key, room_name, participant_name)
-        self.http.request(req)
+        // self.http.request(req)
     }
 }

crates/live_kit_server/src/token.rs 🔗

@@ -1,4 +1,4 @@
-use anyhow::Result;
+use anyhow::{anyhow, Result};
 use hmac::{Hmac, Mac};
 use jwt::SignWithKey;
 use serde::Serialize;
@@ -14,43 +14,49 @@ static DEFAULT_TTL: Duration = Duration::from_secs(6 * 60 * 60); // 6 hours
 #[serde(rename_all = "camelCase")]
 struct ClaimGrants<'a> {
     iss: &'a str,
-    sub: &'a str,
+    sub: Option<&'a str>,
     iat: u64,
     exp: u64,
     nbf: u64,
-    jwtid: &'a str,
+    jwtid: Option<&'a str>,
     video: VideoGrant<'a>,
 }
 
 #[derive(Default, Serialize)]
 #[serde(rename_all = "camelCase")]
-struct VideoGrant<'a> {
-    room_create: Option<bool>,
-    room_join: Option<bool>,
-    room_list: Option<bool>,
-    room_record: Option<bool>,
-    room_admin: Option<bool>,
-    room: Option<&'a str>,
-    can_publish: Option<bool>,
-    can_subscribe: Option<bool>,
-    can_publish_data: Option<bool>,
-    hidden: Option<bool>,
-    recorder: Option<bool>,
+pub struct VideoGrant<'a> {
+    pub room_create: Option<bool>,
+    pub room_join: Option<bool>,
+    pub room_list: Option<bool>,
+    pub room_record: Option<bool>,
+    pub room_admin: Option<bool>,
+    pub room: Option<&'a str>,
+    pub can_publish: Option<bool>,
+    pub can_subscribe: Option<bool>,
+    pub can_publish_data: Option<bool>,
+    pub hidden: Option<bool>,
+    pub recorder: Option<bool>,
 }
 
 pub fn create(
     api_key: &str,
     secret_key: &str,
-    room_name: &str,
-    participant_name: &str,
+    identity: Option<&str>,
+    video_grant: VideoGrant,
 ) -> Result<String> {
+    if video_grant.room_join.is_some() && identity.is_none() {
+        Err(anyhow!(
+            "identity is required for room_join grant, but it is none"
+        ))?;
+    }
+
     let secret_key: Hmac<Sha256> = Hmac::new_from_slice(secret_key.as_bytes())?;
 
     let now = SystemTime::now();
 
     let claims = ClaimGrants {
         iss: api_key,
-        sub: participant_name,
+        sub: identity,
         iat: now.duration_since(UNIX_EPOCH).unwrap().as_secs(),
         exp: now
             .add(DEFAULT_TTL)
@@ -58,14 +64,8 @@ pub fn create(
             .unwrap()
             .as_secs(),
         nbf: 0,
-        jwtid: participant_name,
-        video: VideoGrant {
-            room: Some(room_name),
-            room_join: Some(true),
-            can_publish: Some(true),
-            can_subscribe: Some(true),
-            ..Default::default()
-        },
+        jwtid: identity,
+        video: video_grant,
     };
     Ok(claims.sign_with_key(&secret_key)?)
 }