@mentra/sdk 2.1.27 → 2.1.28
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/dist/app/session/api-client.d.ts.map +1 -1
- package/dist/app/session/dashboard.d.ts +5 -8
- package/dist/app/session/dashboard.d.ts.map +1 -1
- package/dist/app/session/events.d.ts +2 -1
- package/dist/app/session/events.d.ts.map +1 -1
- package/dist/app/session/index.d.ts +62 -3
- package/dist/app/session/index.d.ts.map +1 -1
- package/dist/app/session/modules/audio.d.ts +33 -4
- package/dist/app/session/modules/audio.d.ts.map +1 -1
- package/dist/app/session/modules/camera-managed-extension.d.ts +2 -3
- package/dist/app/session/modules/camera-managed-extension.d.ts.map +1 -1
- package/dist/app/session/modules/camera.d.ts +5 -5
- package/dist/app/session/modules/camera.d.ts.map +1 -1
- package/dist/app/session/modules/led.d.ts +141 -0
- package/dist/app/session/modules/led.d.ts.map +1 -0
- package/dist/app/session/modules/location.d.ts +1 -2
- package/dist/app/session/modules/location.d.ts.map +1 -1
- package/dist/app/session/modules/simple-storage.d.ts.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5347 -112
- package/dist/index.js.map +45 -0
- package/dist/logging/logger.d.ts +1 -1
- package/dist/logging/logger.d.ts.map +1 -1
- package/dist/types/capabilities.d.ts +3 -0
- package/dist/types/capabilities.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -14
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/message-types.d.ts +8 -1
- package/dist/types/message-types.d.ts.map +1 -1
- package/dist/types/messages/app-to-cloud.d.ts +48 -2
- package/dist/types/messages/app-to-cloud.d.ts.map +1 -1
- package/dist/types/messages/cloud-to-app.d.ts +16 -6
- package/dist/types/messages/cloud-to-app.d.ts.map +1 -1
- package/dist/types/messages/cloud-to-glasses.d.ts +29 -1
- package/dist/types/messages/cloud-to-glasses.d.ts.map +1 -1
- package/dist/types/messages/glasses-to-cloud.d.ts +24 -1
- package/dist/types/messages/glasses-to-cloud.d.ts.map +1 -1
- package/dist/types/rtmp-stream.d.ts +1 -1
- package/dist/types/rtmp-stream.d.ts.map +1 -1
- package/dist/types/streams.d.ts +28 -1
- package/dist/types/streams.d.ts.map +1 -1
- package/package.json +9 -3
- package/dist/app/index.js +0 -24
- package/dist/app/server/index.js +0 -658
- package/dist/app/session/api-client.js +0 -101
- package/dist/app/session/dashboard.js +0 -149
- package/dist/app/session/events.js +0 -315
- package/dist/app/session/index.js +0 -1573
- package/dist/app/session/layouts.js +0 -372
- package/dist/app/session/modules/audio.js +0 -321
- package/dist/app/session/modules/camera-managed-extension.js +0 -310
- package/dist/app/session/modules/camera.js +0 -607
- package/dist/app/session/modules/index.js +0 -19
- package/dist/app/session/modules/location.js +0 -61
- package/dist/app/session/modules/simple-storage.js +0 -232
- package/dist/app/session/settings.js +0 -358
- package/dist/app/token/index.js +0 -22
- package/dist/app/token/utils.js +0 -144
- package/dist/app/webview/index.js +0 -382
- package/dist/constants/index.js +0 -16
- package/dist/constants/log-messages/color.js +0 -14
- package/dist/constants/log-messages/logos.js +0 -48
- package/dist/constants/log-messages/updates.js +0 -55
- package/dist/constants/log-messages/warning.js +0 -89
- package/dist/examples/managed-rtmp-streaming-example.js +0 -158
- package/dist/examples/managed-rtmp-streaming-with-restream-example.js +0 -124
- package/dist/examples/rtmp-streaming-example.js +0 -102
- package/dist/logging/logger.js +0 -79
- package/dist/types/capabilities.js +0 -9
- package/dist/types/dashboard/index.js +0 -12
- package/dist/types/enums.js +0 -75
- package/dist/types/index.js +0 -101
- package/dist/types/layouts.js +0 -3
- package/dist/types/message-types.js +0 -212
- package/dist/types/messages/app-to-cloud.js +0 -95
- package/dist/types/messages/base.js +0 -3
- package/dist/types/messages/cloud-to-app.js +0 -78
- package/dist/types/messages/cloud-to-glasses.js +0 -68
- package/dist/types/messages/glasses-to-cloud.js +0 -140
- package/dist/types/models.js +0 -101
- package/dist/types/photo-data.js +0 -2
- package/dist/types/rtmp-stream.js +0 -3
- package/dist/types/streams.js +0 -306
- package/dist/types/token.js +0 -7
- package/dist/types/webhooks.js +0 -28
- package/dist/utils/animation-utils.js +0 -340
- package/dist/utils/bitmap-utils.js +0 -475
- package/dist/utils/permissions-utils.js +0 -263
- package/dist/utils/resource-tracker.js +0 -153
package/dist/app/token/utils.js
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.createToken = createToken;
|
|
37
|
-
exports.validateToken = validateToken;
|
|
38
|
-
exports.generateWebviewUrl = generateWebviewUrl;
|
|
39
|
-
exports.extractTokenFromUrl = extractTokenFromUrl;
|
|
40
|
-
/**
|
|
41
|
-
* 🔐 App Token Utilities
|
|
42
|
-
*
|
|
43
|
-
* Provides utilities for working with App tokens.
|
|
44
|
-
*/
|
|
45
|
-
const jwt = __importStar(require("jsonwebtoken"));
|
|
46
|
-
/**
|
|
47
|
-
* Default token expiration (1 day)
|
|
48
|
-
*/
|
|
49
|
-
const DEFAULT_EXPIRATION = 60 * 60 * 24; // seconds * minutes * hours (1 day).
|
|
50
|
-
/**
|
|
51
|
-
* Create a App token for a user session
|
|
52
|
-
*
|
|
53
|
-
* @param payload - Token payload data
|
|
54
|
-
* @param config - Token configuration
|
|
55
|
-
* @returns JWT token string
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* ```typescript
|
|
59
|
-
* const token = createToken(
|
|
60
|
-
* {
|
|
61
|
-
* userId: 'user123',
|
|
62
|
-
* packageName: 'org.example.myapp',
|
|
63
|
-
* sessionId: 'session789'
|
|
64
|
-
* },
|
|
65
|
-
* { secretKey: 'your_secret_key' }
|
|
66
|
-
* );
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
function createToken(payload, config) {
|
|
70
|
-
return jwt.sign(payload, config.secretKey, { expiresIn: config.expiresIn || DEFAULT_EXPIRATION });
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Validate and decode a App token
|
|
74
|
-
*
|
|
75
|
-
* @param token - JWT token string
|
|
76
|
-
* @param secretKey - Secret key used for validation
|
|
77
|
-
* @returns Token validation result
|
|
78
|
-
*
|
|
79
|
-
* @example
|
|
80
|
-
* ```typescript
|
|
81
|
-
* const result = validateToken('eyJhbGciOiJIUzI1...', 'your_secret_key');
|
|
82
|
-
* if (result.valid) {
|
|
83
|
-
* // Use result.payload
|
|
84
|
-
* }
|
|
85
|
-
* ```
|
|
86
|
-
*/
|
|
87
|
-
function validateToken(token, secretKey) {
|
|
88
|
-
try {
|
|
89
|
-
const decoded = jwt.verify(token, secretKey);
|
|
90
|
-
return {
|
|
91
|
-
valid: true,
|
|
92
|
-
payload: decoded
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
catch (error) {
|
|
96
|
-
return {
|
|
97
|
-
valid: false,
|
|
98
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Generate a webview URL with an embedded App token
|
|
104
|
-
*
|
|
105
|
-
* @param baseUrl - Base URL of the webview
|
|
106
|
-
* @param token - JWT token string
|
|
107
|
-
* @returns Full URL with token parameter
|
|
108
|
-
*
|
|
109
|
-
* @example
|
|
110
|
-
* ```typescript
|
|
111
|
-
* const url = generateWebviewUrl(
|
|
112
|
-
* 'https://example.com/webview',
|
|
113
|
-
* 'eyJhbGciOiJIUzI1...'
|
|
114
|
-
* );
|
|
115
|
-
* // Returns: https://example.com/webview?token=eyJhbGciOiJIUzI1...
|
|
116
|
-
* ```
|
|
117
|
-
*/
|
|
118
|
-
function generateWebviewUrl(baseUrl, token) {
|
|
119
|
-
const url = new URL(baseUrl);
|
|
120
|
-
url.searchParams.append('token', token);
|
|
121
|
-
return url.toString();
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Extract a App token from a URL
|
|
125
|
-
*
|
|
126
|
-
* @param url - URL string containing a token parameter
|
|
127
|
-
* @returns Token string or null if not found
|
|
128
|
-
*
|
|
129
|
-
* @example
|
|
130
|
-
* ```typescript
|
|
131
|
-
* const token = extractTokenFromUrl(
|
|
132
|
-
* 'https://example.com/webview?token=eyJhbGciOiJIUzI1...'
|
|
133
|
-
* );
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
136
|
-
function extractTokenFromUrl(url) {
|
|
137
|
-
try {
|
|
138
|
-
const parsedUrl = new URL(url);
|
|
139
|
-
return parsedUrl.searchParams.get('token');
|
|
140
|
-
}
|
|
141
|
-
catch (error) {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
@@ -1,382 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.extractTempToken = extractTempToken;
|
|
40
|
-
exports.exchangeToken = exchangeToken;
|
|
41
|
-
exports.createAuthMiddleware = createAuthMiddleware;
|
|
42
|
-
// src/app/webview/index.ts
|
|
43
|
-
const axios_1 = __importDefault(require("axios"));
|
|
44
|
-
// Note: Your Express app needs to use cookie-parser middleware for this to work
|
|
45
|
-
// Example: app.use(require('cookie-parser')());
|
|
46
|
-
const crypto = __importStar(require("crypto"));
|
|
47
|
-
const jsrsasign_1 = require("jsrsasign");
|
|
48
|
-
const userTokenPublicKey = process.env.MENTRAOS_CLOUD_USER_TOKEN_PUBLIC_KEY ||
|
|
49
|
-
"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Yt2RtNOdeKQxWMY0c84\nADpY1Jy58YWZhaEgP2A5tBwFUKgy/TH9gQLWZjQ3dQ/6XXO8qq0kluoYFqM7ZDRF\nzJ0E4Yi0WQncioLRcCx4q8pDmqY9vPKgv6PruJdFWca0l0s3gZ3BqSeWum/C23xK\nFPHPwi8gvRdc6ALrkcHeciM+7NykU8c0EY8PSitNL+Tchti95kGu+j6APr5vNewi\nzRpQGOdqaLWe+ahHmtj6KtUZjm8o6lan4f/o08C6litizguZXuw2Nn/Kd9fFI1xF\nIVNJYMy9jgGaOi71+LpGw+vIpwAawp/7IvULDppvY3DdX5nt05P1+jvVJXPxMKzD\nTQIDAQAB\n-----END PUBLIC KEY-----";
|
|
50
|
-
/**
|
|
51
|
-
* Extracts the temporary token from a URL string.
|
|
52
|
-
* @param url The URL string, typically window.location.href.
|
|
53
|
-
* @returns The token string or null if not found.
|
|
54
|
-
*/
|
|
55
|
-
function extractTempToken(url) {
|
|
56
|
-
try {
|
|
57
|
-
const parsedUrl = new URL(url);
|
|
58
|
-
return parsedUrl.searchParams.get("aos_temp_token");
|
|
59
|
-
}
|
|
60
|
-
catch (e) {
|
|
61
|
-
console.error("Error parsing URL for temp token:", e);
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Exchanges a temporary token for a user ID with the MentraOS Cloud.
|
|
67
|
-
* This should be called from the App's backend server.
|
|
68
|
-
* @param cloudApiUrl The base URL of the MentraOS Cloud API.
|
|
69
|
-
* @param tempToken The temporary token obtained from the webview URL.
|
|
70
|
-
* @param apiKey Your App's secret API key.
|
|
71
|
-
* @returns A Promise that resolves with an object containing the userId.
|
|
72
|
-
* @throws Throws an error if the exchange fails (e.g., invalid token, expired, network error).
|
|
73
|
-
*/
|
|
74
|
-
async function exchangeToken(cloudApiUrl, tempToken, apiKey, packageName) {
|
|
75
|
-
const endpoint = `${cloudApiUrl}/api/auth/exchange-user-token`;
|
|
76
|
-
console.log(`Exchanging token for user at ${endpoint}`);
|
|
77
|
-
try {
|
|
78
|
-
const response = await axios_1.default.post(endpoint, { aos_temp_token: tempToken, packageName: packageName }, {
|
|
79
|
-
headers: {
|
|
80
|
-
"Content-Type": "application/json",
|
|
81
|
-
Authorization: `Bearer ${apiKey}`,
|
|
82
|
-
},
|
|
83
|
-
timeout: 10000, // 10 second timeout
|
|
84
|
-
});
|
|
85
|
-
if (response.status === 200 &&
|
|
86
|
-
response.data.success &&
|
|
87
|
-
response.data.userId) {
|
|
88
|
-
return { userId: response.data.userId };
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
// Handle specific error messages from the server if available
|
|
92
|
-
const errorMessage = response.data?.error || `Failed with status ${response.status}`;
|
|
93
|
-
throw new Error(errorMessage);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
catch (error) {
|
|
97
|
-
if (axios_1.default.isAxiosError(error)) {
|
|
98
|
-
const status = error.response?.status;
|
|
99
|
-
const data = error.response?.data;
|
|
100
|
-
const message = data?.error || error.message || "Unknown error during token exchange";
|
|
101
|
-
console.error(`Token exchange failed with status ${status}: ${message}`);
|
|
102
|
-
throw new Error(`Token exchange failed: ${message}`);
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
console.error("Unexpected error during token exchange:", error);
|
|
106
|
-
throw new Error("An unexpected error occurred during token exchange.");
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Signs a user ID to create a secure session token.
|
|
112
|
-
* @param userId The user ID to sign
|
|
113
|
-
* @param secret The secret key used for signing
|
|
114
|
-
* @returns A signed session token string
|
|
115
|
-
*/
|
|
116
|
-
function signSession(userId, secret) {
|
|
117
|
-
// Format: userId.timestamp.signature
|
|
118
|
-
const timestamp = Date.now();
|
|
119
|
-
const data = `${userId}|${timestamp}`;
|
|
120
|
-
const signature = crypto
|
|
121
|
-
.createHmac("sha256", secret)
|
|
122
|
-
.update(data)
|
|
123
|
-
.digest("hex");
|
|
124
|
-
return `${data}|${signature}`;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Verifies and extracts the user ID from a signed session token.
|
|
128
|
-
* @param token The signed session token
|
|
129
|
-
* @param secret The secret key used for verification
|
|
130
|
-
* @param maxAge The maximum age of the token in milliseconds
|
|
131
|
-
* @returns The extracted user ID if valid, or null if invalid
|
|
132
|
-
*/
|
|
133
|
-
function verifySession(token, secret, maxAge) {
|
|
134
|
-
try {
|
|
135
|
-
const parts = token.split("|");
|
|
136
|
-
if (parts.length !== 3)
|
|
137
|
-
return null;
|
|
138
|
-
const [userId, timestampStr, signature] = parts;
|
|
139
|
-
const timestamp = parseInt(timestampStr, 10);
|
|
140
|
-
// Check if token has expired
|
|
141
|
-
if (maxAge && Date.now() - timestamp > maxAge) {
|
|
142
|
-
console.log(`Session token expired: ${token}. Parsed date is ${timestamp}, meaning age is ${Date.now() - timestamp}, but maxAge is ${maxAge}`);
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
// Verify signature
|
|
146
|
-
const data = `${userId}|${timestamp}`;
|
|
147
|
-
const expectedSignature = crypto
|
|
148
|
-
.createHmac("sha256", secret)
|
|
149
|
-
.update(data)
|
|
150
|
-
.digest("hex");
|
|
151
|
-
if (signature !== expectedSignature) {
|
|
152
|
-
console.log(`Session token signature mismatch: ${signature} !== ${expectedSignature}`);
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
return userId;
|
|
156
|
-
}
|
|
157
|
-
catch (error) {
|
|
158
|
-
console.error("Session verification failed:", error);
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Verifies a signed user token and extracts the user ID from it
|
|
164
|
-
* @param signedUserToken The JWT token to verify
|
|
165
|
-
* @returns The user ID (subject) from the token, or null if invalid
|
|
166
|
-
*/
|
|
167
|
-
async function verifySignedUserToken(signedUserToken) {
|
|
168
|
-
try {
|
|
169
|
-
// 1. Parse the PEM public key into a jsrsasign key object
|
|
170
|
-
const publicKeyObj = jsrsasign_1.KEYUTIL.getKey(userTokenPublicKey);
|
|
171
|
-
// 2. Verify JWT signature + claims (issuer, exp, iat) with 2-min tolerance
|
|
172
|
-
const isValid = jsrsasign_1.KJUR.jws.JWS.verifyJWT(signedUserToken, publicKeyObj, {
|
|
173
|
-
alg: ["RS256"],
|
|
174
|
-
iss: ["https://prod.augmentos.cloud"],
|
|
175
|
-
verifyAt: jsrsasign_1.KJUR.jws.IntDate.get("now"),
|
|
176
|
-
gracePeriod: 120,
|
|
177
|
-
});
|
|
178
|
-
if (!isValid)
|
|
179
|
-
return null;
|
|
180
|
-
// 3. Decode payload and return the subject (user ID)
|
|
181
|
-
const parsed = jsrsasign_1.KJUR.jws.JWS.parse(signedUserToken);
|
|
182
|
-
return parsed.payloadObj.sub || null;
|
|
183
|
-
}
|
|
184
|
-
catch (e) {
|
|
185
|
-
console.error("[verifySignedUserToken] Error verifying token:", e);
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Verifies a frontend token by comparing it to a secure hash of the API key
|
|
191
|
-
* @param frontendToken The token to verify (should be a hash of the API key)
|
|
192
|
-
* @param apiKey The API key to hash and compare against
|
|
193
|
-
* @param userId Optional user ID that may be embedded in the token format
|
|
194
|
-
* @returns The user ID if the token is valid, or null if invalid
|
|
195
|
-
*/
|
|
196
|
-
function verifyFrontendToken(frontendToken, apiKey) {
|
|
197
|
-
try {
|
|
198
|
-
// Check if the token contains a user ID and hash separated by a colon
|
|
199
|
-
const tokenParts = frontendToken.split(":");
|
|
200
|
-
if (tokenParts.length === 2) {
|
|
201
|
-
// Format: userId:hash
|
|
202
|
-
const [tokenUserId, tokenHash] = tokenParts;
|
|
203
|
-
// Align the hashing algorithm with server-side `hashWithApiKey`
|
|
204
|
-
// 1. Hash the API key first (server only stores the hashed version)
|
|
205
|
-
const hashedApiKey = crypto
|
|
206
|
-
.createHash("sha256")
|
|
207
|
-
.update(apiKey)
|
|
208
|
-
.digest("hex");
|
|
209
|
-
// 2. Create the expected hash using userId + hashedApiKey (same order & update calls)
|
|
210
|
-
const expectedHash = crypto
|
|
211
|
-
.createHash("sha256")
|
|
212
|
-
.update(tokenUserId)
|
|
213
|
-
.update(hashedApiKey)
|
|
214
|
-
.digest("hex");
|
|
215
|
-
if (tokenHash === expectedHash) {
|
|
216
|
-
return tokenUserId;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
throw new Error("Invalid frontend token format");
|
|
221
|
-
}
|
|
222
|
-
return null;
|
|
223
|
-
}
|
|
224
|
-
catch (error) {
|
|
225
|
-
console.error("Frontend token verification failed:", error);
|
|
226
|
-
return null;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
function validateCloudApiUrlChecksum(checksum, cloudApiUrl, apiKey) {
|
|
230
|
-
const hashedApiKey = crypto.createHash("sha256").update(apiKey).digest("hex");
|
|
231
|
-
const expectedChecksum = crypto
|
|
232
|
-
.createHash("sha256")
|
|
233
|
-
.update(cloudApiUrl)
|
|
234
|
-
.update(hashedApiKey)
|
|
235
|
-
.digest("hex");
|
|
236
|
-
return expectedChecksum === checksum;
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Express middleware for automatically handling the token exchange.
|
|
240
|
-
* Assumes API key and Cloud URL are available (e.g., via environment variables).
|
|
241
|
-
* Adds `req.authUserId` if successful.
|
|
242
|
-
*
|
|
243
|
-
* @param options Configuration options.
|
|
244
|
-
* @param options.cloudApiUrl The base URL of the MentraOS Cloud API.
|
|
245
|
-
* @param options.apiKey Your App's secret API key.
|
|
246
|
-
* @param options.tokenQueryParam The name of the query parameter containing the token (default: 'aos_temp_token').
|
|
247
|
-
* @param options.cookieName The name of the cookie to store the session token (default: 'aos_session').
|
|
248
|
-
* @param options.cookieSecret Secret key used to sign the session cookie. MUST be provided and kept secure.
|
|
249
|
-
* @param options.cookieOptions Options for the session cookie (default: { httpOnly: true, secure: process.env.NODE_ENV === 'production' }).
|
|
250
|
-
*/
|
|
251
|
-
function createAuthMiddleware(options) {
|
|
252
|
-
const { apiKey, packageName, cookieName = "aos_session", cookieSecret, getAppSessionForUser, cookieOptions = {
|
|
253
|
-
httpOnly: true,
|
|
254
|
-
secure: process.env.NODE_ENV === "production",
|
|
255
|
-
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days by default
|
|
256
|
-
sameSite: process.env.NODE_ENV === "production" ? "none" : "lax",
|
|
257
|
-
path: "/",
|
|
258
|
-
}, } = options;
|
|
259
|
-
if (!apiKey) {
|
|
260
|
-
throw new Error("API Key are required for the auth middleware.");
|
|
261
|
-
}
|
|
262
|
-
if (!cookieSecret ||
|
|
263
|
-
typeof cookieSecret !== "string" ||
|
|
264
|
-
cookieSecret.length < 8) {
|
|
265
|
-
throw new Error("A strong cookieSecret (at least 8 characters) is required for secure session management.");
|
|
266
|
-
}
|
|
267
|
-
return async (req, res, next) => {
|
|
268
|
-
// First check for temporary token in the query string
|
|
269
|
-
const tempToken = req.query["aos_temp_token"];
|
|
270
|
-
const frontendToken = req.headers.authorization?.replace("Bearer ", "") ||
|
|
271
|
-
req.query["aos_frontend_token"];
|
|
272
|
-
const signedUserToken = req.query["aos_signed_user_token"];
|
|
273
|
-
// first check for signed user token
|
|
274
|
-
if (signedUserToken) {
|
|
275
|
-
const userId = await verifySignedUserToken(signedUserToken);
|
|
276
|
-
if (userId) {
|
|
277
|
-
// Set the user ID on the request
|
|
278
|
-
req.authUserId = userId;
|
|
279
|
-
if (getAppSessionForUser) {
|
|
280
|
-
const appSession = getAppSessionForUser(userId);
|
|
281
|
-
if (appSession) {
|
|
282
|
-
req.activeSession = appSession;
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
req.activeSession = null;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
// Create a signed session token and store it in a cookie
|
|
289
|
-
const signedSession = signSession(userId, cookieSecret);
|
|
290
|
-
res.cookie(cookieName, signedSession, cookieOptions);
|
|
291
|
-
console.log("[auth.middleware] User ID verified from signed user token: ", userId);
|
|
292
|
-
return next();
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
console.log("[auth.middleware] Signed user token invalid");
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
// If temporary token exists, authenticate with it
|
|
299
|
-
if (tempToken) {
|
|
300
|
-
try {
|
|
301
|
-
let cloudApiUrl = `https://api.mentra.glass`;
|
|
302
|
-
const cloudApiUrlFromQuery = req.query["cloudApiUrl"];
|
|
303
|
-
if (cloudApiUrlFromQuery) {
|
|
304
|
-
const cloudApiUrlChecksum = req.query["cloudApiUrlChecksum"];
|
|
305
|
-
if (validateCloudApiUrlChecksum(cloudApiUrlChecksum, cloudApiUrlFromQuery, apiKey)) {
|
|
306
|
-
console.log(`Cloud API is being routed to alternate url at request of the server: ${cloudApiUrlFromQuery}`);
|
|
307
|
-
cloudApiUrl = cloudApiUrlFromQuery;
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
310
|
-
console.error(`Server requested alternate cloud url of ${cloudApiUrlFromQuery} but the checksum is invalid (checksum: ${cloudApiUrlChecksum}). Using default cloud url of ${cloudApiUrl} instead.`);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
const { userId } = await exchangeToken(cloudApiUrl, tempToken, apiKey, packageName);
|
|
314
|
-
// Set the user ID on the request
|
|
315
|
-
req.authUserId = userId;
|
|
316
|
-
if (getAppSessionForUser) {
|
|
317
|
-
const appSession = getAppSessionForUser(userId);
|
|
318
|
-
if (appSession) {
|
|
319
|
-
req.activeSession = appSession;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
// Create a signed session token and store it in a cookie
|
|
323
|
-
const signedSession = signSession(userId, cookieSecret);
|
|
324
|
-
res.cookie(cookieName, signedSession, cookieOptions);
|
|
325
|
-
console.log("[auth.middleware] User ID verified from temporary token: ", userId);
|
|
326
|
-
return next();
|
|
327
|
-
}
|
|
328
|
-
catch (error) {
|
|
329
|
-
console.error("Webview token exchange failed:", error);
|
|
330
|
-
// Temporary token is invalid
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
if (frontendToken) {
|
|
334
|
-
// Check for user ID in headers if not embedded in token
|
|
335
|
-
const userId = verifyFrontendToken(frontendToken, apiKey);
|
|
336
|
-
if (userId) {
|
|
337
|
-
req.authUserId = userId;
|
|
338
|
-
if (getAppSessionForUser) {
|
|
339
|
-
const appSession = getAppSessionForUser(userId);
|
|
340
|
-
if (appSession) {
|
|
341
|
-
req.activeSession = appSession;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
// Create a signed session token and store it in a cookie
|
|
345
|
-
const signedSession = signSession(userId, cookieSecret);
|
|
346
|
-
res.cookie(cookieName, signedSession, cookieOptions);
|
|
347
|
-
console.log("[auth.middleware] User ID verified from frontend user token: ", userId);
|
|
348
|
-
return next();
|
|
349
|
-
}
|
|
350
|
-
else {
|
|
351
|
-
console.log("[auth.middleware] Frontend token invalid");
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
// No valid temporary token, check for existing session cookie
|
|
355
|
-
const sessionCookie = req.cookies?.[cookieName];
|
|
356
|
-
if (sessionCookie) {
|
|
357
|
-
try {
|
|
358
|
-
// Verify the signed session cookie and extract the user ID
|
|
359
|
-
const userId = verifySession(sessionCookie, cookieSecret, cookieOptions.maxAge);
|
|
360
|
-
if (userId) {
|
|
361
|
-
req.authUserId = userId;
|
|
362
|
-
if (getAppSessionForUser) {
|
|
363
|
-
const appSession = getAppSessionForUser(userId);
|
|
364
|
-
if (appSession) {
|
|
365
|
-
req.activeSession = appSession;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
return next();
|
|
369
|
-
}
|
|
370
|
-
// Invalid or expired session, clear the cookie
|
|
371
|
-
res.clearCookie(cookieName, { path: cookieOptions.path });
|
|
372
|
-
}
|
|
373
|
-
catch (error) {
|
|
374
|
-
console.error("Invalid session cookie:", error);
|
|
375
|
-
// Clear the invalid cookie
|
|
376
|
-
res.clearCookie(cookieName, { path: cookieOptions.path });
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
// No valid authentication method found, proceed without setting req.authUserId
|
|
380
|
-
next();
|
|
381
|
-
};
|
|
382
|
-
}
|
package/dist/constants/index.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Constants for the SDK
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.systemApps = void 0;
|
|
7
|
-
/**
|
|
8
|
-
* System app definitions
|
|
9
|
-
*/
|
|
10
|
-
exports.systemApps = {
|
|
11
|
-
dashboard: {
|
|
12
|
-
name: 'Dashboard',
|
|
13
|
-
packageName: 'system.augmentos.dashboard',
|
|
14
|
-
isSystemApp: true
|
|
15
|
-
},
|
|
16
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.green = green;
|
|
4
|
-
exports.yellow = yellow;
|
|
5
|
-
exports.red = red;
|
|
6
|
-
function green(text) {
|
|
7
|
-
return `\x1b[32m${text}\x1b[0m`;
|
|
8
|
-
}
|
|
9
|
-
function yellow(text) {
|
|
10
|
-
return `\x1b[33m${text}\x1b[0m`;
|
|
11
|
-
}
|
|
12
|
-
function red(text) {
|
|
13
|
-
return `\x1b[31m${text}\x1b[0m`;
|
|
14
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.newUpdateText = exports.mentraLogo_1 = exports.warnLog = void 0;
|
|
4
|
-
exports.warnLog = String.raw `
|
|
5
|
-
__/\\\\____________/\\\\_
|
|
6
|
-
_\/\\\\\\________/\\\\\\_
|
|
7
|
-
_\/\\\//\\\____/\\\//\\\_
|
|
8
|
-
_\/\\\\///\\\/\\\/_\/\\\_
|
|
9
|
-
_\/\\\__\///\\\/___\/\\\_
|
|
10
|
-
_\/\\\____\///_____\/\\\_
|
|
11
|
-
_\/\\\_____________\/\\\_
|
|
12
|
-
_\/\\\_____________\/\\\_
|
|
13
|
-
_\///______________\///__`;
|
|
14
|
-
exports.mentraLogo_1 = String.raw `
|
|
15
|
-
__ __ ________ __ __ ________ _______ ______
|
|
16
|
-
| \ / \| \| \ | \| \| \ / \
|
|
17
|
-
| $$\ / $$| $$$$$$$$| $$\ | $$ \$$$$$$$$| $$$$$$$\| $$$$$$\
|
|
18
|
-
| $$$\ / $$$| $$__ | $$$\| $$ | $$ | $$__| $$| $$__| $$
|
|
19
|
-
| $$$$\ $$$$| $$ \ | $$$$\ $$ | $$ | $$ $$| $$ $$
|
|
20
|
-
| $$\$$ $$ $$| $$$$$ | $$\$$ $$ | $$ | $$$$$$$\| $$$$$$$$
|
|
21
|
-
| $$ \$$$| $$| $$_____ | $$ \$$$$ | $$ | $$ | $$| $$ | $$
|
|
22
|
-
| $$ \$ | $$| $$ \| $$ \$$$ | $$ | $$ | $$| $$ | $$
|
|
23
|
-
\$$ \$$ \$$$$$$$$ \$$ \$$ \$$ \$$ \$$ \$$ \$$
|
|
24
|
-
`;
|
|
25
|
-
exports.newUpdateText = `
|
|
26
|
-
┬╔╗╔╔═╗╦ ╦ ╦ ╦╔═╗╔╦╗╔═╗╔╦╗╔═╗┬
|
|
27
|
-
│║║║║╣ ║║║ ║ ║╠═╝ ║║╠═╣ ║ ║╣ │
|
|
28
|
-
o╝╚╝╚═╝╚╩╝ ╚═╝╩ ═╩╝╩ ╩ ╩ ╚═╝o
|
|
29
|
-
`;
|
|
30
|
-
// export const newSDKUpdate = (versionNumb: string): string => {
|
|
31
|
-
// return `
|
|
32
|
-
// /$$ /$$ /$$$$$$$$ /$$ /$$ /$$$$$$$$ /$$$$$$$ /$$$$$$
|
|
33
|
-
// | $$$ /$$$| $$_____/| $$$ | $$|__ $$__/| $$__ $$ /$$__ $$
|
|
34
|
-
// | $$$$ /$$$$| $$ | $$$$| $$ | $$ | $$ \ $$| $$ \ $$
|
|
35
|
-
// | $$ $$/$$ $$| $$$$$ | $$ $$ $$ | $$ | $$$$$$$/| $$$$$$$$
|
|
36
|
-
// | $$ $$$| $$| $$__/ | $$ $$$$ | $$ | $$__ $$| $$__ $$
|
|
37
|
-
// | $$\ $ | $$| $$ | $$\ $$$ | $$ | $$ \ $$| $$ | $$
|
|
38
|
-
// | $$ \/ | $$| $$$$$$$$| $$ \ $$ | $$ | $$ | $$| $$ | $$
|
|
39
|
-
// |__/ |__/|________/|__/ \__/ |__/ |__/ |__/|__/ |__/
|
|
40
|
-
// ┬╔╗╔╔═╗╦ ╦ ╦ ╦╔═╗╔╦╗╔═╗╔╦╗╔═╗┬
|
|
41
|
-
// │║║║║╣ ║║║ ║ ║╠═╝ ║║╠═╣ ║ ║╣ │
|
|
42
|
-
// o╝╚╝╚═╝╚╩╝ ╚═╝╩ ═╩╝╩ ╩ ╩ ╚═╝o
|
|
43
|
-
// -------------------------------
|
|
44
|
-
// SDK VERSION V${versionNumb} is out!
|
|
45
|
-
// -------------------------------
|
|
46
|
-
// bun install @mentra/sdk@latest
|
|
47
|
-
// `;
|
|
48
|
-
// };
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* updates.ts
|
|
4
|
-
*
|
|
5
|
-
* This file defines constant messages that should be displayed
|
|
6
|
-
* in the terminal to notify developers about new SDK releases.
|
|
7
|
-
*
|
|
8
|
-
* Each function generates a stylized ASCII message (banner-style)
|
|
9
|
-
* that highlights the latest SDK version and provides the npm install command.
|
|
10
|
-
* https://patorjk.com/software/taag/
|
|
11
|
-
*
|
|
12
|
-
* These messages are intended to be logged to the console or shown in
|
|
13
|
-
* terminal output so developers are aware of updates in a clear
|
|
14
|
-
* and visually distinct way.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*/
|
|
18
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
19
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
20
|
-
};
|
|
21
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.newSDKUpdate = void 0;
|
|
23
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
24
|
-
const boxen_1 = __importDefault(require("boxen"));
|
|
25
|
-
const logos_1 = require("./logos");
|
|
26
|
-
const createUpdateNotification = (versionNumb) => {
|
|
27
|
-
const line = chalk_1.default.bold.gray("-------------------------------");
|
|
28
|
-
const logo = chalk_1.default.cyan(logos_1.mentraLogo_1);
|
|
29
|
-
const title = chalk_1.default.bold.cyan(logos_1.newUpdateText);
|
|
30
|
-
const versionMessage = `Version ${chalk_1.default.bold.cyan(`SDK VERSION V${versionNumb} is out! 🎉`)}`;
|
|
31
|
-
const currentNote = chalk_1.default.yellow("You are running an older version");
|
|
32
|
-
const instructions = chalk_1.default.yellow("Update to the latest version with:");
|
|
33
|
-
const command = chalk_1.default.green.bold("bun install @mentra/sdk@latest");
|
|
34
|
-
const content = [
|
|
35
|
-
logo,
|
|
36
|
-
title,
|
|
37
|
-
line,
|
|
38
|
-
versionMessage,
|
|
39
|
-
currentNote,
|
|
40
|
-
line,
|
|
41
|
-
instructions,
|
|
42
|
-
command,
|
|
43
|
-
].join("\n");
|
|
44
|
-
return (0, boxen_1.default)(content, {
|
|
45
|
-
padding: 1,
|
|
46
|
-
margin: 1,
|
|
47
|
-
borderStyle: "round",
|
|
48
|
-
borderColor: "cyan",
|
|
49
|
-
textAlignment: "left",
|
|
50
|
-
});
|
|
51
|
-
};
|
|
52
|
-
const newSDKUpdate = (versionNumb) => {
|
|
53
|
-
return createUpdateNotification(versionNumb);
|
|
54
|
-
};
|
|
55
|
-
exports.newSDKUpdate = newSDKUpdate;
|