livekit-server-sdk 2.8.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/AccessToken.cjs +169 -0
- package/dist/AccessToken.cjs.map +1 -0
- package/dist/AccessToken.js +130 -137
- package/dist/AccessToken.js.map +1 -1
- package/dist/AccessToken.test.cjs +147 -0
- package/dist/AccessToken.test.cjs.map +1 -0
- package/dist/AccessToken.test.js +129 -0
- package/dist/AccessToken.test.js.map +1 -0
- package/dist/AgentDispatchClient.cjs +133 -0
- package/dist/AgentDispatchClient.cjs.map +1 -0
- package/dist/AgentDispatchClient.d.ts +1 -1
- package/dist/AgentDispatchClient.d.ts.map +1 -1
- package/dist/AgentDispatchClient.js +102 -79
- package/dist/AgentDispatchClient.js.map +1 -1
- package/dist/EgressClient.cjs +381 -0
- package/dist/EgressClient.cjs.map +1 -0
- package/dist/EgressClient.js +349 -288
- package/dist/EgressClient.js.map +1 -1
- package/dist/IngressClient.cjs +164 -0
- package/dist/IngressClient.cjs.map +1 -0
- package/dist/IngressClient.js +131 -106
- package/dist/IngressClient.js.map +1 -1
- package/dist/RoomServiceClient.cjs +240 -0
- package/dist/RoomServiceClient.cjs.map +1 -0
- package/dist/RoomServiceClient.js +219 -151
- package/dist/RoomServiceClient.js.map +1 -1
- package/dist/ServiceBase.cjs +49 -0
- package/dist/ServiceBase.cjs.map +1 -0
- package/dist/ServiceBase.js +25 -28
- package/dist/ServiceBase.js.map +1 -1
- package/dist/SipClient.cjs +379 -0
- package/dist/SipClient.cjs.map +1 -0
- package/dist/SipClient.d.ts +15 -0
- package/dist/SipClient.d.ts.map +1 -1
- package/dist/SipClient.js +360 -260
- package/dist/SipClient.js.map +1 -1
- package/dist/TwirpRPC.cjs +71 -0
- package/dist/TwirpRPC.cjs.map +1 -0
- package/dist/TwirpRPC.d.ts.map +1 -1
- package/dist/TwirpRPC.js +32 -29
- package/dist/TwirpRPC.js.map +1 -1
- package/dist/WebhookReceiver.cjs +78 -0
- package/dist/WebhookReceiver.cjs.map +1 -0
- package/dist/WebhookReceiver.js +48 -45
- package/dist/WebhookReceiver.js.map +1 -1
- package/dist/WebhookReceiver.test.cjs +38 -0
- package/dist/WebhookReceiver.test.cjs.map +1 -0
- package/dist/WebhookReceiver.test.js +37 -0
- package/dist/WebhookReceiver.test.js.map +1 -0
- package/dist/grants.cjs +53 -0
- package/dist/grants.cjs.map +1 -0
- package/dist/grants.js +25 -23
- package/dist/grants.js.map +1 -1
- package/dist/grants.test.cjs +27 -0
- package/dist/grants.test.cjs.map +1 -0
- package/dist/grants.test.js +26 -0
- package/dist/grants.test.js.map +1 -0
- package/dist/index.cjs +136 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +104 -12
- package/dist/index.js.map +1 -1
- package/package.json +12 -3
- package/src/AgentDispatchClient.ts +2 -2
- package/src/SipClient.ts +33 -0
- package/src/TwirpRPC.ts +1 -1
package/README.md
CHANGED
|
@@ -120,7 +120,7 @@ svc.deleteRoom('myroom').then(() => {
|
|
|
120
120
|
|
|
121
121
|
## Webhooks
|
|
122
122
|
|
|
123
|
-
The JS SDK also provides helper functions to decode and verify webhook callbacks. While verification is optional, it ensures the authenticity of the message. See [webhooks guide](https://docs.livekit.io/
|
|
123
|
+
The JS SDK also provides helper functions to decode and verify webhook callbacks. While verification is optional, it ensures the authenticity of the message. See [webhooks guide](https://docs.livekit.io/home/server/webhooks/) for details.
|
|
124
124
|
|
|
125
125
|
LiveKit POSTs to webhook endpoints with `Content-Type: application/webhook+json`. Please ensure your server is able to receive POST body with that MIME.
|
|
126
126
|
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var AccessToken_exports = {};
|
|
30
|
+
__export(AccessToken_exports, {
|
|
31
|
+
AccessToken: () => AccessToken,
|
|
32
|
+
TokenVerifier: () => TokenVerifier
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(AccessToken_exports);
|
|
35
|
+
var jose = __toESM(require("jose"), 1);
|
|
36
|
+
var import_grants = require("./grants.cjs");
|
|
37
|
+
const defaultTTL = `6h`;
|
|
38
|
+
class AccessToken {
|
|
39
|
+
/**
|
|
40
|
+
* Creates a new AccessToken
|
|
41
|
+
* @param apiKey - API Key, can be set in env LIVEKIT_API_KEY
|
|
42
|
+
* @param apiSecret - Secret, can be set in env LIVEKIT_API_SECRET
|
|
43
|
+
*/
|
|
44
|
+
constructor(apiKey, apiSecret, options) {
|
|
45
|
+
if (!apiKey) {
|
|
46
|
+
apiKey = process.env.LIVEKIT_API_KEY;
|
|
47
|
+
}
|
|
48
|
+
if (!apiSecret) {
|
|
49
|
+
apiSecret = process.env.LIVEKIT_API_SECRET;
|
|
50
|
+
}
|
|
51
|
+
if (!apiKey || !apiSecret) {
|
|
52
|
+
throw Error("api-key and api-secret must be set");
|
|
53
|
+
} else if (typeof document !== "undefined") {
|
|
54
|
+
console.error(
|
|
55
|
+
"You should not include your API secret in your web client bundle.\n\nYour web client should request a token from your backend server which should then use the API secret to generate a token. See https://docs.livekit.io/client/connect/"
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
this.apiKey = apiKey;
|
|
59
|
+
this.apiSecret = apiSecret;
|
|
60
|
+
this.grants = {};
|
|
61
|
+
this.identity = options == null ? void 0 : options.identity;
|
|
62
|
+
this.ttl = (options == null ? void 0 : options.ttl) || defaultTTL;
|
|
63
|
+
if (typeof this.ttl === "number") {
|
|
64
|
+
this.ttl = `${this.ttl}s`;
|
|
65
|
+
}
|
|
66
|
+
if (options == null ? void 0 : options.metadata) {
|
|
67
|
+
this.metadata = options.metadata;
|
|
68
|
+
}
|
|
69
|
+
if (options == null ? void 0 : options.attributes) {
|
|
70
|
+
this.attributes = options.attributes;
|
|
71
|
+
}
|
|
72
|
+
if (options == null ? void 0 : options.name) {
|
|
73
|
+
this.name = options.name;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Adds a video grant to this token.
|
|
78
|
+
* @param grant -
|
|
79
|
+
*/
|
|
80
|
+
addGrant(grant) {
|
|
81
|
+
this.grants.video = { ...this.grants.video ?? {}, ...grant };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Adds a SIP grant to this token.
|
|
85
|
+
* @param grant -
|
|
86
|
+
*/
|
|
87
|
+
addSIPGrant(grant) {
|
|
88
|
+
this.grants.sip = { ...this.grants.sip ?? {}, ...grant };
|
|
89
|
+
}
|
|
90
|
+
get name() {
|
|
91
|
+
return this.grants.name;
|
|
92
|
+
}
|
|
93
|
+
set name(name) {
|
|
94
|
+
this.grants.name = name;
|
|
95
|
+
}
|
|
96
|
+
get metadata() {
|
|
97
|
+
return this.grants.metadata;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Set metadata to be passed to the Participant, used only when joining the room
|
|
101
|
+
*/
|
|
102
|
+
set metadata(md) {
|
|
103
|
+
this.grants.metadata = md;
|
|
104
|
+
}
|
|
105
|
+
get attributes() {
|
|
106
|
+
return this.grants.attributes;
|
|
107
|
+
}
|
|
108
|
+
set attributes(attrs) {
|
|
109
|
+
this.grants.attributes = attrs;
|
|
110
|
+
}
|
|
111
|
+
get kind() {
|
|
112
|
+
return this.grants.kind;
|
|
113
|
+
}
|
|
114
|
+
set kind(kind) {
|
|
115
|
+
this.grants.kind = kind;
|
|
116
|
+
}
|
|
117
|
+
get sha256() {
|
|
118
|
+
return this.grants.sha256;
|
|
119
|
+
}
|
|
120
|
+
set sha256(sha) {
|
|
121
|
+
this.grants.sha256 = sha;
|
|
122
|
+
}
|
|
123
|
+
get roomPreset() {
|
|
124
|
+
return this.grants.roomPreset;
|
|
125
|
+
}
|
|
126
|
+
set roomPreset(preset) {
|
|
127
|
+
this.grants.roomPreset = preset;
|
|
128
|
+
}
|
|
129
|
+
get roomConfig() {
|
|
130
|
+
return this.grants.roomConfig;
|
|
131
|
+
}
|
|
132
|
+
set roomConfig(config) {
|
|
133
|
+
this.grants.roomConfig = config;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* @returns JWT encoded token
|
|
137
|
+
*/
|
|
138
|
+
async toJwt() {
|
|
139
|
+
var _a;
|
|
140
|
+
const secret = new TextEncoder().encode(this.apiSecret);
|
|
141
|
+
const jwt = new jose.SignJWT((0, import_grants.claimsToJwtPayload)(this.grants)).setProtectedHeader({ alg: "HS256" }).setIssuer(this.apiKey).setExpirationTime(this.ttl).setNotBefore(0);
|
|
142
|
+
if (this.identity) {
|
|
143
|
+
jwt.setSubject(this.identity);
|
|
144
|
+
} else if ((_a = this.grants.video) == null ? void 0 : _a.roomJoin) {
|
|
145
|
+
throw Error("identity is required for join but not set");
|
|
146
|
+
}
|
|
147
|
+
return jwt.sign(secret);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
class TokenVerifier {
|
|
151
|
+
constructor(apiKey, apiSecret) {
|
|
152
|
+
this.apiKey = apiKey;
|
|
153
|
+
this.apiSecret = apiSecret;
|
|
154
|
+
}
|
|
155
|
+
async verify(token) {
|
|
156
|
+
const secret = new TextEncoder().encode(this.apiSecret);
|
|
157
|
+
const { payload } = await jose.jwtVerify(token, secret, { issuer: this.apiKey });
|
|
158
|
+
if (!payload) {
|
|
159
|
+
throw Error("invalid token");
|
|
160
|
+
}
|
|
161
|
+
return payload;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
165
|
+
0 && (module.exports = {
|
|
166
|
+
AccessToken,
|
|
167
|
+
TokenVerifier
|
|
168
|
+
});
|
|
169
|
+
//# sourceMappingURL=AccessToken.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/AccessToken.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { RoomConfiguration } from '@livekit/protocol';\nimport * as jose from 'jose';\nimport type { ClaimGrants, SIPGrant, VideoGrant } from './grants.js';\nimport { claimsToJwtPayload } from './grants.js';\n\n// 6 hours\nconst defaultTTL = `6h`;\n\nexport interface AccessTokenOptions {\n /**\n * amount of time before expiration\n * expressed in seconds or a string describing a time span zeit/ms.\n * eg: '2 days', '10h', or seconds as numeric value\n */\n ttl?: number | string;\n\n /**\n * display name for the participant, available as `Participant.name`\n */\n name?: string;\n\n /**\n * identity of the user, required for room join tokens\n */\n identity?: string;\n\n /**\n * custom metadata to be passed to participants\n */\n metadata?: string;\n\n /**\n * custom attributes to be passed to participants\n */\n attributes?: Record<string, string>;\n}\n\nexport class AccessToken {\n private apiKey: string;\n\n private apiSecret: string;\n\n private grants: ClaimGrants;\n\n identity?: string;\n\n ttl: number | string;\n\n /**\n * Creates a new AccessToken\n * @param apiKey - API Key, can be set in env LIVEKIT_API_KEY\n * @param apiSecret - Secret, can be set in env LIVEKIT_API_SECRET\n */\n constructor(apiKey?: string, apiSecret?: string, options?: AccessTokenOptions) {\n if (!apiKey) {\n apiKey = process.env.LIVEKIT_API_KEY;\n }\n if (!apiSecret) {\n apiSecret = process.env.LIVEKIT_API_SECRET;\n }\n if (!apiKey || !apiSecret) {\n throw Error('api-key and api-secret must be set');\n } else if (typeof document !== 'undefined') {\n // check against document rather than window because deno provides window\n console.error(\n 'You should not include your API secret in your web client bundle.\\n\\n' +\n 'Your web client should request a token from your backend server which should then use ' +\n 'the API secret to generate a token. See https://docs.livekit.io/client/connect/',\n );\n }\n this.apiKey = apiKey;\n this.apiSecret = apiSecret;\n this.grants = {};\n this.identity = options?.identity;\n this.ttl = options?.ttl || defaultTTL;\n if (typeof this.ttl === 'number') {\n this.ttl = `${this.ttl}s`;\n }\n if (options?.metadata) {\n this.metadata = options.metadata;\n }\n if (options?.attributes) {\n this.attributes = options.attributes;\n }\n if (options?.name) {\n this.name = options.name;\n }\n }\n\n /**\n * Adds a video grant to this token.\n * @param grant -\n */\n addGrant(grant: VideoGrant) {\n this.grants.video = { ...(this.grants.video ?? {}), ...grant };\n }\n\n /**\n * Adds a SIP grant to this token.\n * @param grant -\n */\n addSIPGrant(grant: SIPGrant) {\n this.grants.sip = { ...(this.grants.sip ?? {}), ...grant };\n }\n\n get name(): string | undefined {\n return this.grants.name;\n }\n\n set name(name: string) {\n this.grants.name = name;\n }\n\n get metadata(): string | undefined {\n return this.grants.metadata;\n }\n\n /**\n * Set metadata to be passed to the Participant, used only when joining the room\n */\n set metadata(md: string) {\n this.grants.metadata = md;\n }\n\n get attributes(): Record<string, string> | undefined {\n return this.grants.attributes;\n }\n\n set attributes(attrs: Record<string, string>) {\n this.grants.attributes = attrs;\n }\n\n get kind(): string | undefined {\n return this.grants.kind;\n }\n\n set kind(kind: string) {\n this.grants.kind = kind;\n }\n\n get sha256(): string | undefined {\n return this.grants.sha256;\n }\n\n set sha256(sha: string | undefined) {\n this.grants.sha256 = sha;\n }\n\n get roomPreset(): string | undefined {\n return this.grants.roomPreset;\n }\n\n set roomPreset(preset: string | undefined) {\n this.grants.roomPreset = preset;\n }\n\n get roomConfig(): RoomConfiguration | undefined {\n return this.grants.roomConfig;\n }\n\n set roomConfig(config: RoomConfiguration | undefined) {\n this.grants.roomConfig = config;\n }\n\n /**\n * @returns JWT encoded token\n */\n async toJwt(): Promise<string> {\n // TODO: check for video grant validity\n\n const secret = new TextEncoder().encode(this.apiSecret);\n\n const jwt = new jose.SignJWT(claimsToJwtPayload(this.grants))\n .setProtectedHeader({ alg: 'HS256' })\n .setIssuer(this.apiKey)\n .setExpirationTime(this.ttl)\n .setNotBefore(0);\n if (this.identity) {\n jwt.setSubject(this.identity);\n } else if (this.grants.video?.roomJoin) {\n throw Error('identity is required for join but not set');\n }\n return jwt.sign(secret);\n }\n}\n\nexport class TokenVerifier {\n private apiKey: string;\n\n private apiSecret: string;\n\n constructor(apiKey: string, apiSecret: string) {\n this.apiKey = apiKey;\n this.apiSecret = apiSecret;\n }\n\n async verify(token: string): Promise<ClaimGrants> {\n const secret = new TextEncoder().encode(this.apiSecret);\n const { payload } = await jose.jwtVerify(token, secret, { issuer: this.apiKey });\n if (!payload) {\n throw Error('invalid token');\n }\n\n return payload as ClaimGrants;\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/AccessToken.js
CHANGED
|
@@ -1,141 +1,134 @@
|
|
|
1
|
-
import * as jose from
|
|
2
|
-
import { claimsToJwtPayload } from
|
|
3
|
-
// 6 hours
|
|
1
|
+
import * as jose from "jose";
|
|
2
|
+
import { claimsToJwtPayload } from "./grants.js";
|
|
4
3
|
const defaultTTL = `6h`;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
.setExpirationTime(this.ttl)
|
|
117
|
-
.setNotBefore(0);
|
|
118
|
-
if (this.identity) {
|
|
119
|
-
jwt.setSubject(this.identity);
|
|
120
|
-
}
|
|
121
|
-
else if ((_a = this.grants.video) === null || _a === void 0 ? void 0 : _a.roomJoin) {
|
|
122
|
-
throw Error('identity is required for join but not set');
|
|
123
|
-
}
|
|
124
|
-
return jwt.sign(secret);
|
|
125
|
-
}
|
|
4
|
+
class AccessToken {
|
|
5
|
+
/**
|
|
6
|
+
* Creates a new AccessToken
|
|
7
|
+
* @param apiKey - API Key, can be set in env LIVEKIT_API_KEY
|
|
8
|
+
* @param apiSecret - Secret, can be set in env LIVEKIT_API_SECRET
|
|
9
|
+
*/
|
|
10
|
+
constructor(apiKey, apiSecret, options) {
|
|
11
|
+
if (!apiKey) {
|
|
12
|
+
apiKey = process.env.LIVEKIT_API_KEY;
|
|
13
|
+
}
|
|
14
|
+
if (!apiSecret) {
|
|
15
|
+
apiSecret = process.env.LIVEKIT_API_SECRET;
|
|
16
|
+
}
|
|
17
|
+
if (!apiKey || !apiSecret) {
|
|
18
|
+
throw Error("api-key and api-secret must be set");
|
|
19
|
+
} else if (typeof document !== "undefined") {
|
|
20
|
+
console.error(
|
|
21
|
+
"You should not include your API secret in your web client bundle.\n\nYour web client should request a token from your backend server which should then use the API secret to generate a token. See https://docs.livekit.io/client/connect/"
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
this.apiKey = apiKey;
|
|
25
|
+
this.apiSecret = apiSecret;
|
|
26
|
+
this.grants = {};
|
|
27
|
+
this.identity = options == null ? void 0 : options.identity;
|
|
28
|
+
this.ttl = (options == null ? void 0 : options.ttl) || defaultTTL;
|
|
29
|
+
if (typeof this.ttl === "number") {
|
|
30
|
+
this.ttl = `${this.ttl}s`;
|
|
31
|
+
}
|
|
32
|
+
if (options == null ? void 0 : options.metadata) {
|
|
33
|
+
this.metadata = options.metadata;
|
|
34
|
+
}
|
|
35
|
+
if (options == null ? void 0 : options.attributes) {
|
|
36
|
+
this.attributes = options.attributes;
|
|
37
|
+
}
|
|
38
|
+
if (options == null ? void 0 : options.name) {
|
|
39
|
+
this.name = options.name;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Adds a video grant to this token.
|
|
44
|
+
* @param grant -
|
|
45
|
+
*/
|
|
46
|
+
addGrant(grant) {
|
|
47
|
+
this.grants.video = { ...this.grants.video ?? {}, ...grant };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Adds a SIP grant to this token.
|
|
51
|
+
* @param grant -
|
|
52
|
+
*/
|
|
53
|
+
addSIPGrant(grant) {
|
|
54
|
+
this.grants.sip = { ...this.grants.sip ?? {}, ...grant };
|
|
55
|
+
}
|
|
56
|
+
get name() {
|
|
57
|
+
return this.grants.name;
|
|
58
|
+
}
|
|
59
|
+
set name(name) {
|
|
60
|
+
this.grants.name = name;
|
|
61
|
+
}
|
|
62
|
+
get metadata() {
|
|
63
|
+
return this.grants.metadata;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Set metadata to be passed to the Participant, used only when joining the room
|
|
67
|
+
*/
|
|
68
|
+
set metadata(md) {
|
|
69
|
+
this.grants.metadata = md;
|
|
70
|
+
}
|
|
71
|
+
get attributes() {
|
|
72
|
+
return this.grants.attributes;
|
|
73
|
+
}
|
|
74
|
+
set attributes(attrs) {
|
|
75
|
+
this.grants.attributes = attrs;
|
|
76
|
+
}
|
|
77
|
+
get kind() {
|
|
78
|
+
return this.grants.kind;
|
|
79
|
+
}
|
|
80
|
+
set kind(kind) {
|
|
81
|
+
this.grants.kind = kind;
|
|
82
|
+
}
|
|
83
|
+
get sha256() {
|
|
84
|
+
return this.grants.sha256;
|
|
85
|
+
}
|
|
86
|
+
set sha256(sha) {
|
|
87
|
+
this.grants.sha256 = sha;
|
|
88
|
+
}
|
|
89
|
+
get roomPreset() {
|
|
90
|
+
return this.grants.roomPreset;
|
|
91
|
+
}
|
|
92
|
+
set roomPreset(preset) {
|
|
93
|
+
this.grants.roomPreset = preset;
|
|
94
|
+
}
|
|
95
|
+
get roomConfig() {
|
|
96
|
+
return this.grants.roomConfig;
|
|
97
|
+
}
|
|
98
|
+
set roomConfig(config) {
|
|
99
|
+
this.grants.roomConfig = config;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* @returns JWT encoded token
|
|
103
|
+
*/
|
|
104
|
+
async toJwt() {
|
|
105
|
+
var _a;
|
|
106
|
+
const secret = new TextEncoder().encode(this.apiSecret);
|
|
107
|
+
const jwt = new jose.SignJWT(claimsToJwtPayload(this.grants)).setProtectedHeader({ alg: "HS256" }).setIssuer(this.apiKey).setExpirationTime(this.ttl).setNotBefore(0);
|
|
108
|
+
if (this.identity) {
|
|
109
|
+
jwt.setSubject(this.identity);
|
|
110
|
+
} else if ((_a = this.grants.video) == null ? void 0 : _a.roomJoin) {
|
|
111
|
+
throw Error("identity is required for join but not set");
|
|
112
|
+
}
|
|
113
|
+
return jwt.sign(secret);
|
|
114
|
+
}
|
|
126
115
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
116
|
+
class TokenVerifier {
|
|
117
|
+
constructor(apiKey, apiSecret) {
|
|
118
|
+
this.apiKey = apiKey;
|
|
119
|
+
this.apiSecret = apiSecret;
|
|
120
|
+
}
|
|
121
|
+
async verify(token) {
|
|
122
|
+
const secret = new TextEncoder().encode(this.apiSecret);
|
|
123
|
+
const { payload } = await jose.jwtVerify(token, secret, { issuer: this.apiKey });
|
|
124
|
+
if (!payload) {
|
|
125
|
+
throw Error("invalid token");
|
|
126
|
+
}
|
|
127
|
+
return payload;
|
|
128
|
+
}
|
|
140
129
|
}
|
|
130
|
+
export {
|
|
131
|
+
AccessToken,
|
|
132
|
+
TokenVerifier
|
|
133
|
+
};
|
|
141
134
|
//# sourceMappingURL=AccessToken.js.map
|
package/dist/AccessToken.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"sources":["../src/AccessToken.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { RoomConfiguration } from '@livekit/protocol';\nimport * as jose from 'jose';\nimport type { ClaimGrants, SIPGrant, VideoGrant } from './grants.js';\nimport { claimsToJwtPayload } from './grants.js';\n\n// 6 hours\nconst defaultTTL = `6h`;\n\nexport interface AccessTokenOptions {\n /**\n * amount of time before expiration\n * expressed in seconds or a string describing a time span zeit/ms.\n * eg: '2 days', '10h', or seconds as numeric value\n */\n ttl?: number | string;\n\n /**\n * display name for the participant, available as `Participant.name`\n */\n name?: string;\n\n /**\n * identity of the user, required for room join tokens\n */\n identity?: string;\n\n /**\n * custom metadata to be passed to participants\n */\n metadata?: string;\n\n /**\n * custom attributes to be passed to participants\n */\n attributes?: Record<string, string>;\n}\n\nexport class AccessToken {\n private apiKey: string;\n\n private apiSecret: string;\n\n private grants: ClaimGrants;\n\n identity?: string;\n\n ttl: number | string;\n\n /**\n * Creates a new AccessToken\n * @param apiKey - API Key, can be set in env LIVEKIT_API_KEY\n * @param apiSecret - Secret, can be set in env LIVEKIT_API_SECRET\n */\n constructor(apiKey?: string, apiSecret?: string, options?: AccessTokenOptions) {\n if (!apiKey) {\n apiKey = process.env.LIVEKIT_API_KEY;\n }\n if (!apiSecret) {\n apiSecret = process.env.LIVEKIT_API_SECRET;\n }\n if (!apiKey || !apiSecret) {\n throw Error('api-key and api-secret must be set');\n } else if (typeof document !== 'undefined') {\n // check against document rather than window because deno provides window\n console.error(\n 'You should not include your API secret in your web client bundle.\\n\\n' +\n 'Your web client should request a token from your backend server which should then use ' +\n 'the API secret to generate a token. See https://docs.livekit.io/client/connect/',\n );\n }\n this.apiKey = apiKey;\n this.apiSecret = apiSecret;\n this.grants = {};\n this.identity = options?.identity;\n this.ttl = options?.ttl || defaultTTL;\n if (typeof this.ttl === 'number') {\n this.ttl = `${this.ttl}s`;\n }\n if (options?.metadata) {\n this.metadata = options.metadata;\n }\n if (options?.attributes) {\n this.attributes = options.attributes;\n }\n if (options?.name) {\n this.name = options.name;\n }\n }\n\n /**\n * Adds a video grant to this token.\n * @param grant -\n */\n addGrant(grant: VideoGrant) {\n this.grants.video = { ...(this.grants.video ?? {}), ...grant };\n }\n\n /**\n * Adds a SIP grant to this token.\n * @param grant -\n */\n addSIPGrant(grant: SIPGrant) {\n this.grants.sip = { ...(this.grants.sip ?? {}), ...grant };\n }\n\n get name(): string | undefined {\n return this.grants.name;\n }\n\n set name(name: string) {\n this.grants.name = name;\n }\n\n get metadata(): string | undefined {\n return this.grants.metadata;\n }\n\n /**\n * Set metadata to be passed to the Participant, used only when joining the room\n */\n set metadata(md: string) {\n this.grants.metadata = md;\n }\n\n get attributes(): Record<string, string> | undefined {\n return this.grants.attributes;\n }\n\n set attributes(attrs: Record<string, string>) {\n this.grants.attributes = attrs;\n }\n\n get kind(): string | undefined {\n return this.grants.kind;\n }\n\n set kind(kind: string) {\n this.grants.kind = kind;\n }\n\n get sha256(): string | undefined {\n return this.grants.sha256;\n }\n\n set sha256(sha: string | undefined) {\n this.grants.sha256 = sha;\n }\n\n get roomPreset(): string | undefined {\n return this.grants.roomPreset;\n }\n\n set roomPreset(preset: string | undefined) {\n this.grants.roomPreset = preset;\n }\n\n get roomConfig(): RoomConfiguration | undefined {\n return this.grants.roomConfig;\n }\n\n set roomConfig(config: RoomConfiguration | undefined) {\n this.grants.roomConfig = config;\n }\n\n /**\n * @returns JWT encoded token\n */\n async toJwt(): Promise<string> {\n // TODO: check for video grant validity\n\n const secret = new TextEncoder().encode(this.apiSecret);\n\n const jwt = new jose.SignJWT(claimsToJwtPayload(this.grants))\n .setProtectedHeader({ alg: 'HS256' })\n .setIssuer(this.apiKey)\n .setExpirationTime(this.ttl)\n .setNotBefore(0);\n if (this.identity) {\n jwt.setSubject(this.identity);\n } else if (this.grants.video?.roomJoin) {\n throw Error('identity is required for join but not set');\n }\n return jwt.sign(secret);\n }\n}\n\nexport class TokenVerifier {\n private apiKey: string;\n\n private apiSecret: string;\n\n constructor(apiKey: string, apiSecret: string) {\n this.apiKey = apiKey;\n this.apiSecret = apiSecret;\n }\n\n async verify(token: string): Promise<ClaimGrants> {\n const secret = new TextEncoder().encode(this.apiSecret);\n const { payload } = await jose.jwtVerify(token, secret, { issuer: this.apiKey });\n if (!payload) {\n throw Error('invalid token');\n }\n\n return payload as ClaimGrants;\n }\n}\n"],"mappings":"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","names":[]}
|