@asgardeo/nuxt 0.0.0 → 0.1.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.
Files changed (119) hide show
  1. package/README.md +482 -6
  2. package/dist/module.d.mts +17 -24
  3. package/dist/module.json +2 -2
  4. package/dist/module.mjs +174 -48
  5. package/dist/runtime/components/AsgardeoRoot.d.ts +52 -0
  6. package/dist/runtime/components/AsgardeoRoot.js +160 -0
  7. package/dist/runtime/components/actions/SignInButton.d.ts +37 -0
  8. package/dist/runtime/components/actions/SignInButton.js +51 -0
  9. package/dist/runtime/components/actions/SignOutButton.d.ts +34 -0
  10. package/dist/runtime/components/actions/SignOutButton.js +43 -0
  11. package/dist/runtime/components/actions/SignUpButton.d.ts +33 -0
  12. package/dist/runtime/components/actions/SignUpButton.js +48 -0
  13. package/dist/runtime/components/auth/Callback.d.ts +43 -0
  14. package/dist/runtime/components/auth/Callback.js +93 -0
  15. package/dist/runtime/components/auth/SignIn.d.ts +38 -0
  16. package/dist/runtime/components/auth/SignIn.js +60 -0
  17. package/dist/runtime/components/auth/SignUp.d.ts +40 -0
  18. package/dist/runtime/components/auth/SignUp.js +79 -0
  19. package/dist/runtime/components/control/Loading.d.ts +36 -0
  20. package/dist/runtime/components/control/Loading.js +17 -0
  21. package/dist/runtime/components/control/SignedIn.d.ts +38 -0
  22. package/dist/runtime/components/control/SignedIn.js +17 -0
  23. package/dist/runtime/components/control/SignedOut.d.ts +37 -0
  24. package/dist/runtime/components/control/SignedOut.js +17 -0
  25. package/dist/runtime/components/organization/CreateOrganization.d.ts +32 -0
  26. package/dist/runtime/components/organization/CreateOrganization.js +29 -0
  27. package/dist/runtime/components/organization/Organization.d.ts +39 -0
  28. package/dist/runtime/components/organization/Organization.js +17 -0
  29. package/dist/runtime/components/organization/OrganizationList.d.ts +34 -0
  30. package/dist/runtime/components/organization/OrganizationList.js +30 -0
  31. package/dist/runtime/components/organization/OrganizationProfile.d.ts +32 -0
  32. package/dist/runtime/components/organization/OrganizationProfile.js +32 -0
  33. package/dist/runtime/components/organization/OrganizationSwitcher.d.ts +36 -0
  34. package/dist/runtime/components/organization/OrganizationSwitcher.js +26 -0
  35. package/dist/runtime/components/user/User.d.ts +38 -0
  36. package/dist/runtime/components/user/User.js +17 -0
  37. package/dist/runtime/components/user/UserDropdown.d.ts +38 -0
  38. package/dist/runtime/components/user/UserDropdown.js +45 -0
  39. package/dist/runtime/components/user/UserProfile.d.ts +35 -0
  40. package/dist/runtime/components/user/UserProfile.js +35 -0
  41. package/dist/runtime/composables/useAsgardeo.d.ts +38 -0
  42. package/dist/runtime/composables/useAsgardeo.js +73 -0
  43. package/dist/runtime/errors/asgardeo-error.d.ts +47 -0
  44. package/dist/runtime/errors/asgardeo-error.js +15 -0
  45. package/dist/runtime/errors/error-codes.d.ts +40 -0
  46. package/dist/runtime/errors/error-codes.js +19 -0
  47. package/dist/runtime/{composables/asgardeo/useAuth.d.ts → errors/index.d.ts} +2 -2
  48. package/dist/runtime/errors/index.js +2 -0
  49. package/dist/runtime/middleware/auth.d.ts +35 -0
  50. package/dist/runtime/middleware/auth.js +2 -0
  51. package/dist/runtime/middleware/defineAsgardeoMiddleware.d.ts +53 -0
  52. package/dist/runtime/middleware/defineAsgardeoMiddleware.js +24 -0
  53. package/dist/runtime/plugins/asgardeo.d.ts +40 -0
  54. package/dist/runtime/plugins/asgardeo.js +129 -0
  55. package/dist/runtime/server/AsgardeoNuxtClient.d.ts +182 -0
  56. package/dist/runtime/server/AsgardeoNuxtClient.js +366 -0
  57. package/dist/runtime/server/index.d.ts +33 -0
  58. package/dist/runtime/server/index.js +3 -0
  59. package/dist/runtime/server/plugins/asgardeo-ssr.d.ts +41 -0
  60. package/dist/runtime/server/plugins/asgardeo-ssr.js +134 -0
  61. package/dist/runtime/server/routes/auth/branding/branding.get.d.ts +31 -0
  62. package/dist/runtime/server/routes/auth/branding/branding.get.js +40 -0
  63. package/dist/runtime/server/routes/auth/organizations/current.get.d.ts +29 -0
  64. package/dist/runtime/server/routes/auth/organizations/current.get.js +24 -0
  65. package/dist/runtime/server/routes/auth/organizations/id.get.d.ts +28 -0
  66. package/dist/runtime/server/routes/auth/organizations/id.get.js +28 -0
  67. package/dist/runtime/server/routes/auth/organizations/index.get.d.ts +28 -0
  68. package/dist/runtime/server/routes/auth/organizations/index.get.js +24 -0
  69. package/dist/runtime/server/routes/auth/organizations/index.post.d.ts +30 -0
  70. package/dist/runtime/server/routes/auth/organizations/index.post.js +30 -0
  71. package/dist/runtime/server/routes/auth/organizations/me.get.d.ts +28 -0
  72. package/dist/runtime/server/routes/auth/organizations/me.get.js +24 -0
  73. package/dist/runtime/server/routes/auth/organizations/switch.post.d.ts +32 -0
  74. package/dist/runtime/server/routes/auth/organizations/switch.post.js +49 -0
  75. package/dist/runtime/server/routes/auth/session/callback.get.d.ts +27 -0
  76. package/dist/runtime/server/routes/auth/session/callback.get.js +91 -0
  77. package/dist/runtime/server/routes/auth/session/callback.post.d.ts +48 -0
  78. package/dist/runtime/server/routes/auth/session/callback.post.js +53 -0
  79. package/dist/runtime/server/routes/auth/session/session.get.d.ts +26 -0
  80. package/dist/runtime/server/routes/auth/session/session.get.js +22 -0
  81. package/dist/runtime/server/routes/auth/session/signin.get.d.ts +29 -0
  82. package/dist/runtime/server/routes/auth/session/signin.get.js +37 -0
  83. package/dist/runtime/server/routes/auth/session/signin.post.d.ts +37 -0
  84. package/dist/runtime/server/routes/auth/session/signin.post.js +102 -0
  85. package/dist/runtime/server/routes/auth/session/signout.post.d.ts +31 -0
  86. package/dist/runtime/server/routes/auth/session/signout.post.js +38 -0
  87. package/dist/runtime/server/routes/auth/session/signup.post.d.ts +36 -0
  88. package/dist/runtime/server/routes/auth/session/signup.post.js +30 -0
  89. package/dist/runtime/server/routes/auth/session/token.get.d.ts +29 -0
  90. package/dist/runtime/server/routes/auth/session/token.get.js +6 -0
  91. package/dist/runtime/server/routes/auth/user/profile.get.d.ts +29 -0
  92. package/dist/runtime/server/routes/auth/user/profile.get.js +24 -0
  93. package/dist/runtime/server/{handler.d.ts → routes/auth/user/profile.patch.d.ts} +17 -13
  94. package/dist/runtime/server/routes/auth/user/profile.patch.js +33 -0
  95. package/dist/runtime/server/{services/asgardeo/index.d.ts → routes/auth/user/user.get.d.ts} +6 -4
  96. package/dist/runtime/server/routes/auth/user/user.get.js +21 -0
  97. package/dist/runtime/server/utils/event-context.d.ts +49 -0
  98. package/dist/runtime/server/utils/event-context.js +3 -0
  99. package/dist/runtime/server/utils/serverSession.d.ts +65 -0
  100. package/dist/runtime/server/utils/serverSession.js +44 -0
  101. package/dist/runtime/server/utils/session.d.ts +85 -0
  102. package/dist/runtime/server/utils/session.js +106 -0
  103. package/dist/runtime/server/utils/token-refresh.d.ts +42 -0
  104. package/dist/runtime/server/utils/token-refresh.js +65 -0
  105. package/dist/runtime/types/augments.d.ts +61 -0
  106. package/dist/runtime/types.d.ts +115 -38
  107. package/dist/runtime/utils/createRouteMatcher.d.ts +40 -0
  108. package/dist/runtime/utils/createRouteMatcher.js +7 -0
  109. package/dist/runtime/utils/index.d.ts +30 -0
  110. package/dist/runtime/utils/index.js +1 -0
  111. package/dist/runtime/utils/log.d.ts +44 -0
  112. package/dist/runtime/utils/log.js +25 -0
  113. package/dist/runtime/utils/url-validation.d.ts +49 -0
  114. package/dist/runtime/utils/url-validation.js +38 -0
  115. package/dist/types.d.mts +0 -2
  116. package/package.json +48 -23
  117. package/dist/runtime/composables/asgardeo/useAuth.js +0 -129
  118. package/dist/runtime/server/handler.js +0 -231
  119. package/dist/runtime/server/services/asgardeo/index.js +0 -18
