telnyx 7.29.0 → 7.30.0-beta.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.
@@ -0,0 +1,87 @@
1
+ /**
2
+ * WebRTC login tokens minted locally, with no request to Telnyx.
3
+ *
4
+ * The token has the same shape as the one
5
+ * `POST /v2/telephony_credentials/{id}/token` returns, so it is used the same
6
+ * way: pass it to the WebRTC SDK as `login_token`. Telnyx verifies it on login.
7
+ * It is the same computation as `TelephonyCredential#to_jwt` in telnyx-ruby.
8
+ *
9
+ * The signing material comes from the credential: `token_material` is in the
10
+ * response of `POST /v2/telephony_credentials` and of
11
+ * `GET /v2/telephony_credentials/{id}/token_material`. It is as sensitive as
12
+ * the SIP password, so keep it on the server; never ship it to a browser.
13
+ *
14
+ * @example
15
+ * const { data: credential } = await client.telephonyCredentials.create({
16
+ * connection_id: '123',
17
+ * include: 'token_material', // the API returns the material only when asked
18
+ * });
19
+ * const loginToken = await client.telephonyCredentials.toJwt(credential); // 1 hour
20
+ * const shortLived = await client.telephonyCredentials.toJwt(credential, { ttl: 600 });
21
+ *
22
+ * To mint later with no request at all, store these with the user the credential
23
+ * belongs to, server side: `id`, `user_id`, `sip_username`, `expires_at` and
24
+ * `token_material`. The token is built from all of them.
25
+ *
26
+ * @example From stored values, without a request at all
27
+ * import { createLoginToken } from 'telnyx/lib/login-token';
28
+ * const loginToken = await createLoginToken({
29
+ * id: '...', user_id: '...', sip_username: 'gencred...', expires_at: '2027-01-01T00:00:00Z',
30
+ * token_material: { kid: 'v1', tel_token: '...', signing_secret: '...' },
31
+ * });
32
+ */
33
+ import { TelnyxError } from "../core/error.js";
34
+ /** Token lifetime when `ttl` is not given: one hour. */
35
+ export declare const LOGIN_TOKEN_DEFAULT_TTL = 3600;
36
+ /** Longest lifetime a login token can have: one day, the same as API-minted tokens. */
37
+ export declare const LOGIN_TOKEN_MAX_TTL = 86400;
38
+ /** `cty` header of a locally minted token; voice-sdk-proxy selects the verification path by it. */
39
+ export declare const LOGIN_TOKEN_CONTENT_TYPE = "telnyx-webrtc;v=1";
40
+ /**
41
+ * What the API returns as `token_material`. `signing_secret` is base64url
42
+ * (unpadded) bytes of the HS256 key; `tel_token` goes into the token as is.
43
+ */
44
+ export interface TokenMaterial {
45
+ /** Which key the material was derived with (`v1` today). Goes in the JWT header. */
46
+ kid: string;
47
+ /** The SIP credential encrypted for the gateway, the same value `/token` puts in the `tel_token` claim. */
48
+ tel_token: string;
49
+ /** The HS256 key the token is signed with, base64url. */
50
+ signing_secret: string;
51
+ }
52
+ /** The fields of a telephony credential that a login token is built from. */
53
+ export interface LoginTokenCredential {
54
+ /** The telephony credential `id`. */
55
+ id?: string | undefined;
56
+ /** The credential's `user_id`. */
57
+ user_id?: string | undefined;
58
+ /** The credential's `sip_username`; the token's `identity`. */
59
+ sip_username?: string | undefined;
60
+ /** The credential's `expires_at`, as the API returns it, or null. */
61
+ expires_at?: string | null | undefined;
62
+ /** `kid`, `tel_token`, `signing_secret`; present on a credential from `create`. */
63
+ token_material?: TokenMaterial | undefined;
64
+ }
65
+ export interface LoginTokenOptions {
66
+ /** Token lifetime in seconds, 1..86400. Default one hour. */
67
+ ttl?: number | undefined;
68
+ /** Signing material to use instead of `credential.token_material`. */
69
+ tokenMaterial?: TokenMaterial | undefined;
70
+ /** The token's issue time; defaults to now. */
71
+ now?: Date | number | undefined;
72
+ }
73
+ export declare class TelnyxLoginTokenError extends TelnyxError {
74
+ constructor(message: string);
75
+ }
76
+ /**
77
+ * Mints a login token for `credential`, valid from `now` for `ttl` seconds.
78
+ * Pure computation: HMAC-SHA256 over the token with `token_material.signing_secret`.
79
+ */
80
+ export declare function createLoginToken(credential: LoginTokenCredential, options?: LoginTokenOptions): Promise<string>;
81
+ /**
82
+ * Checks a token minted by `createLoginToken` against `signingSecret` and
83
+ * returns its claims. For tests and debugging: Telnyx does the real
84
+ * verification on login.
85
+ */
86
+ export declare function decodeLoginToken(jwt: string, signingSecret: string): Promise<Record<string, unknown>>;
87
+ //# sourceMappingURL=login-token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-token.d.ts","sourceRoot":"","sources":["../src/lib/login-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAI5C,wDAAwD;AACxD,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,uFAAuF;AACvF,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AACzC,mGAAmG;AACnG,eAAO,MAAM,wBAAwB,sBAAsB,CAAC;AAE5D;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,oFAAoF;IACpF,GAAG,EAAE,MAAM,CAAC;IACZ,2GAA2G;IAC3G,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,6EAA6E;AAC7E,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACvC,mFAAmF;IACnF,cAAc,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAC5C;AAED,MAAM,WAAW,iBAAiB;IAChC,6DAA6D;IAC7D,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,sEAAsE;IACtE,aAAa,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC1C,+CAA+C;IAC/C,GAAG,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;CACjC;AAED,qBAAa,qBAAsB,SAAQ,WAAW;gBACxC,OAAO,EAAE,MAAM;CAI5B;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,oBAAoB,EAChC,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAW3G"}
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+ /**
3
+ * WebRTC login tokens minted locally, with no request to Telnyx.
4
+ *
5
+ * The token has the same shape as the one
6
+ * `POST /v2/telephony_credentials/{id}/token` returns, so it is used the same
7
+ * way: pass it to the WebRTC SDK as `login_token`. Telnyx verifies it on login.
8
+ * It is the same computation as `TelephonyCredential#to_jwt` in telnyx-ruby.
9
+ *
10
+ * The signing material comes from the credential: `token_material` is in the
11
+ * response of `POST /v2/telephony_credentials` and of
12
+ * `GET /v2/telephony_credentials/{id}/token_material`. It is as sensitive as
13
+ * the SIP password, so keep it on the server; never ship it to a browser.
14
+ *
15
+ * @example
16
+ * const { data: credential } = await client.telephonyCredentials.create({
17
+ * connection_id: '123',
18
+ * include: 'token_material', // the API returns the material only when asked
19
+ * });
20
+ * const loginToken = await client.telephonyCredentials.toJwt(credential); // 1 hour
21
+ * const shortLived = await client.telephonyCredentials.toJwt(credential, { ttl: 600 });
22
+ *
23
+ * To mint later with no request at all, store these with the user the credential
24
+ * belongs to, server side: `id`, `user_id`, `sip_username`, `expires_at` and
25
+ * `token_material`. The token is built from all of them.
26
+ *
27
+ * @example From stored values, without a request at all
28
+ * import { createLoginToken } from 'telnyx/lib/login-token';
29
+ * const loginToken = await createLoginToken({
30
+ * id: '...', user_id: '...', sip_username: 'gencred...', expires_at: '2027-01-01T00:00:00Z',
31
+ * token_material: { kid: 'v1', tel_token: '...', signing_secret: '...' },
32
+ * });
33
+ */
34
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
35
+ if (k2 === undefined) k2 = k;
36
+ var desc = Object.getOwnPropertyDescriptor(m, k);
37
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
38
+ desc = { enumerable: true, get: function() { return m[k]; } };
39
+ }
40
+ Object.defineProperty(o, k2, desc);
41
+ }) : (function(o, m, k, k2) {
42
+ if (k2 === undefined) k2 = k;
43
+ o[k2] = m[k];
44
+ }));
45
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
46
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
47
+ }) : function(o, v) {
48
+ o["default"] = v;
49
+ });
50
+ var __importStar = (this && this.__importStar) || (function () {
51
+ var ownKeys = function(o) {
52
+ ownKeys = Object.getOwnPropertyNames || function (o) {
53
+ var ar = [];
54
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
55
+ return ar;
56
+ };
57
+ return ownKeys(o);
58
+ };
59
+ return function (mod) {
60
+ if (mod && mod.__esModule) return mod;
61
+ var result = {};
62
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
63
+ __setModuleDefault(result, mod);
64
+ return result;
65
+ };
66
+ })();
67
+ Object.defineProperty(exports, "__esModule", { value: true });
68
+ exports.TelnyxLoginTokenError = exports.LOGIN_TOKEN_CONTENT_TYPE = exports.LOGIN_TOKEN_MAX_TTL = exports.LOGIN_TOKEN_DEFAULT_TTL = void 0;
69
+ exports.createLoginToken = createLoginToken;
70
+ exports.decodeLoginToken = decodeLoginToken;
71
+ const error_1 = require("../core/error.js");
72
+ const base64_1 = require("../internal/utils/base64.js");
73
+ const bytes_1 = require("../internal/utils/bytes.js");
74
+ /** Token lifetime when `ttl` is not given: one hour. */
75
+ exports.LOGIN_TOKEN_DEFAULT_TTL = 3600;
76
+ /** Longest lifetime a login token can have: one day, the same as API-minted tokens. */
77
+ exports.LOGIN_TOKEN_MAX_TTL = 86400;
78
+ /** `cty` header of a locally minted token; voice-sdk-proxy selects the verification path by it. */
79
+ exports.LOGIN_TOKEN_CONTENT_TYPE = 'telnyx-webrtc;v=1';
80
+ class TelnyxLoginTokenError extends error_1.TelnyxError {
81
+ constructor(message) {
82
+ super(message);
83
+ this.name = 'TelnyxLoginTokenError';
84
+ }
85
+ }
86
+ exports.TelnyxLoginTokenError = TelnyxLoginTokenError;
87
+ /**
88
+ * Mints a login token for `credential`, valid from `now` for `ttl` seconds.
89
+ * Pure computation: HMAC-SHA256 over the token with `token_material.signing_secret`.
90
+ */
91
+ async function createLoginToken(credential, options = {}) {
92
+ const credentialId = required(credential.id, 'id');
93
+ const userId = required(credential.user_id, 'user_id');
94
+ const identity = required(credential.sip_username, 'sip_username');
95
+ const material = normalizeMaterial(options.tokenMaterial ?? credential.token_material);
96
+ const ttl = clampTtl(options.ttl);
97
+ const now = options.now === undefined ? Date.now() : Number(options.now);
98
+ const iat = Math.floor(now / 1000);
99
+ // Same field order as the Ruby SDK, so the two produce the same bytes.
100
+ const header = { alg: 'HS256', typ: 'JWT', cty: exports.LOGIN_TOKEN_CONTENT_TYPE, kid: material.kid };
101
+ const payload = {
102
+ sub: credentialId,
103
+ user_id: userId,
104
+ identity,
105
+ cred_exp: credential.expires_at ?? null,
106
+ tel_token: material.tel_token,
107
+ iat,
108
+ nbf: iat,
109
+ exp: iat + ttl,
110
+ jti: `${credentialId}-${iat}`,
111
+ };
112
+ const signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}`;
113
+ return `${signingInput}.${base64url(await sign(signingInput, material.signing_secret))}`;
114
+ }
115
+ /**
116
+ * Checks a token minted by `createLoginToken` against `signingSecret` and
117
+ * returns its claims. For tests and debugging: Telnyx does the real
118
+ * verification on login.
119
+ */
120
+ async function decodeLoginToken(jwt, signingSecret) {
121
+ const [head, body, sig, ...rest] = String(jwt).split('.');
122
+ if (!head || !body || sig === undefined || rest.length) {
123
+ throw new TelnyxLoginTokenError('not a JWT');
124
+ }
125
+ const expected = await sign(`${head}.${body}`, signingSecret);
126
+ const given = fromBase64url(sig);
127
+ if (!bytesEqual(given, expected)) {
128
+ throw new TelnyxLoginTokenError('Signature is invalid and does not match the payload');
129
+ }
130
+ return JSON.parse((0, bytes_1.decodeUTF8)(fromBase64url(body)));
131
+ }
132
+ function required(value, name) {
133
+ if (value === undefined || value === null || String(value) === '') {
134
+ throw new TelnyxLoginTokenError(`${name} is required to mint a token`);
135
+ }
136
+ return String(value);
137
+ }
138
+ function normalizeMaterial(material) {
139
+ if (!material || typeof material !== 'object') {
140
+ throw new TelnyxLoginTokenError('token_material is required to mint a token');
141
+ }
142
+ const out = {};
143
+ for (const field of ['kid', 'tel_token', 'signing_secret']) {
144
+ const value = material[field];
145
+ if (value === undefined || value === null || String(value) === '') {
146
+ throw new TelnyxLoginTokenError(`token_material.${field} is missing`);
147
+ }
148
+ out[field] = String(value);
149
+ }
150
+ return out;
151
+ }
152
+ function clampTtl(ttl) {
153
+ const n = ttl === undefined ? exports.LOGIN_TOKEN_DEFAULT_TTL : Math.trunc(Number(ttl));
154
+ if (!Number.isFinite(n))
155
+ return exports.LOGIN_TOKEN_DEFAULT_TTL;
156
+ return Math.min(exports.LOGIN_TOKEN_MAX_TTL, Math.max(1, n));
157
+ }
158
+ function base64url(data) {
159
+ // Base64 pads with at most two '=': a bounded match keeps this linear on any input.
160
+ return (0, base64_1.toBase64)(data)
161
+ .replace(/\+/g, '-')
162
+ .replace(/\//g, '_')
163
+ .replace(/={1,2}$/, '');
164
+ }
165
+ function fromBase64url(str) {
166
+ const b64 = str.replace(/-/g, '+').replace(/_/g, '/');
167
+ return (0, base64_1.fromBase64)(b64 + '='.repeat((4 - (b64.length % 4)) % 4));
168
+ }
169
+ function bytesEqual(a, b) {
170
+ if (a.length !== b.length)
171
+ return false;
172
+ let diff = 0;
173
+ for (let i = 0; i < a.length; i++)
174
+ diff |= a[i] ^ b[i];
175
+ return diff === 0;
176
+ }
177
+ async function getSubtle() {
178
+ if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.subtle) {
179
+ return globalThis.crypto.subtle;
180
+ }
181
+ // Node.js < 19 may need webcrypto from crypto module
182
+ const nodeCrypto = await Promise.resolve().then(() => __importStar(require('crypto')));
183
+ return nodeCrypto.webcrypto.subtle;
184
+ }
185
+ async function sign(signingInput, signingSecret) {
186
+ const subtle = await getSubtle();
187
+ const key = await subtle.importKey('raw', fromBase64url(signingSecret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
188
+ return new Uint8Array(await subtle.sign('HMAC', key, (0, bytes_1.encodeUTF8)(signingInput)));
189
+ }
190
+ //# sourceMappingURL=login-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-token.js","sourceRoot":"","sources":["../src/lib/login-token.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * WebRTC login tokens minted locally, with no request to Telnyx.
3
+ *
4
+ * The token has the same shape as the one
5
+ * `POST /v2/telephony_credentials/{id}/token` returns, so it is used the same
6
+ * way: pass it to the WebRTC SDK as `login_token`. Telnyx verifies it on login.
7
+ * It is the same computation as `TelephonyCredential#to_jwt` in telnyx-ruby.
8
+ *
9
+ * The signing material comes from the credential: `token_material` is in the
10
+ * response of `POST /v2/telephony_credentials` and of
11
+ * `GET /v2/telephony_credentials/{id}/token_material`. It is as sensitive as
12
+ * the SIP password, so keep it on the server; never ship it to a browser.
13
+ *
14
+ * @example
15
+ * const { data: credential } = await client.telephonyCredentials.create({
16
+ * connection_id: '123',
17
+ * include: 'token_material', // the API returns the material only when asked
18
+ * });
19
+ * const loginToken = await client.telephonyCredentials.toJwt(credential); // 1 hour
20
+ * const shortLived = await client.telephonyCredentials.toJwt(credential, { ttl: 600 });
21
+ *
22
+ * To mint later with no request at all, store these with the user the credential
23
+ * belongs to, server side: `id`, `user_id`, `sip_username`, `expires_at` and
24
+ * `token_material`. The token is built from all of them.
25
+ *
26
+ * @example From stored values, without a request at all
27
+ * import { createLoginToken } from 'telnyx/lib/login-token';
28
+ * const loginToken = await createLoginToken({
29
+ * id: '...', user_id: '...', sip_username: 'gencred...', expires_at: '2027-01-01T00:00:00Z',
30
+ * token_material: { kid: 'v1', tel_token: '...', signing_secret: '...' },
31
+ * });
32
+ */
33
+ import { TelnyxError } from "../core/error.mjs";
34
+ import { fromBase64, toBase64 } from "../internal/utils/base64.mjs";
35
+ import { decodeUTF8, encodeUTF8 } from "../internal/utils/bytes.mjs";
36
+ /** Token lifetime when `ttl` is not given: one hour. */
37
+ export const LOGIN_TOKEN_DEFAULT_TTL = 3600;
38
+ /** Longest lifetime a login token can have: one day, the same as API-minted tokens. */
39
+ export const LOGIN_TOKEN_MAX_TTL = 86400;
40
+ /** `cty` header of a locally minted token; voice-sdk-proxy selects the verification path by it. */
41
+ export const LOGIN_TOKEN_CONTENT_TYPE = 'telnyx-webrtc;v=1';
42
+ export class TelnyxLoginTokenError extends TelnyxError {
43
+ constructor(message) {
44
+ super(message);
45
+ this.name = 'TelnyxLoginTokenError';
46
+ }
47
+ }
48
+ /**
49
+ * Mints a login token for `credential`, valid from `now` for `ttl` seconds.
50
+ * Pure computation: HMAC-SHA256 over the token with `token_material.signing_secret`.
51
+ */
52
+ export async function createLoginToken(credential, options = {}) {
53
+ const credentialId = required(credential.id, 'id');
54
+ const userId = required(credential.user_id, 'user_id');
55
+ const identity = required(credential.sip_username, 'sip_username');
56
+ const material = normalizeMaterial(options.tokenMaterial ?? credential.token_material);
57
+ const ttl = clampTtl(options.ttl);
58
+ const now = options.now === undefined ? Date.now() : Number(options.now);
59
+ const iat = Math.floor(now / 1000);
60
+ // Same field order as the Ruby SDK, so the two produce the same bytes.
61
+ const header = { alg: 'HS256', typ: 'JWT', cty: LOGIN_TOKEN_CONTENT_TYPE, kid: material.kid };
62
+ const payload = {
63
+ sub: credentialId,
64
+ user_id: userId,
65
+ identity,
66
+ cred_exp: credential.expires_at ?? null,
67
+ tel_token: material.tel_token,
68
+ iat,
69
+ nbf: iat,
70
+ exp: iat + ttl,
71
+ jti: `${credentialId}-${iat}`,
72
+ };
73
+ const signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}`;
74
+ return `${signingInput}.${base64url(await sign(signingInput, material.signing_secret))}`;
75
+ }
76
+ /**
77
+ * Checks a token minted by `createLoginToken` against `signingSecret` and
78
+ * returns its claims. For tests and debugging: Telnyx does the real
79
+ * verification on login.
80
+ */
81
+ export async function decodeLoginToken(jwt, signingSecret) {
82
+ const [head, body, sig, ...rest] = String(jwt).split('.');
83
+ if (!head || !body || sig === undefined || rest.length) {
84
+ throw new TelnyxLoginTokenError('not a JWT');
85
+ }
86
+ const expected = await sign(`${head}.${body}`, signingSecret);
87
+ const given = fromBase64url(sig);
88
+ if (!bytesEqual(given, expected)) {
89
+ throw new TelnyxLoginTokenError('Signature is invalid and does not match the payload');
90
+ }
91
+ return JSON.parse(decodeUTF8(fromBase64url(body)));
92
+ }
93
+ function required(value, name) {
94
+ if (value === undefined || value === null || String(value) === '') {
95
+ throw new TelnyxLoginTokenError(`${name} is required to mint a token`);
96
+ }
97
+ return String(value);
98
+ }
99
+ function normalizeMaterial(material) {
100
+ if (!material || typeof material !== 'object') {
101
+ throw new TelnyxLoginTokenError('token_material is required to mint a token');
102
+ }
103
+ const out = {};
104
+ for (const field of ['kid', 'tel_token', 'signing_secret']) {
105
+ const value = material[field];
106
+ if (value === undefined || value === null || String(value) === '') {
107
+ throw new TelnyxLoginTokenError(`token_material.${field} is missing`);
108
+ }
109
+ out[field] = String(value);
110
+ }
111
+ return out;
112
+ }
113
+ function clampTtl(ttl) {
114
+ const n = ttl === undefined ? LOGIN_TOKEN_DEFAULT_TTL : Math.trunc(Number(ttl));
115
+ if (!Number.isFinite(n))
116
+ return LOGIN_TOKEN_DEFAULT_TTL;
117
+ return Math.min(LOGIN_TOKEN_MAX_TTL, Math.max(1, n));
118
+ }
119
+ function base64url(data) {
120
+ // Base64 pads with at most two '=': a bounded match keeps this linear on any input.
121
+ return toBase64(data)
122
+ .replace(/\+/g, '-')
123
+ .replace(/\//g, '_')
124
+ .replace(/={1,2}$/, '');
125
+ }
126
+ function fromBase64url(str) {
127
+ const b64 = str.replace(/-/g, '+').replace(/_/g, '/');
128
+ return fromBase64(b64 + '='.repeat((4 - (b64.length % 4)) % 4));
129
+ }
130
+ function bytesEqual(a, b) {
131
+ if (a.length !== b.length)
132
+ return false;
133
+ let diff = 0;
134
+ for (let i = 0; i < a.length; i++)
135
+ diff |= a[i] ^ b[i];
136
+ return diff === 0;
137
+ }
138
+ async function getSubtle() {
139
+ if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.subtle) {
140
+ return globalThis.crypto.subtle;
141
+ }
142
+ // Node.js < 19 may need webcrypto from crypto module
143
+ const nodeCrypto = await import('crypto');
144
+ return nodeCrypto.webcrypto.subtle;
145
+ }
146
+ async function sign(signingInput, signingSecret) {
147
+ const subtle = await getSubtle();
148
+ const key = await subtle.importKey('raw', fromBase64url(signingSecret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
149
+ return new Uint8Array(await subtle.sign('HMAC', key, encodeUTF8(signingInput)));
150
+ }
151
+ //# sourceMappingURL=login-token.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-token.mjs","sourceRoot":"","sources":["../src/lib/login-token.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "telnyx",
3
- "version": "7.29.0",
3
+ "version": "7.30.0-beta.0",
4
4
  "description": "The official TypeScript library for the Telnyx API",
5
5
  "author": "Telnyx <support@telnyx.com>",
6
6
  "types": "./index.d.ts",
@@ -2,6 +2,7 @@ import { APIResource } from "../core/resource.mjs";
2
2
  import { APIPromise } from "../core/api-promise.mjs";
3
3
  import { DefaultFlatPagination, type DefaultFlatPaginationParams, PagePromise } from "../core/pagination.mjs";
4
4
  import { RequestOptions } from "../internal/request-options.mjs";
5
+ import { type LoginTokenOptions, type TokenMaterial } from "../lib/login-token.mjs";
5
6
  export declare class TelephonyCredentials extends APIResource {
6
7
  /**
7
8
  * Returns a paginated list of the on-demand telephony credentials on your account,
@@ -28,7 +29,7 @@ export declare class TelephonyCredentials extends APIResource {
28
29
  * });
29
30
  * ```
