@openinc/parse-server-opendash 3.9.7 → 3.10.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.
@@ -8,38 +8,132 @@ const crypto_1 = require("crypto");
8
8
  const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
9
9
  const jwks_rsa_1 = __importDefault(require("jwks-rsa"));
10
10
  const config_1 = require("../features/config");
11
- const tenantId = config_1.ConfigInstance.getInstance().get("MICROSOFT_TENANT_ID");
12
- const appId = config_1.ConfigInstance.getInstance().get("MICROSOFT_APP_ID");
13
- // Setup JWKS client for Microsoft (replace TENANT_ID)
11
+ const types_1 = require("../types");
12
+ const tenantId = config_1.ConfigInstance.getInstance().get("MICROSOFT_TENANT_ID") ||
13
+ process.env.MICROSOFT_TENANT_ID ||
14
+ process.env.OI_MICROSOFT_TENANT_ID;
15
+ const appId = config_1.ConfigInstance.getInstance().get("MICROSOFT_APP_ID") ||
16
+ process.env.MICROSOFT_APP_ID ||
17
+ process.env.OI_MICROSOFT_APP_ID;
18
+ // Setup JWKS client for Microsoft - try v2.0 first, fallback to v1.0
19
+ const getJwksUri = (version = "v2.0") => `https://login.microsoftonline.com/${tenantId}/discovery/${version}/keys`;
14
20
  const client = (0, jwks_rsa_1.default)({
15
- jwksUri: `https://login.microsoftonline.com/${tenantId}/discovery/v2.0/keys`,
21
+ jwksUri: getJwksUri(),
22
+ cache: true,
23
+ cacheMaxEntries: 5,
24
+ cacheMaxAge: 1000 * 60 * 60 * 24, // 24 hours
25
+ timeout: 30000, // 30 seconds
26
+ });
27
+ // Fallback client for v1.0 if v2.0 fails
28
+ const clientV1 = (0, jwks_rsa_1.default)({
29
+ jwksUri: getJwksUri("v1.0"),
30
+ cache: true,
31
+ cacheMaxEntries: 5,
32
+ cacheMaxAge: 1000 * 60 * 60 * 24, // 24 hours
33
+ timeout: 30000, // 30 seconds
16
34
  });