@@ -0,0 +1,366 @@
1
+ import {
2
+ AsgardeoNodeClient,
3
+ LegacyAsgardeoNodeClient,
4
+ getBrandingPreference,
5
+ getMeOrganizations,
6
+ getAllOrganizations,
7
+ createOrganization,
8
+ getOrganization,
9
+ getScim2Me,
10
+ getSchemas,
11
+ flattenUserSchema,
12
+ generateFlattenedUserProfile,
13
+ updateMeProfile,
14
+ initializeEmbeddedSignInFlow,
15
+ executeEmbeddedSignInFlow,
16
+ executeEmbeddedSignUpFlow
17
+ } from "@asgardeo/node";
18
+ class AsgardeoNuxtClient extends AsgardeoNodeClient {
19
+ static instance;
20
+ legacy;
21
+ isInitialized = false;
22
+ constructor() {
23
+ super();
24
+ this.legacy = new LegacyAsgardeoNodeClient();
25
+ }
26
+ /**
27
+ * Get the singleton instance of AsgardeoNuxtClient.
28
+ */
29
+ static getInstance() {
30
+ if (!AsgardeoNuxtClient.instance) {
31
+ AsgardeoNuxtClient.instance = new AsgardeoNuxtClient();
32
+ }
33
+ return AsgardeoNuxtClient.instance;
34
+ }
35
+ /**
36
+ * Initializes the underlying legacy client with OAuth/OIDC settings derived
37
+ * from the Nuxt module config. Idempotent — repeated calls are no-ops after
38
+ * the first successful initialization.
39
+ */
40
+ async initialize(config, storage) {
41
+ if (this.isInitialized) {
42
+ return true;
43
+ }
44
+ const authConfig = {
45
+ afterSignInUrl: config.afterSignInUrl,
46
+ afterSignOutUrl: config.afterSignOutUrl || "/",
47
+ baseUrl: config.baseUrl,
48
+ clientId: config.clientId,
49
+ clientSecret: config.clientSecret || void 0,
50
+ enablePKCE: true,
51
+ scopes: config.scopes || ["openid", "profile"]
52
+ };
53
+ const result = await this.legacy.initialize(authConfig, storage);
54
+ this.isInitialized = true;
55
+ return result;
56
+ }
57
+ async reInitialize(config) {
58
+ await this.legacy.reInitialize(config);
59
+ return true;
60
+ }
61
+ /**
62
+ * Seeds the legacy in-memory token store from a verified session JWT payload.
63
+ *
64
+ * The signed session cookie is the source of truth for tokens in this SDK — it
65
+ * survives server restarts and new worker processes. The underlying
66
+ * {@link LegacyAsgardeoNodeClient}, however, keeps tokens in a
67
+ * {@link MemoryCacheStore} keyed by `sessionId`, and its
68
+ * `getAccessToken` / `getUser` / `getDecodedIdToken` / `signOut` paths all
69
+ * read from that store. Without rehydration, those calls fail whenever the
70
+ * in-memory store and the cookie diverge (the classic case: `nuxi dev`
71
+ * restart while the browser still holds a valid session cookie).
72
+ *
73
+ * Writes the snake_case token shape the legacy helper expects
74
+ * (see `AuthenticationHelper.processTokenResponse`). Safe to call on every
75
+ * request — it's an in-memory write and the cookie always reflects the
76
+ * freshest tokens (the refresh path re-issues the cookie too).
77
+ */
78
+ async rehydrateSessionFromPayload(session) {
79
+ if (!this.isInitialized || !session?.sessionId || !session?.accessToken) {
80
+ return;
81
+ }
82
+ const storageManager = await this.legacy.getStorageManager();
83
+ const iatSeconds = typeof session.iat === "number" ? session.iat : Math.floor(Date.now() / 1e3);
84
+ const expiresInSeconds = typeof session.accessTokenExpiresAt === "number" ? Math.max(0, session.accessTokenExpiresAt - iatSeconds) : 3600;
85
+ await storageManager.setSessionData(
86
+ {
87
+ access_token: session.accessToken,
88
+ created_at: iatSeconds * 1e3,
89
+ expires_in: String(expiresInSeconds || 3600),
90
+ id_token: session.idToken ?? "",
91
+ refresh_token: session.refreshToken ?? "",
92
+ scope: session.scopes ?? "",
93
+ session_state: "",
94
+ token_type: "Bearer"
95
+ },
96
+ session.sessionId
97
+ );
98
+ }
99
+ /**
100
+ * Initiates the authorization code flow, handles an embedded sign-in step,
101
+ * or exchanges a code for tokens.
102
+ *
103
+ * Overload 1 — **redirect-flow** (existing callers like `signin.get.ts`):
104
+ * ```
105
+ * signIn(authURLCallback, sessionId, code?, sessionState?, state?, config?)
106
+ * ```
107
+ * Overload 2 — **embedded flow initiate** (flowId === ''):
108
+ * ```
109
+ * signIn({flowId: ''}, request, sessionId)
110
+ * ```
111
+ * Dispatches to `initializeEmbeddedSignInFlow`.
112
+ *
113
+ * Overload 3 — **embedded flow execute** (flowId set):
114
+ * ```
115
+ * signIn(payload, request, sessionId)
116
+ * ```
117
+ * Dispatches to `executeEmbeddedSignInFlow`.
118
+ *
119
+ * Overload 4 — **code exchange** (completion after embedded flow):
120
+ * ```
121
+ * signIn({code, state, session_state}, {}, sessionId)
122
+ * ```
123
+ * Falls through to the legacy redirect-flow code-exchange path.
124
+ */
125
+ signIn(...args) {
126
+ const arg0 = args[0];
127
+ if (typeof arg0 === "object" && arg0 !== null && "flowId" in arg0) {
128
+ const sessionId = args[2];
129
+ if (arg0.flowId === "") {
130
+ return this.getAuthorizeRequestUrl(
131
+ { client_secret: "{{clientSecret}}", response_mode: "direct" },
132
+ sessionId
133
+ ).then((authorizeUrl) => {
134
+ const url = new URL(authorizeUrl);
135
+ return initializeEmbeddedSignInFlow({
136
+ payload: Object.fromEntries(url.searchParams.entries()),
137
+ url: `${url.origin}${url.pathname}`
138
+ });
139
+ });
140
+ }
141
+ const request = args[1] ?? {};
142
+ return executeEmbeddedSignInFlow({
143
+ payload: arg0,
144
+ url: request.url
145
+ });
146
+ }
147
+ if (typeof arg0 === "object" && arg0 !== null && ("code" in arg0 || "state" in arg0)) {
148
+ const payload = arg0;
149
+ const code = typeof payload.code === "string" ? payload.code : void 0;
150
+ const sessionState = typeof payload.session_state === "string" ? payload.session_state : void 0;
151
+ const state = typeof payload.state === "string" ? payload.state : void 0;
152
+ const extraParams = {};
153
+ if (code) {
154
+ extraParams.code = code;
155
+ }
156
+ if (sessionState) {
157
+ extraParams.session_state = sessionState;
158
+ }
159
+ if (state) {
160
+ extraParams.state = state;
161
+ }
162
+ return this.legacy.signIn(args[3], args[2], code, sessionState, state, extraParams);
163
+ }
164
+ return this.legacy.signIn(args[0], args[1], args[2], args[3], args[4], args[5]);
165
+ }
166
+ async signUp(payloadOrOptions) {
167
+ if (!payloadOrOptions || !("flowType" in payloadOrOptions)) {
168
+ return void 0;
169
+ }
170
+ const configData = await this.legacy.getConfigData?.();
171
+ const baseUrl = configData?.baseUrl;
172
+ const response = await executeEmbeddedSignUpFlow({
173
+ baseUrl,
174
+ payload: payloadOrOptions
175
+ });
176
+ return response;
177
+ }
178
+ /**
179
+ * Returns the OAuth2 authorization URL.
180
+ * Used by the redirect-flow GET handler and the embedded-flow initiation path.
181
+ *
182
+ * Mirrors `AsgardeoNextClient.getAuthorizeRequestUrl`.
183
+ */
184
+ async getAuthorizeRequestUrl(customParams, userId) {
185
+ return this.legacy.getSignInUrl(customParams, userId);
186
+ }
187
+ /**
188
+ * Clears the session and returns the RP-Initiated Logout URL.
189
+ * Accepts either `(sessionId: string)` or `(options?, sessionId?, callback?)`.
190
+ */
191
+ async signOut(...args) {
192
+ const sessionId = typeof args[0] === "string" ? args[0] : args[1];
193
+ return this.legacy.signOut(sessionId);
194
+ }
195
+ getUser(sessionId) {
196
+ return this.legacy.getUser(sessionId);
197
+ }
198
+ getAccessToken(sessionId) {
199
+ return this.legacy.getAccessToken(sessionId);
200
+ }
201
+ /**
202
+ * Decodes and returns the ID token claims for the given session.
203
+ * Exposed here (as on {@link AsgardeoNextClient}) so route handlers can
204
+ * access ID token claims without falling back to the legacy client.
205
+ */
206
+ getDecodedIdToken(sessionId, idToken) {
207
+ return this.legacy.getDecodedIdToken(sessionId, idToken);
208
+ }
209
+ isSignedIn(sessionId) {
210
+ return this.legacy.isSignedIn(sessionId);
211
+ }
212
+ exchangeToken(config, sessionId) {
213
+ return this.legacy.exchangeToken(config, sessionId);
214
+ }
215
+ /**
216
+ * Fetches the flattened SCIM2 user profile for the given session.
217
+ * Mirrors `AsgardeoNextClient.getUserProfile` — calls `getScim2Me` +
218
+ * `getSchemas` + `generateFlattenedUserProfile` and falls back to
219
+ * `getUser` claims if SCIM2 is unavailable.
220
+ */
221
+ async getUserProfile(sessionId) {
222
+ const accessToken = await this.getAccessToken(sessionId);
223
+ const configData = await this.legacy.getConfigData?.();
224
+ const baseUrl = configData?.baseUrl ?? "";
225
+ try {
226
+ const authHeaders = { Authorization: `Bearer ${accessToken}` };
227
+ const [profile, schemas] = await Promise.all([
228
+ getScim2Me({ baseUrl, headers: authHeaders }),
229
+ getSchemas({ baseUrl, headers: authHeaders })
230
+ ]);
231
+ const processedSchemas = flattenUserSchema(schemas);
232
+ return {
233
+ flattenedProfile: generateFlattenedUserProfile(profile, processedSchemas),
234
+ profile,
235
+ schemas: processedSchemas
236
+ };
237
+ } catch {
238
+ const user = await this.getUser(sessionId);
239
+ return { flattenedProfile: user, profile: user, schemas: [] };
240
+ }
241
+ }
242
+ /**
243
+ * Extracts the current organisation from the decoded ID token.
244
+ * Returns null when the user is not acting within an organisation.
245
+ */
246
+ async getCurrentOrganization(sessionId) {
247
+ try {
248
+ const idToken = await this.getDecodedIdToken(sessionId);
249
+ if (!idToken?.org_id) {
250
+ return null;
251
+ }
252
+ return {
253
+ id: idToken.org_id,
254
+ name: idToken.org_name ?? "",
255
+ orgHandle: idToken.org_handle ?? ""
256
+ };
257
+ } catch {
258
+ return null;
259
+ }
260
+ }
261
+ /**
262
+ * Returns the list of organisations the authenticated user is a member of.
263
+ */
264
+ async getMyOrganizations(sessionId) {
265
+ const accessToken = await this.getAccessToken(sessionId);
266
+ const configData = await this.legacy.getConfigData?.();
267
+ const baseUrl = configData?.baseUrl ?? "";
268
+ return getMeOrganizations({
269
+ baseUrl,
270
+ headers: { Authorization: `Bearer ${accessToken}` }
271
+ });
272
+ }
273
+ /**
274
+ * Fetches the branding preference for the tenant / application.
275
+ * Delegates to the standalone `getBrandingPreference` API helper from
276
+ * `@asgardeo/node`, which does not require an authenticated session.
277
+ */
278
+ // eslint-disable-next-line class-methods-use-this
279
+ async getBrandingPreference(config) {
280
+ return getBrandingPreference(config);
281
+ }
282
+ /**
283
+ * Updates the SCIM2 /Me profile for the authenticated user.
284
+ * Mirrors `AsgardeoNextClient.updateUserProfile`.
285
+ */
286
+ async updateUserProfile(config, sessionId) {
287
+ const accessToken = await this.getAccessToken(sessionId);
288
+ const configData = await this.legacy.getConfigData?.();
289
+ const baseUrl = configData?.baseUrl ?? "";
290
+ return updateMeProfile({
291
+ ...config,
292
+ // pass-through, includes payload
293
+ baseUrl,
294
+ headers: { ...config.headers, Authorization: `Bearer ${accessToken}` }
295
+ });
296
+ }
297
+ /**
298
+ * Retrieves all organisations accessible to the authenticated user
299
+ * (paginated). Mirrors `AsgardeoNextClient.getAllOrganizations`.
300
+ */
301
+ async getAllOrganizations(options, sessionId) {
302
+ const resolvedSessionId = sessionId ?? "";
303
+ const accessToken = await this.getAccessToken(resolvedSessionId);
304
+ const configData = await this.legacy.getConfigData?.();
305
+ const baseUrl = configData?.baseUrl ?? "";
306
+ return getAllOrganizations({
307
+ baseUrl,
308
+ headers: { Authorization: `Bearer ${accessToken}` }
309
+ });
310
+ }
311
+ /**
312
+ * Creates a new sub-organisation. Mirrors `AsgardeoNextClient.createOrganization`.
313
+ */
314
+ async createOrganization(payload, sessionId) {
315
+ const accessToken = await this.getAccessToken(sessionId);
316
+ const configData = await this.legacy.getConfigData?.();
317
+ const baseUrl = configData?.baseUrl ?? "";
318
+ return createOrganization({
319
+ baseUrl,
320
+ headers: { Authorization: `Bearer ${accessToken}` },
321
+ payload
322
+ });
323
+ }
324
+ /**
325
+ * Fetches the details of a single organisation by ID.
326
+ * Mirrors `AsgardeoNextClient.getOrganization`.
327
+ */
328
+ async getOrganization(organizationId, sessionId) {
329
+ const accessToken = await this.getAccessToken(sessionId);
330
+ const configData = await this.legacy.getConfigData?.();
331
+ const baseUrl = configData?.baseUrl ?? "";
332
+ return getOrganization({
333
+ baseUrl,
334
+ headers: { Authorization: `Bearer ${accessToken}` },
335
+ organizationId
336
+ });
337
+ }
338
+ /**
339
+ * Performs an organisation-switch token exchange and returns the new
340
+ * `TokenResponse`. The caller (the Nitro route) is responsible for
341
+ * persisting the new session cookie.
342
+ *
343
+ * Mirrors `AsgardeoNextClient.switchOrganization`.
344
+ */
345
+ async switchOrganization(organization, sessionId) {
346
+ if (!organization.id) {
347
+ throw new Error("Organization ID is required for switching organizations.");
348
+ }
349
+ const exchangeConfig = {
350
+ attachToken: false,
351
+ data: {
352
+ client_id: "{{clientId}}",
353
+ client_secret: "{{clientSecret}}",
354
+ grant_type: "organization_switch",
355
+ scope: "{{scopes}}",
356
+ switching_organization: organization.id,
357
+ token: "{{accessToken}}"
358
+ },
359
+ id: "organization-switch",
360
+ returnsSession: true,
361
+ signInRequired: true
362
+ };
363
+ return this.legacy.exchangeToken(exchangeConfig, sessionId);
364
+ }
365
+ }
366
+ export default AsgardeoNuxtClient;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3
+ *
4
+ * WSO2 LLC. licenses this file to you under the Apache License,
5
+ * Version 2.0 (the "License"); you may not use this file except
6
+ * in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing,
12
+ * software distributed under the License is distributed on an
13
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ * KIND, either express or implied. See the License for the
15
+ * specific language governing permissions and limitations
16
+ * under the License.
17
+ */
18
+ /**
19
+ * @asgardeo/nuxt/server
20
+ *
21
+ * Public server-only barrel. Import from this subpath to access
22
+ * server utilities without bundling them into the client.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { useServerSession, requireServerSession } from '@asgardeo/nuxt/server';
27
+ * ```
28
+ */
29
+ export { useServerSession, requireServerSession } from './utils/serverSession.js';
30
+ export { getValidAccessToken } from './utils/token-refresh.js';
31
+ export { getAsgardeoContext } from './utils/event-context.js';
32
+ export type { AsgardeoEventContext } from './utils/event-context.js';
33
+ export type { AsgardeoSessionPayload, AsgardeoNuxtConfig } from '../types.js';
@@ -0,0 +1,3 @@
1
+ export { useServerSession, requireServerSession } from "./utils/serverSession.js";
2
+ export { getValidAccessToken } from "./utils/token-refresh.js";
3
+ export { getAsgardeoContext } from "./utils/event-context.js";
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3
+ *
4
+ * WSO2 LLC. licenses this file to you under the Apache License,
5
+ * Version 2.0 (the "License"); you may not use this file except
6
+ * in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing,
12
+ * software distributed under the License is distributed on an
13
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ * KIND, either express or implied. See the License for the
15
+ * specific language governing permissions and limitations
16
+ * under the License.
17
+ */
18
+ import '../../types/augments.d.js';
19
+ /**
20
+ * Nitro server plugin — the Nuxt equivalent of `AsgardeoServerProvider` in the
21
+ * Next.js SDK.
22
+ *
23
+ * On every page request it:
24
+ * 1. Initialises the singleton {@link AsgardeoNuxtClient} once (idempotent).
25
+ * 2. Verifies the JWT session cookie → resolves `isSignedIn`.
26
+ * 3. When signed in, detects org context from the ID token (`user_org`) and
27
+ * switches `resolvedBaseUrl` to `${baseUrl}/o` when the user is acting
28
+ * within an organisation.
29
+ * 4. In parallel (gated by `preferences`):
30
+ * - Fetches user + SCIM2 user profile (`preferences.user.fetchUserProfile !== false`)
31
+ * - Fetches current org + my orgs (`preferences.user.fetchOrganizations !== false`)
32
+ * - Fetches branding preference (`preferences.theme.inheritFromBranding !== false`)
33
+ * 5. Writes the full {@link AsgardeoSSRData} to `event.context.asgardeo.ssr`
34
+ * so the Nuxt plugin can seed `useState` keys for zero-cost hydration.
35
+ *
36
+ * Each fetch is individually wrapped in try/catch so a broken SCIM or branding
37
+ * call never crashes SSR — the client layer can recover via the existing
38
+ * `/api/auth/*` routes.
39
+ */
40
+ declare const _default: import("nitropack/types").NitroAppPlugin;
41
+ export default _default;
@@ -0,0 +1,134 @@
1
+ import { getRequestURL } from "h3";
2
+ import { defineNitroPlugin } from "nitropack/runtime";
3
+ import { createLogger } from "../../utils/log.js";
4
+ import AsgardeoNuxtClient from "../AsgardeoNuxtClient.js";
5
+ import { verifyAndRehydrateSession } from "../utils/serverSession.js";
6
+ import { useRuntimeConfig } from "#imports";
7
+ import "../../types/augments.d";
8
+ const log = createLogger("asgardeo-ssr");
9
+ const CALLBACK_PATH = "/api/auth/callback";
10
+ function resolveCallbackUrl(event) {
11
+ const url = getRequestURL(event, { xForwardedHost: true, xForwardedProto: true });
12
+ return `${url.origin}${CALLBACK_PATH}`;
13
+ }
14
+ export default defineNitroPlugin((nitro) => {
15
+ nitro.hooks.hook("request", async (event) => {
16
+ const client = AsgardeoNuxtClient.getInstance();
17
+ if (!client.isInitialized) {
18
+ const config2 = useRuntimeConfig(event);
19
+ const publicConfig2 = config2.public.asgardeo;
20
+ const privateConfig = config2.asgardeo;
21
+ if (!publicConfig2?.baseUrl || !publicConfig2?.clientId) {
22
+ log.error(
23
+ "Missing required config: baseUrl and clientId. Set NUXT_PUBLIC_ASGARDEO_BASE_URL and NUXT_PUBLIC_ASGARDEO_CLIENT_ID."
24
+ );
25
+ return;
26
+ }
27
+ const sessionSecret2 = process.env["ASGARDEO_SESSION_SECRET"] || privateConfig?.sessionSecret;
28
+ if (!sessionSecret2) {
29
+ if (process.env["NODE_ENV"] === "production") {
30
+ log.error(
31
+ "ASGARDEO_SESSION_SECRET is required in production. Set it to a secure random string of at least 32 characters. Refusing to initialize Asgardeo client."
32
+ );
33
+ return;
34
+ }
35
+ log.warn(
36
+ "ASGARDEO_SESSION_SECRET is not set. Using an insecure default for development only. Set ASGARDEO_SESSION_SECRET before deploying."
37
+ );
38
+ }
39
+ try {
40
+ await client.initialize({
41
+ afterSignInUrl: resolveCallbackUrl(event),
42
+ afterSignOutUrl: publicConfig2.afterSignOutUrl || "/",
43
+ baseUrl: publicConfig2.baseUrl,
44
+ clientId: publicConfig2.clientId,
45
+ clientSecret: privateConfig?.clientSecret || void 0,
46
+ scopes: publicConfig2.scopes || ["openid", "profile"]
47
+ });
48
+ } catch (err) {
49
+ log.error("Failed to initialize Asgardeo client:", err);
50
+ return;
51
+ }
52
+ }
53
+ const url = event.path || "";
54
+ if (url.startsWith("/api/") || url.startsWith("/_nuxt/") || url.startsWith("/__nuxt_")) {
55
+ return;
56
+ }
57
+ const config = useRuntimeConfig(event);
58
+ const publicConfig = config.public.asgardeo;
59
+ const prefs = publicConfig?.preferences;
60
+ const sessionSecret = process.env["ASGARDEO_SESSION_SECRET"] || config.asgardeo?.sessionSecret;
61
+ const session = await verifyAndRehydrateSession(
62
+ event,
63
+ sessionSecret
64
+ );
65
+ if (!session) {
66
+ const eventContext2 = event.context;
67
+ eventContext2.asgardeo = { isSignedIn: false, session: null };
68
+ return;
69
+ }
70
+ const baseUrl = publicConfig?.baseUrl ?? "";
71
+ let resolvedBaseUrl = baseUrl;
72
+ try {
73
+ if (session.organizationId) {
74
+ resolvedBaseUrl = `${baseUrl}/o`;
75
+ } else {
76
+ const idToken = await client.getDecodedIdToken(
77
+ session.sessionId
78
+ );
79
+ if (idToken?.["user_org"]) {
80
+ resolvedBaseUrl = `${baseUrl}/o`;
81
+ }
82
+ }
83
+ } catch {
84
+ }
85
+ const shouldFetchProfile = prefs?.user?.fetchUserProfile !== false;
86
+ const shouldFetchOrgs = prefs?.user?.fetchOrganizations !== false;
87
+ const shouldFetchBranding = prefs?.theme?.inheritFromBranding !== false;
88
+ const [userResult, userProfileResult, orgsResult, currentOrgResult, brandingResult] = await Promise.allSettled([
89
+ // Always fetch the basic user object (needed for AsgardeoAuthState.user)
90
+ client.getUser(session.sessionId),
91
+ // SCIM2 user profile (flattened + schemas)
92
+ shouldFetchProfile ? client.getUserProfile(session.sessionId) : Promise.resolve(null),
93
+ // User's organisations
94
+ shouldFetchOrgs ? client.getMyOrganizations(session.sessionId) : Promise.resolve([]),
95
+ // Current organisation (derived from the ID token)
96
+ shouldFetchOrgs ? client.getCurrentOrganization(session.sessionId) : Promise.resolve(null),
97
+ // Branding preference (does not require a session)
98
+ shouldFetchBranding ? client.getBrandingPreference({ baseUrl: resolvedBaseUrl }) : Promise.resolve(null)
99
+ ]);
100
+ if (userResult.status === "rejected") {
101
+ log.debug("Failed to fetch user:", userResult.reason);
102
+ }
103
+ if (userProfileResult.status === "rejected") {
104
+ log.warn("Failed to fetch user profile (SCIM2):", userProfileResult.reason);
105
+ }
106
+ if (orgsResult.status === "rejected") {
107
+ log.warn("Failed to fetch my organisations:", orgsResult.reason);
108
+ }
109
+ if (currentOrgResult.status === "rejected") {
110
+ log.warn("Failed to resolve current organisation:", currentOrgResult.reason);
111
+ }
112
+ if (brandingResult.status === "rejected") {
113
+ log.warn("Failed to fetch branding preference:", brandingResult.reason);
114
+ }
115
+ const ssrData = {
116
+ brandingPreference: brandingResult.status === "fulfilled" ? brandingResult.value : null,
117
+ currentOrganization: currentOrgResult.status === "fulfilled" ? currentOrgResult.value : null,
118
+ isSignedIn: true,
119
+ myOrganizations: orgsResult.status === "fulfilled" && Array.isArray(orgsResult.value) ? orgsResult.value : [],
120
+ resolvedBaseUrl,
121
+ session,
122
+ user: userResult.status === "fulfilled" ? userResult.value : null,
123
+ userProfile: userProfileResult.status === "fulfilled" ? userProfileResult.value : null
124
+ };
125
+ const eventContext = event.context;
126
+ eventContext.asgardeo = { isSignedIn: true, session, ssr: ssrData };
127
+ const authState = {
128
+ isLoading: false,
129
+ isSignedIn: true,
130
+ user: ssrData.user
131
+ };
132
+ eventContext["__asgardeoAuth"] = authState;
133
+ });
134
+ });
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3
+ *
4
+ * WSO2 LLC. licenses this file to you under the Apache License,
5
+ * Version 2.0 (the "License"); you may not use this file except
6
+ * in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing,
12
+ * software distributed under the License is distributed on an
13
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ * KIND, either express or implied. See the License for the
15
+ * specific language governing permissions and limitations
16
+ * under the License.
17
+ */
18
+ import type { BrandingPreference } from '@asgardeo/node';
19
+ /**
20
+ * GET /api/auth/branding
21
+ *
22
+ * Returns the branding preference for the current tenant / organisation context.
23
+ * Resolves the correct `baseUrl` (org-scoped if the session is inside an org).
24
+ * Does not require an authenticated session — unauthenticated callers receive
25
+ * the root-tenant branding.
26
+ *
27
+ * Used by `AsgardeoRoot.revalidateBranding` to refresh client-side branding
28
+ * state without a full page reload.
29
+ */
30
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<BrandingPreference | null>>;
31
+ export default _default;
@@ -0,0 +1,40 @@
1
+ import { defineEventHandler, createError } from "h3";
2
+ import AsgardeoNuxtClient from "../../../AsgardeoNuxtClient.js";
3
+ import { verifyAndRehydrateSession } from "../../../utils/serverSession.js";
4
+ import { useRuntimeConfig } from "#imports";
5
+ export default defineEventHandler(async (event) => {
6
+ const config = useRuntimeConfig(event);
7
+ const publicConfig = config.public.asgardeo;
8
+ const sessionSecret = config.asgardeo?.sessionSecret;
9
+ const baseUrl = publicConfig?.baseUrl ?? "";
10
+ let resolvedBaseUrl = baseUrl;
11
+ try {
12
+ const session = await verifyAndRehydrateSession(
13
+ event,
14
+ sessionSecret
15
+ );
16
+ if (session) {
17
+ if (session.organizationId) {
18
+ resolvedBaseUrl = `${baseUrl}/o`;
19
+ } else {
20
+ const client = AsgardeoNuxtClient.getInstance();
21
+ const idToken = await client.getDecodedIdToken(
22
+ session.sessionId
23
+ );
24
+ if (idToken?.["user_org"]) {
25
+ resolvedBaseUrl = `${baseUrl}/o`;
26
+ }
27
+ }
28
+ }
29
+ } catch {
30
+ }
31
+ try {
32
+ const client = AsgardeoNuxtClient.getInstance();
33
+ return await client.getBrandingPreference({ baseUrl: resolvedBaseUrl });
34
+ } catch (err) {
35
+ throw createError({
36
+ statusCode: 500,
37
+ statusMessage: `Failed to retrieve branding preference: ${err instanceof Error ? err.message : String(err)}`
38
+ });
39
+ }
40
+ });
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3
+ *
4
+ * WSO2 LLC. licenses this file to you under the Apache License,
5
+ * Version 2.0 (the "License"); you may not use this file except
6
+ * in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing,
12
+ * software distributed under the License is distributed on an
13
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ * KIND, either express or implied. See the License for the
15
+ * specific language governing permissions and limitations
16
+ * under the License.
17
+ */
18
+ import type { Organization } from '@asgardeo/node';
19
+ /**
20
+ * GET /api/auth/organizations/current
21
+ *
22
+ * Returns the organisation the authenticated user is currently acting within,
23
+ * derived from the session's ID token (`org_id` / `org_name` claims).
24
+ * Returns `null` when the user is not inside an organisation context.
25
+ *
26
+ * Used by `AsgardeoRoot.revalidateCurrentOrganization` callback.
27
+ */
28
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<Organization | null>>;
29
+ export default _default;