C#生成LiveKit JWT Token无效问题求助
解决C#生成LiveKit JWT Token时video claim为字符串的问题
问题根源
LiveKit的JWT要求video、audio这类权限Claim是JSON对象类型(例如{"canPublish": true, "canSubscribe": true}),但C#默认的Claim构造器仅支持字符串值,直接将对象序列化后存入Claim会导致JWT解码后该字段为字符串而非对象,最终Token无效。
解决方案:直接构造JWT Payload而非依赖默认Claim系统
绕过默认Claim只能存字符串的限制,手动构造包含对象类型字段的Payload,让JWT库直接将其序列化为JSON对象。
方法1:使用Dictionary<string, object>构造Payload
这种方式最直接,JWT库会自动将对象类型的值序列化为JSON对象:
using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Text; using Microsoft.IdentityModel.Tokens; public string GenerateLiveKitToken(string apiKey, string apiSecret, string roomName, string identity) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(apiSecret)); var signingCreds = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); // 构造包含对象类型权限的Payload var payload = new Dictionary<string, object> { ["iss"] = apiKey, ["sub"] = identity, ["room"] = roomName, ["exp"] = DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds(), // video字段直接用匿名对象,JWT库会序列化为JSON对象 ["video"] = new { canPublish = true, canSubscribe = true, canPublishSources = new[] { "camera", "screen" } }, ["audio"] = new { canPublish = true, canSubscribe = true } }; var token = new JwtSecurityToken( issuer: apiKey, payload: payload, expires: DateTime.UtcNow.AddHours(1), signingCredentials: signingCreds ); return new JwtSecurityTokenHandler().WriteToken(token); }
方法2:使用JObject构造Payload(适合复杂场景)
如果需要更灵活的JSON结构(比如动态添加字段),可以用Newtonsoft.Json的JObject:
using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Text; using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json.Linq; public string GenerateLiveKitToken(string apiKey, string apiSecret, string roomName, string identity) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(apiSecret)); var signingCreds = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var payload = new JObject { ["iss"] = apiKey, ["sub"] = identity, ["room"] = roomName, ["exp"] = DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds(), ["video"] = new JObject { ["canPublish"] = true, ["canSubscribe"] = true, ["canPublishSources"] = new JArray("camera", "screen") } }; // 将JObject转换为Claim列表,指定JSON类型 var claims = new List<System.Security.Claims.Claim>(); foreach (var prop in payload.Properties()) { var valueType = prop.Value.Type switch { JTokenType.Object or JTokenType.Array => "json", _ => null }; claims.Add(new System.Security.Claims.Claim(prop.Name, prop.Value.ToString(), valueType)); } var token = new JwtSecurityToken( issuer: apiKey, claims: claims, expires: DateTime.UtcNow.AddHours(1), signingCredentials: signingCreds ); return new JwtSecurityTokenHandler().WriteToken(token); }
关键注意事项
- 确保安装了必要的NuGet包:
System.IdentityModel.Tokens.Jwt(必选)、Newtonsoft.Json(方法2需要) - 权限字段的命名和大小写要严格符合LiveKit的要求,比如
canPublish、canSubscribe不能写错 - 过期时间
exp必须是Unix时间戳(或用DateTime类型让库自动转换),否则Token会被判定为无效
内容的提问来源于stack exchange,提问作者Diego Satizabal
相关产品推荐
相关产品推荐

