Repository navigation
Expand file tree
/
Copy pathexample.ts
More file actions
351 lines (308 loc) Β· 12.3 KB
/
Copy pathexample.ts
File metadata and controls
351 lines (308 loc) Β· 12.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
/**
* Auth0 MyOrganization SDK - Complete Usage Examples
*
* This file demonstrates both SPA and server-side usage patterns for the MyOrganizationClient.
* The SDK provides secure separation between client-side and server-side authentication.
*/
// SPA applications - only import the main client
import { MyOrganizationClient } from "./src/wrappers/index.js";
// Server applications - import from server module
import { createMyOrganizationClientWithClientCredentials } from "./src/server.js";
/**
* π SPA APPLICATION EXAMPLES (React, Vue, Angular, etc.)
*
* SPA users can only use token-based authentication - no client secrets exposed!
*/
// Example 1: SPA with static token
async function spaExampleWithStaticToken() {
const client = new MyOrganizationClient({
domain: "your-tenant.auth0.com", // Your Auth0 domain
token: "your-user-access-token", // User's access token from Auth0 SPA SDK
});
try {
// Get organization details that user has access to
const orgDetails = await client.organizationDetails.get();
console.log("Organization Details:", orgDetails);
} catch (error) {
console.error("Error:", error);
}
}
// Example 2: SPA with dynamic token (recommended for simple use cases)
async function spaExampleWithDynamicToken() {
const client = new MyOrganizationClient({
domain: "your-tenant.auth0.com",
token: () => getAccessTokenFromAuth0SPA(), // Function that returns fresh token
});
try {
// Access organization APIs with user permissions
const orgDetails = await client.organizationDetails.get();
console.log("Organization Details:", orgDetails);
} catch (error) {
console.error("Error:", error);
}
}
// Example 2b: SPA with async function (ignores scope parameter)
async function spaExampleWithAsyncToken() {
const client = new MyOrganizationClient({
domain: "your-tenant.auth0.com",
// SDK always calls with { scope }, but function without parameters ignores extra arguments
token: async () => {
return await auth0.getTokenSilently();
},
});
try {
// Works perfectly - SDK passes scope, function ignores it
const orgDetails = await client.organizationDetails.get();
console.log("Organization Details:", orgDetails);
} catch (error) {
console.error("Error:", error);
}
}
// Helper function for SPA token retrieval (integrate with @auth0/auth0-spa-js)
async function getAccessTokenFromAuth0SPA(): Promise<string> {
// This would integrate with your Auth0 SPA SDK
// return await auth0Client.getTokenSilently();
return "user-access-token-from-spa-sdk";
}
// Example 3: SPA with scope-aware token function (Recommended for Auth0 SPAs)
async function spaExampleWithScopeAwareToken() {
const client = new MyOrganizationClient({
domain: "your-tenant.auth0.com",
token: async ({ scope }) => {
// This function receives the exact scopes required by each API endpoint
// Perfect for Auth0 SPA SDK getTokenSilently pattern
console.log("API endpoint requires scopes:", scope);
// Example integration with @auth0/auth0-spa-js
const token = await auth0.getTokenSilently({
authorizationParams: {
scope: `openid profile email ${scope}`,
},
});
return token;
},
});
try {
// Each API call automatically passes the required scopes to your token function
console.log("=== Getting organization details ===");
const orgDetails = await client.organizationDetails.get(); // Calls with org-specific scopes
console.log("Organization Details:", orgDetails);
console.log("\n=== Getting organization members ===");
const members = await client.organization.members.list(); // Calls with member-specific scopes
console.log("Organization Members:", members);
console.log("\n=== Creating a member invitation ===");
const invitation = await client.organization.invitations.create({
// This endpoint might require different scopes than the read operations above
invitee: {
email: "newuser@example.com",
},
client_id: "your-client-id",
connection_id: "con_2CZPv6IY0gWzDaQJ",
ttl_sec: 3600,
roles: ["rol_basic_member"],
send_invitation_email: true,
});
console.log("Created invitation:", invitation);
} catch (error) {
console.error("Error:", error);
}
}
// Example 5: Simplest pattern - Just pass your getAccessToken function
async function spaExampleWithDirectFunction() {
// Even simpler! Just pass your getAccessToken function directly
// The SDK automatically calls it with { scope: [...] }
const client = new MyOrganizationClient({
domain: "your-tenant.auth0.com",
token: getAccessToken, // SDK handles scope passing automatically
});
try {
console.log("=== Using direct function pattern ===");
const orgDetails = await client.organizationDetails.get();
console.log("Organization Details:", orgDetails);
} catch (error) {
console.error("Error:", error);
}
}
// Your getAccessToken function - SDK automatically passes { scope } to it
async function getAccessToken({ scope }: { scope: string }) {
console.log("getAccessToken called with scopes:", scope);
// Your implementation can be anything - Auth0 SPA, custom auth, etc.
return await auth0.getTokenSilently({
authorizationParams: {
scope: `openid profile email ${scope}`,
},
});
}
// Mock auth0 client for example (in real code, import from @auth0/auth0-spa-js)
const auth0 = {
async getTokenSilently(options?: { authorizationParams: { scope: string } }): Promise<string> {
const scope = options?.authorizationParams?.scope || "openid profile email";
console.log(`π Getting Auth0 SPA token with scope: "${scope}"`);
// In real implementation, this would return the actual access token
return `auth0-spa-token-with-scopes-${Date.now()}`;
},
};
/**
* π SERVER-SIDE EXAMPLES (Node.js, serverless functions, etc.)
*
* Server users can use client credentials with the TokenProvider pattern.
* Domain inheritance ensures no duplication!
*/
// Example 3: Server with client secret (most common)
async function serverExampleWithClientSecret() {
// Option 1: Use the factory function (recommended)
const client = createMyOrganizationClientWithClientCredentials(
{
domain: "your-tenant.auth0.com",
clientInfo: {
name: "my-server-app",
version: "1.0.0",
},
},
{
clientId: "YOUR_CLIENT_ID",
clientSecret: "YOUR_CLIENT_SECRET",
organization: "org_123456789",
// audience is optional - defaults to https://{domain}/my-org/
},
);
// Option 2: Manual setup (if you need more control)
// const tokenProvider = new ClientCredentialsTokenProvider({
// domain: 'your-tenant.auth0.com',
// clientId: 'YOUR_CLIENT_ID',
// clientSecret: 'YOUR_CLIENT_SECRET',
// organization: 'org_123456789'
// });
//
// const client = new MyOrganizationClient({
// domain: 'your-tenant.auth0.com',
// tokenProvider: tokenProvider,
// clientInfo: {
// name: "my-server-app",
// version: "1.0.0"
// }
// });
try {
// Server-side access with client credentials
const orgDetails = await client.organizationDetails.get();
console.log("Organization Details:", orgDetails);
// Access organization members with server permissions
const members = await client.organization.members.list();
console.log("Organization Members count:", members);
} catch (error) {
console.error("Error:", error);
}
}
// Example 4: Server with private key JWT (enhanced security)
async function serverExampleWithPrivateKey() {
// Option 1: Use the factory function (recommended)
const client = createMyOrganizationClientWithClientCredentials(
{ domain: "your-tenant.auth0.com" },
{
clientId: "YOUR_CLIENT_ID",
privateKey: process.env.AUTH0_PRIVATE_KEY!, // Your RSA/ECDSA private key
organization: "org_123456789",
audience: "https://my-tenant.auth0.com/custom-api/", // Custom audience if needed
},
);
// Option 2: Manual setup (if you need more control)
// const tokenProvider = new ClientCredentialsTokenProvider({
// domain: 'your-tenant.auth0.com',
// clientId: 'YOUR_CLIENT_ID',
// privateKey: process.env.AUTH0_PRIVATE_KEY!,
// organization: 'org_123456789',
// audience: 'https://my-tenant.auth0.com/custom-api/'
// });
//
// const client = new MyOrganizationClient({
// domain: 'your-tenant.auth0.com',
// tokenProvider: tokenProvider
// });
try {
const orgDetails = await client.organizationDetails.get();
console.log("Secure Organization Details:", orgDetails);
} catch (error) {
console.error("Error:", error);
}
}
// Example 3: Initialize client with static token
async function exampleWithStaticToken() {
const client = new MyOrganizationClient({
token: "your-access-token-here", // Replace with your actual token
domain: "your-tenant.auth0.com", // Replace with your Auth0 domain
clientInfo: {
name: "my-app",
version: "1.0.0",
},
});
try {
// Get organization details
const orgDetails = await client.organizationDetails.get();
console.log("Organization Details:", orgDetails);
// List organization members
const members = await client.organization.members.list();
console.log("Organization Members:", members);
// Get organization configuration
const config = await client.organization.configuration.get();
console.log("Organization Configuration:", config);
} catch (error) {
console.error("Error:", error);
}
}
/**
* π― MAIN EXECUTION AND BENEFITS
*/
// Main function to run examples
async function main() {
console.log("=== Auth0 MyOrganization SDK Examples ===\n");
console.log("π SPA Examples (Browser-safe - no client secrets):");
console.log("1. SPA with Static Token:");
await spaExampleWithStaticToken();
console.log("\n2. SPA with Dynamic Token:");
await spaExampleWithDynamicToken();
console.log("\n2b. SPA with Async Token (ignores scope):");
await spaExampleWithAsyncToken();
console.log("\n3. SPA with Scope-Aware Token:");
await spaExampleWithScopeAwareToken();
console.log("\n4. SPA with Direct Function:");
await spaExampleWithDirectFunction();
console.log("\n" + "=".repeat(50) + "\n");
console.log("π Server Examples (Client credentials via TokenProvider):");
console.log("3. Server with Client Secret:");
await serverExampleWithClientSecret();
console.log("\n4. Server with Private Key JWT:");
await serverExampleWithPrivateKey();
console.log("\nβ
All examples completed!");
}
// Uncomment the line below to run the examples
// main().catch(console.error);
/**
* π SECURITY GUARANTEE:
*
* β
SPA users importing '@auth0/myorganization-js' will NEVER see:
* - clientId, clientSecret, privateKey options in MyOrganizationClient
* - ClientCredentialsTokenProvider class
* - Any client credentials related interfaces
*
* β
These are ONLY available from '@auth0/myorganization-js/server' import!
*
* π― PERFECT API:
* - Simple factory function: createMyOrganizationClientWithClientCredentials()
* - Or manual setup with TokenProvider constructor
* - Domain specified once, audience auto-generated or customizable
* - Clean separation between SPA and server usage!
*/
export {
// SPA Examples
spaExampleWithStaticToken,
spaExampleWithDynamicToken,
spaExampleWithAsyncToken,
spaExampleWithScopeAwareToken,
spaExampleWithDirectFunction,
getAccessTokenFromAuth0SPA,
getAccessToken,
// Server Examples
serverExampleWithClientSecret,
serverExampleWithPrivateKey,
// Main execution
main,
};