30
31
  */
31
- create(body: TelephonyCredentialCreateParams, options?: RequestOptions): APIPromise<TelephonyCredentialCreateResponse>;
32
+ create(params: TelephonyCredentialCreateParams, options?: RequestOptions): APIPromise<TelephonyCredentialCreateResponse>;
32
33
  /**
33
34
  * Permanently deletes the specified telephony credential, revoking any access it
34
35
  * provided.
@@ -60,6 +61,37 @@ export declare class TelephonyCredentials extends APIResource {
60
61
  * ```
61
62
  */
62
63
  update(id: string, body: TelephonyCredentialUpdateParams, options?: RequestOptions): APIPromise<TelephonyCredentialUpdateResponse>;
64
+ /**
65
+ * The material a login token is signed with (`kid`, `tel_token`,
66
+ * `signing_secret`), for a credential that did not come from `create`. Treat
67
+ * the result like the SIP password.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * const { data: tokenMaterial } =
72
+ * await client.telephonyCredentials.retrieveTokenMaterial('id');
73
+ * ```
74
+ */
75
+ retrieveTokenMaterial(id: string, options?: RequestOptions): APIPromise<TelephonyCredentialRetrieveTokenMaterialResponse>;
76
+ /**
77
+ * Mints a WebRTC login token for the credential locally: the same use as
78
+ * `createToken`, with no request to Telnyx per token. Uses the
79
+ * `token_material` of a credential from `create`, or `tokenMaterial` from the
80
+ * options, or fetches it once with `retrieveTokenMaterial`.
81
+ *
82
+ * `ttl` is the token lifetime in seconds, 1..86400, default one hour.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * const { data: credential } = await client.telephonyCredentials.create({
87
+ * connection_id: '1234567890',
88
+ * });
89
+ * const loginToken = await client.telephonyCredentials.toJwt(credential);
90
+ * ```
91
+ */
92
+ toJwt(credential: TelephonyCredential, options?: LoginTokenOptions & {
93
+ requestOptions?: RequestOptions | undefined;
94
+ }): Promise<string>;
63
95
  /**
64
96
  * Create an Access Token (JWT) for the credential.
65
97
  *
@@ -114,6 +146,14 @@ export interface TelephonyCredential {
114
146
  * Identifies the user this credential is associated with.
115
147
  */
