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.
- package/README.md +27 -0
- package/client.d.mts +2 -2
- package/client.d.mts.map +1 -1
- package/client.d.ts +2 -2
- package/client.d.ts.map +1 -1
- package/client.js.map +1 -1
- package/client.mjs.map +1 -1
- package/lib/login-token.d.mts +87 -0
- package/lib/login-token.d.mts.map +1 -0
- package/lib/login-token.d.ts +87 -0
- package/lib/login-token.d.ts.map +1 -0
- package/lib/login-token.js +190 -0
- package/lib/login-token.js.map +1 -0
- package/lib/login-token.mjs +151 -0
- package/lib/login-token.mjs.map +1 -0
- package/package.json +1 -1
- package/resources/telephony-credentials.d.mts +48 -2
- package/resources/telephony-credentials.d.mts.map +1 -1
- package/resources/telephony-credentials.d.ts +48 -2
- package/resources/telephony-credentials.d.ts.map +1 -1
- package/resources/telephony-credentials.js +46 -2
- package/resources/telephony-credentials.js.map +1 -1
- package/resources/telephony-credentials.mjs +46 -2
- package/resources/telephony-credentials.mjs.map +1 -1
- package/src/client.ts +4 -0
- package/src/lib/login-token.ts +219 -0
- package/src/resources/telephony-credentials.ts +75 -2
- package/src/version.ts +1 -1
- package/version.d.mts +1 -1
- package/version.d.mts.map +1 -1
- package/version.d.ts +1 -1
- package/version.d.ts.map +1 -1
- package/version.js +1 -1
- package/version.js.map +1 -1
- package/version.mjs +1 -1
- package/version.mjs.map +1 -1
|
@@ -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
|
@@ -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(
|
|
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":"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;
|
|
1
|
+
{"version":3,"file":"telephony-credentials.d.mts","sourceRoot":"","sources":["../src/resources/telephony-credentials.ts"],"names":[],"mappings":"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"}
|