@openinc/parse-server-opendash 3.10.2 → 3.10.4
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.
|
@@ -15,129 +15,67 @@ const tenantId = config_1.ConfigInstance.getInstance().get("MICROSOFT_TENANT_ID"
|
|
|
15
15
|
const appId = config_1.ConfigInstance.getInstance().get("MICROSOFT_APP_ID") ||
|
|
16
16
|
process.env.MICROSOFT_APP_ID ||
|
|
17
17
|
process.env.OI_MICROSOFT_APP_ID;
|
|
18
|
-
//
|
|
19
|
-
const getJwksUri = (version = "v2.0") => `https://login.microsoftonline.com/${tenantId}/discovery/${version}/keys`;
|
|
18
|
+
// Simple, standard Microsoft v2.0 endpoint with app-specific parameter
|
|
20
19
|
const client = (0, jwks_rsa_1.default)({
|
|
21
|
-
jwksUri:
|
|
20
|
+
jwksUri: `https://login.microsoftonline.com/${tenantId}/discovery/keys?appid=${appId}`,
|
|
22
21
|
cache: true,
|
|
23
|
-
|
|
24
|
-
|
|
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
|
|
22
|
+
cacheMaxAge: 12 * 60 * 60 * 1000, // 12 hours
|
|
23
|
+
timeout: 30000,
|
|
34
24
|
});
|
|
35
25
|
function getKey(header, callback) {
|
|
36
|
-
console.log("JWT Header:", header);
|
|
37
|
-
console.log("Tenant ID:", tenantId);
|
|
38
|
-
console.log("App ID:", appId);
|
|
39
26
|
if (!header.kid) {
|
|
40
|
-
console.error("No kid found in token header");
|
|
41
27
|
return callback(new Error("No kid found in token header"));
|
|
42
28
|
}
|
|
43
|
-
console.log("Attempting to get signing key for kid:", header.kid);
|
|
44
29
|
client.getSigningKey(header.kid, (err, key) => {
|
|
45
|
-
if (err)
|
|
46
|
-
|
|
47
|
-
|
|
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");
|
|
30
|
+
if (err)
|
|
31
|
+
return callback(err);
|
|
32
|
+
if (!key)
|
|
71
33
|
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)));
|
|
81
|
-
}
|
|
34
|
+
callback(null, key.getPublicKey());
|
|
82
35
|
});
|
|
83
36
|
}
|
|
84
37
|
async function init(name) {
|
|
85
38
|
Parse.Cloud.define(name, async (request) => {
|
|
86
|
-
console.log("Logging in with microsoft...");
|
|
87
39
|
const token = request.params.token;
|
|
88
40
|
const account = request.params.account;
|
|
89
|
-
const defaultTenant = await new Parse.Query(types_1.Tenant)
|
|
90
|
-
.ascending("createdAt")
|
|
91
|
-
.first({ useMasterKey: true });
|
|
92
41
|
if (!token) {
|
|
93
42
|
throw new Parse.Error(Parse.Error.INVALID_JSON, "Token missing");
|
|
94
43
|
}
|
|
95
|
-
// Validate Microsoft configuration
|
|
96
44
|
if (!tenantId || !appId) {
|
|
97
|
-
console.error("Missing Microsoft configuration:", {
|
|
98
|
-
tenantId: !!tenantId,
|
|
99
|
-
appId: !!appId,
|
|
100
|
-
});
|
|
101
45
|
throw new Parse.Error(Parse.Error.INVALID_JSON, "Microsoft authentication not properly configured");
|
|
102
46
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
47
|
+
// DEBUGGING: Decode token without verification to see what we're dealing with
|
|
48
|
+
console.log("=== DEBUGGING TOKEN ===");
|
|
49
|
+
try {
|
|
50
|
+
const tokenParts = token.split(".");
|
|
51
|
+
const payload = JSON.parse(Buffer.from(tokenParts[1], "base64").toString());
|
|
52
|
+
console.log("Token audience (aud):", payload.aud);
|
|
53
|
+
console.log("Token issuer (iss):", payload.iss);
|
|
106
54
|
console.log("Expected audience:", appId);
|
|
107
55
|
console.log("Expected issuer:", `https://login.microsoftonline.com/${tenantId}/v2.0`);
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
aud: payload.aud,
|
|
117
|
-
iss: payload.iss,
|
|
118
|
-
tid: payload.tid,
|
|
119
|
-
ver: payload.ver,
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
catch (decodeError) {
|
|
124
|
-
console.error("Failed to decode token for debugging:", decodeError);
|
|
125
|
-
}
|
|
56
|
+
console.log("Audience match:", payload.aud === appId);
|
|
57
|
+
console.log("Issuer match:", payload.iss === `https://login.microsoftonline.com/${tenantId}/v2.0`);
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
console.error("Failed to decode token:", e);
|
|
61
|
+
}
|
|
62
|
+
console.log("=== END DEBUGGING ===");
|
|
63
|
+
const verifiedPayload = await new Promise((resolve, reject) => {
|
|
126
64
|
jsonwebtoken_1.default.verify(token, getKey, {
|
|
127
65
|
audience: appId,
|
|
128
66
|
issuer: `https://login.microsoftonline.com/${tenantId}/v2.0`,
|
|
129
|
-
algorithms: ["RS256"],
|
|
67
|
+
algorithms: ["RS256"],
|
|
130
68
|
}, (err, decoded) => {
|
|
131
69
|
if (err) {
|
|
132
|
-
console.error("JWT verification failed:", err);
|
|
133
|
-
console.error("Error name:", err.name);
|
|
134
|
-
console.error("Error message:", err.message);
|
|
70
|
+
console.error("JWT verification failed:", err.message);
|
|
135
71
|
return reject(err);
|
|
136
72
|
}
|
|
137
|
-
console.log("JWT verification successful");
|
|
138
73
|
resolve(decoded);
|
|
139
74
|
});
|
|
140
75
|
});
|
|
76
|
+
const defaultTenant = await new Parse.Query(types_1.Tenant)
|
|
77
|
+
.ascending("createdAt")
|
|
78
|
+
.first({ useMasterKey: true });
|
|
141
79
|
let user = await new Parse.Query(Parse.User)
|
|
142
80
|
.equalTo("username", verifiedPayload.oid)
|
|
143
81
|
.first({ useMasterKey: true });
|
|
@@ -145,7 +83,7 @@ async function init(name) {
|
|
|
145
83
|
user = new Parse.User();
|
|
146
84
|
user.set("username", verifiedPayload.oid);
|
|
147
85
|
user.set("email", account.username);
|
|
148
|
-
user.set("password", (0, crypto_1.randomBytes)(16).toString("hex"));
|
|
86
|
+
user.set("password", (0, crypto_1.randomBytes)(16).toString("hex"));
|
|
149
87
|
user.set("name", verifiedPayload.name || verifiedPayload.preferred_username);
|
|
150
88
|
user.set("tenant", defaultTenant);
|
|
151
89
|
user = await user.signUp(null, { useMasterKey: true });
|
|
@@ -155,7 +93,7 @@ async function init(name) {
|
|
|
155
93
|
const session = new Parse.Object("_Session");
|
|
156
94
|
session.set("user", user);
|
|
157
95
|
session.set("sessionToken", sessionToken);
|
|
158
|
-
session.set("expiresAt", new Date(Date.now() + 24 * 60 * 60 * 1000 * 7));
|
|
96
|
+
session.set("expiresAt", new Date(Date.now() + 24 * 60 * 60 * 1000 * 7));
|
|
159
97
|
const savedSession = await session.save(null, { useMasterKey: true });
|
|
160
98
|
return savedSession.get("sessionToken");
|
|
161
99
|
});
|