116
148
  user_id?: string;
149
+ /**
150
+ * What a login token is signed with. Returned by `create`; see `toJwt` and
151
+ * `retrieveTokenMaterial`.
152
+ */
153
+ token_material?: TokenMaterial;
154
+ }
155
+ export interface TelephonyCredentialRetrieveTokenMaterialResponse {
156
+ data?: TokenMaterial;
117
157
  }
118
158
  export interface TelephonyCredentialCreateResponse {
119
159
  data?: TelephonyCredential;
@@ -164,6 +204,11 @@ export declare namespace TelephonyCredentialListParams {
164
204
  }
165
205
  }
166
206
  export interface TelephonyCredentialCreateParams {
207
+ /**
208
+ * Query param: extra fields to return. `token_material` adds what `toJwt` signs
209
+ * with (as sensitive as `sip_password`; keep it on the server).
210
+ */
211
+ include?: 'token_material' | undefined;
167
212
  /**
168
213
  * Identifies the Credential Connection this credential is associated with.
169
214
  */
@@ -202,7 +247,8 @@ export interface TelephonyCredentialCreateTokenParams {
202
247
  */
203
248
  'Idempotency-Key'?: string;
204
249
  }
250
+ export type { LoginTokenOptions, TokenMaterial } from "../lib/login-token.mjs";
205
251
  export declare namespace TelephonyCredentials {
206
- export { type TelephonyCredential as TelephonyCredential, type TelephonyCredentialCreateResponse as TelephonyCredentialCreateResponse, type TelephonyCredentialRetrieveResponse as TelephonyCredentialRetrieveResponse, type TelephonyCredentialUpdateResponse as TelephonyCredentialUpdateResponse, type TelephonyCredentialDeleteResponse as TelephonyCredentialDeleteResponse, type TelephonyCredentialCreateTokenResponse as TelephonyCredentialCreateTokenResponse, type TelephonyCredentialsDefaultFlatPagination as TelephonyCredentialsDefaultFlatPagination, type TelephonyCredentialListParams as TelephonyCredentialListParams, type TelephonyCredentialCreateParams as TelephonyCredentialCreateParams, type TelephonyCredentialUpdateParams as TelephonyCredentialUpdateParams, type TelephonyCredentialCreateTokenParams as TelephonyCredentialCreateTokenParams, };
252
+ export { type TelephonyCredential as TelephonyCredential, type TelephonyCredentialCreateResponse as TelephonyCredentialCreateResponse, type TelephonyCredentialRetrieveResponse as TelephonyCredentialRetrieveResponse, type TelephonyCredentialUpdateResponse as TelephonyCredentialUpdateResponse, type TelephonyCredentialDeleteResponse as TelephonyCredentialDeleteResponse, type TelephonyCredentialCreateTokenResponse as TelephonyCredentialCreateTokenResponse, type TelephonyCredentialRetrieveTokenMaterialResponse as TelephonyCredentialRetrieveTokenMaterialResponse, type TokenMaterial as TokenMaterial, type TelephonyCredentialsDefaultFlatPagination as TelephonyCredentialsDefaultFlatPagination, type TelephonyCredentialListParams as TelephonyCredentialListParams, type TelephonyCredentialCreateParams as TelephonyCredentialCreateParams, type TelephonyCredentialUpdateParams as TelephonyCredentialUpdateParams, type TelephonyCredentialCreateTokenParams as TelephonyCredentialCreateTokenParams, };
207
253
  }
208
254
  //# sourceMappingURL=telephony-credentials.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"telephony-credentials.d.mts","sourceRoot":"","sources":["../src/resources/telephony-credentials.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"telephony-credentials.d.mts","sourceRoot":"","sources":["../src/resources/telephony-credentials.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,6BAAyB;AAC/C,OAAO,EAAE,UAAU,EAAE,gCAA4B;AACjD,OAAO,EAAE,qBAAqB,EAAE,KAAK,2BAA2B,EAAE,WAAW,EAAE,+BAA2B;AAE1G,OAAO,EAAE,cAAc,EAAE,wCAAoC;AAE7D,OAAO,EAAoB,KAAK,iBAAiB,EAAE,KAAK,aAAa,EAAE,+BAA2B;AAElG,qBAAa,oBAAqB,SAAQ,WAAW;IACnD;;;;;;;;;;;OAWG;IACH,IAAI,CACF,KAAK,GAAE,6BAA6B,GAAG,IAAI,GAAG,SAAc,EAC5D,OAAO,CAAC,EAAE,cAAc,GACvB,WAAW,CAAC,yCAAyC,EAAE,mBAAmB,CAAC;IAO9E;;;;;;;;;;;OAWG;IACH,MAAM,CACJ,MAAM,EAAE,+BAA+B,EACvC,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,iCAAiC,CAAC;IAUhD;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,iCAAiC,CAAC;IAI3F;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,mCAAmC,CAAC;IAI/F;;;;;;;;OAQG;IACH,MAAM,CACJ,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,+BAA+B,EACrC,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,iCAAiC,CAAC;IAIhD;;;;;;;;;;OAUG;IACH,qBAAqB,CACnB,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,gDAAgD,CAAC;IAI/D;;;;;;;;;;;;;;;OAeG;IACG,KAAK,CACT,UAAU,EAAE,mBAAmB,EAC/B,OAAO,CAAC,EAAE,iBAAiB,GAAG;QAAE,cAAc,CAAC,EAAE,cAAc,GAAG,SAAS,CAAA;KAAE,GAC5E,OAAO,CAAC,MAAM,CAAC;IASlB;;;;;;;;OAQG;IACH,WAAW,CACT,EAAE,EAAE,MAAM,EACV,MAAM,GAAE,oCAAoC,GAAG,IAAI,GAAG,SAAc,EACpE,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,MAAM,CAAC;CAatB;AAED,MAAM,MAAM,yCAAyC,GAAG,qBAAqB,CAAC,mBAAmB,CAAC,CAAC;AAEnG,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC;CAChC;AAED,MAAM,WAAW,gDAAgD;IAC/D,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAED,MAAM,WAAW,iCAAiC;IAChD,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B;AAED,MAAM,WAAW,mCAAmC;IAClD,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B;AAED,MAAM,WAAW,iCAAiC;IAChD,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B;AAED,MAAM,WAAW,iCAAiC;IAChD,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B;AAED,MAAM,MAAM,sCAAsC,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,6BAA8B,SAAQ,2BAA2B;IAChF;;;OAGG;IACH,MAAM,CAAC,EAAE,6BAA6B,CAAC,MAAM,CAAC;CAC/C;AAED,yBAAiB,6BAA6B,CAAC;IAC7C;;;OAGG;IACH,UAAiB,MAAM;QACrB;;WAEG;QACH,IAAI,CAAC,EAAE,MAAM,CAAC;QAEd;;WAEG;QACH,WAAW,CAAC,EAAE,MAAM,CAAC;QAErB;;WAEG;QACH,YAAY,CAAC,EAAE,MAAM,CAAC;QAEtB;;WAEG;QACH,MAAM,CAAC,EAAE,MAAM,CAAC;QAEhB;;WAEG;QACH,GAAG,CAAC,EAAE,MAAM,CAAC;KACd;CACF;AAED,MAAM,WAAW,+BAA+B;IAC9C;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAEvC;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oCAAoC;IACnD;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,+BAA2B;AAE3E,MAAM,CAAC,OAAO,WAAW,oBAAoB,CAAC;IAC5C,OAAO,EACL,KAAK,mBAAmB,IAAI,mBAAmB,EAC/C,KAAK,iCAAiC,IAAI,iCAAiC,EAC3E,KAAK,mCAAmC,IAAI,mCAAmC,EAC/E,KAAK,iCAAiC,IAAI,iCAAiC,EAC3E,KAAK,iCAAiC,IAAI,iCAAiC,EAC3E,KAAK,sCAAsC,IAAI,sCAAsC,EACrF,KAAK,gDAAgD,IAAI,gDAAgD,EACzG,KAAK,aAAa,IAAI,aAAa,EACnC,KAAK,yCAAyC,IAAI,yCAAyC,EAC3F,KAAK,6BAA6B,IAAI,6BAA6B,EACnE,KAAK,+BAA+B,IAAI,+BAA+B,EACvE,KAAK,+BAA+B,IAAI,+BAA+B,EACvE,KAAK,oCAAoC,IAAI,oCAAoC,GAClF,CAAC;CACH"}