17
35
  function getKey(header, callback) {
36
+ console.log("JWT Header:", header);
37
+ console.log("Tenant ID:", tenantId);
38
+ console.log("App ID:", appId);
18
39
  if (!header.kid) {
40
+ console.error("No kid found in token header");
19
41
  return callback(new Error("No kid found in token header"));
20
42
  }
43
+ console.log("Attempting to get signing key for kid:", header.kid);
21
44
  client.getSigningKey(header.kid, (err, key) => {
22
- if (err || !key) {
23
- return callback(err || new Error("Key not found"));
45
+ if (err) {
46
+ console.error("Error with v2.0 endpoint, trying v1.0:", err);
47
+ // Try v1.0 endpoint as fallback
48
+ clientV1.getSigningKey(header.kid, (errV1, keyV1) => {
49
+ if (errV1) {
50
+ console.error("Error with v1.0 endpoint:", errV1);
51
+ return callback(errV1);
52
+ }
53
+ if (!keyV1) {
54
+ console.error("No key returned from v1.0 JWKS client");
55
+ return callback(new Error("Key not found in v1.0 endpoint"));
56
+ }
57
+ try {
58
+ const signingKey = keyV1.getPublicKey();
59
+ console.log("Successfully retrieved signing key from v1.0 endpoint");
60
+ callback(null, signingKey);
61
+ }
62
+ catch (keyError) {
63
+ console.error("Error extracting public key from v1.0:", keyError);
64
+ callback(keyError instanceof Error ? keyError : new Error(String(keyError)));
65
+ }
66
+ });
67
+ return;
68
+ }
69
+ if (!key) {
70
+ console.error("No key returned from JWKS client");
71
+ return callback(new Error("Key not found"));
72
+ }
73
+ try {
74
+ const signingKey = key.getPublicKey();
75
+ console.log("Successfully retrieved signing key");
76
+ callback(null, signingKey);
77
+ }
78
+ catch (keyError) {
79
+ console.error("Error extracting public key:", keyError);
80
+ callback(keyError instanceof Error ? keyError : new Error(String(keyError)));
24
81
  }
25
- const signingKey = key.getPublicKey();
26
- callback(null, signingKey);
27
82
  });
28
83
  }
29
84
  async function init(name) {
30
85
  Parse.Cloud.define(name, async (request) => {
31
86
  const token = request.params.token;
32
87
  const account = request.params.account;
88
+ const defaultTenant = await new Parse.Query(types_1.Tenant)
89
+ .ascending("createdAt")
90
+ .first({ useMasterKey: true });
33
91
  if (!token) {
34
92
  throw new Parse.Error(Parse.Error.INVALID_JSON, "Token missing");
35
93
  }
94
+ // Validate Microsoft configuration
95
+ if (!tenantId || !appId) {
96
+ console.error("Missing Microsoft configuration:", {
97
+ tenantId: !!tenantId,
98
+ appId: !!appId,
99
+ });
100
+ throw new Parse.Error(Parse.Error.INVALID_JSON, "Microsoft authentication not properly configured");
101
+ }
36
102
  const verifiedPayload = await new Promise((resolve, reject) => {
103
+ console.log("Starting JWT verification...");
104
+ console.log("Token length:", token.length);
105
+ console.log("Expected audience:", appId);
106
+ console.log("Expected issuer:", `https://login.microsoftonline.com/${tenantId}/v2.0`);
107
+ // Decode token payload for debugging (without verification)
108
+ try {
109
+ const tokenParts = token.split(".");
110
+ if (tokenParts.length === 3) {
111
+ const header = JSON.parse(Buffer.from(tokenParts[0], "base64").toString());
112
+ const payload = JSON.parse(Buffer.from(tokenParts[1], "base64").toString());
113
+ console.log("Token header (unverified):", header);
114
+ console.log("Token payload (unverified):", {
115
+ aud: payload.aud,
116
+ iss: payload.iss,
117
+ tid: payload.tid,
118
+ ver: payload.ver,
119
+ });
120
+ }
121
+ }
122
+ catch (decodeError) {
123
+ console.error("Failed to decode token for debugging:", decodeError);
124
+ }
37
125
  jsonwebtoken_1.default.verify(token, getKey, {
38
126
  audience: appId,
39
127
  issuer: `https://login.microsoftonline.com/${tenantId}/v2.0`,
128
+ algorithms: ["RS256"], // Microsoft uses RS256
40
129
  }, (err, decoded) => {
41
- if (err)
130
+ if (err) {
131
+ console.error("JWT verification failed:", err);
132
+ console.error("Error name:", err.name);
133
+ console.error("Error message:", err.message);
42
134
  return reject(err);
135
+ }
136
+ console.log("JWT verification successful");
43
137
  resolve(decoded);
44
138
  });
45
139
  });
@@ -52,6 +146,7 @@ async function init(name) {
52
146
  user.set("email", account.username);
53
147
  user.set("password", (0, crypto_1.randomBytes)(16).toString("hex")); // Generate a random password
54
148
  user.set("name", verifiedPayload.name || verifiedPayload.preferred_username);
149
+ user.set("tenant", defaultTenant);
55
150
  user = await user.signUp(null, { useMasterKey: true });
56
151
  return user.getSessionToken();
57
152
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openinc/parse-server-opendash",
3
- "version": "3.9.7",
3
+ "version": "3.10.0",
4
4
  "description": "Parse Server Cloud Code for open.INC Stack.",
5
5
  "packageManager": "pnpm@10.13.1",
6
6
  "keywords": [