@asgardeo/nuxt 0.0.0 → 0.1.0-alpha.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
package/README.md CHANGED
@@ -1,26 +1,502 @@
1
1
  <p align="center" style="color: #343a40">
2
2
  <h1 align="center">@asgardeo/nuxt</h1>
3
3
  </p>
4
- <p align="center" style="font-size: 1.2rem;">Nuxt.js SDK for Asgardeo</p>
4
+ <p align="center" style="font-size: 1.2rem;">Nuxt 3 module for Asgardeo — Authentication and Identity Management</p>
5
5
  <div align="center">
6
6
  <img alt="npm (scoped)" src="https://img.shields.io/npm/v/@asgardeo/nuxt">
7
7
  <img alt="npm" src="https://img.shields.io/npm/dw/@asgardeo/nuxt">
8
8
  <a href="./LICENSE"><img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg" alt="License"></a>
9
9
  </div>
10
10
 
11
+ ---
12
+
13
+ ## Table of contents
14
+
15
+ - [Installation](#installation)
16
+ - [Quick start](#quick-start)
17
+ - [Configuration reference](#configuration-reference)
18
+ - [Core config](#core-config)
19
+ - [Preferences](#preferences)
20
+ - [Environment variables](#environment-variables)
21
+ - [AsgardeoRoot wrapper](#asgardeoroot-wrapper)
22
+ - [Composables](#composables)
23
+ - [Embedded (app-native) auth flows](#embedded-app-native-auth-flows)
24
+ - [Server-side data flow](#server-side-data-flow)
25
+ - [How the Nitro plugin works](#how-the-nitro-plugin-works)
26
+ - [SSR → client hydration](#ssr--client-hydration)
27
+ - [AsgardeoRoot reads hydrated state](#asgardeoroot-reads-hydrated-state)
28
+ - [Server API routes](#server-api-routes)
29
+ - [Coming from the Next.js SDK](#coming-from-the-nextjs-sdk)
30
+ - [License](#license)
31
+
32
+ ---
33
+
11
34
  ## Installation
12
35
 
13
36
  ```bash
14
- # Using npm
37
+ # npm
15
38
  npm install @asgardeo/nuxt
16
39
 
17
- # or using pnpm
40
+ # pnpm
18
41
  pnpm add @asgardeo/nuxt
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Quick start
47
+
48
+ ### 1. Register the module
49
+
50
+ ```ts
51
+ // nuxt.config.ts
52
+ export default defineNuxtConfig({
53
+ modules: ['@asgardeo/nuxt'],
54
+
55
+ asgardeo: {
56
+ baseUrl: 'https://api.asgardeo.io/t/<your-org-name>',
57
+ clientId: '<your-client-id>',
58
+ },
59
+ });
60
+ ```
61
+
62
+ Secrets should be supplied via environment variables rather than committed to source (see [Environment variables](#environment-variables)).
63
+
64
+ ### 2. Wrap your app with `<AsgardeoRoot>`
65
+
66
+ ```vue
67
+ <!-- app.vue -->
68
+ <template>
69
+ <AsgardeoRoot>
70
+ <NuxtPage />
71
+ </AsgardeoRoot>
72
+ </template>
73
+ ```
74
+
75
+ `AsgardeoRoot` is auto-registered by the module — no import needed. It mounts the full provider tree (branding, theme, user, organisation) and forwards server-resolved data to every downstream composable.
76
+
77
+ ### 3. Use composables in your pages
78
+
79
+ ```vue
80
+ <!-- pages/profile.vue -->
81
+ <script setup lang="ts">
82
+ const { isSignedIn, user, signIn, signOut } = useAsgardeo();
83
+ </script>
84
+
85
+ <template>
86
+ <div v-if="isSignedIn">
87
+ <p>Welcome, {{ user?.given_name }}</p>
88
+ <button @click="signOut()">Sign out</button>
89
+ </div>
90
+ <div v-else>
91
+ <button @click="signIn()">Sign in</button>
92
+ </div>
93
+ </template>
94
+ ```
95
+
96
+ ### 4. Protect pages with middleware
97
+
98
+ ```ts
99
+ // middleware/auth.ts
100
+ export default defineAsgardeoMiddleware();
101
+ ```
102
+
103
+ ```vue
104
+ <!-- pages/dashboard.vue -->
105
+ <script setup lang="ts">
106
+ definePageMeta({ middleware: 'auth' });
107
+ </script>
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Configuration reference
113
+
114
+ ### Core config
115
+
116
+ All options are set under the `asgardeo` key in `nuxt.config.ts`.
117
+
118
+ | Option | Type | Default | Description |
119
+ |--------|------|---------|-------------|
120
+ | `baseUrl` | `string` | — | Base URL of your Asgardeo organisation, e.g. `https://api.asgardeo.io/t/your_org`. |
121
+ | `clientId` | `string` | — | OAuth 2.0 Client ID. |
122
+ | `clientSecret` | `string` | — | OAuth 2.0 Client Secret. **Prefer the `ASGARDEO_CLIENT_SECRET` env var.** |
123
+ | `sessionSecret` | `string` | — | Secret used to sign session JWTs. **Prefer the `ASGARDEO_SESSION_SECRET` env var.** |
124
+ | `scopes` | `string[]` | `['openid', 'profile']` | OAuth 2.0 scopes to request. |
125
+ | `afterSignInUrl` | `string` | `'/'` | Path to redirect to after a successful sign-in. |
126
+ | `afterSignOutUrl` | `string` | `'/'` | Path to redirect to after sign-out. |
127
+ | `preferences` | `object` | see below | Feature-gating for server-side data fetches. |
128
+
129
+ ### Preferences
130
+
131
+ The `preferences` block controls which data the Nitro server plugin fetches on every SSR request. All options default to `true`; set to `false` to skip a fetch and reduce per-request latency.
132
+
133
+ ```ts
134
+ // nuxt.config.ts
135
+ export default defineNuxtConfig({
136
+ asgardeo: {
137
+ baseUrl: '...',
138
+ clientId: '...',
139
+ preferences: {
140
+ user: {
141
+ /**
142
+ * Fetch the SCIM2 user profile (flattened attributes + schemas) on
143
+ * every server-rendered request.
144
+ * Consumed by `useUser()` → UserProvider.
145
+ * Default: true
146
+ */
147
+ fetchUserProfile: true,
148
+
149
+ /**
150
+ * Fetch the user's organisation memberships and the current
151
+ * organisation (derived from the ID-token `org_id` claim) on every
152
+ * server-rendered request.
153
+ * Consumed by `useOrganization()` → OrganizationProvider.
154
+ * Default: true
155
+ */
156
+ fetchOrganizations: true,
157
+ },
158
+ theme: {
159
+ /**
160
+ * Fetch the Asgardeo branding preference and pass it to
161
+ * BrandingProvider / ThemeProvider so server-rendered pages match
162
+ * the configured brand theme without a client-side round-trip.
163
+ * Default: true
164
+ */
165
+ inheritFromBranding: true,
166
+ },
167
+ /**
168
+ * i18n options forwarded directly to I18nProvider.
169
+ * See @asgardeo/vue I18nProvider for the full type.
170
+ */
171
+ i18n: {
172
+ defaultLocale: 'en-US',
173
+ },
174
+ },
175
+ },
176
+ });
177
+ ```
178
+
179
+ #### When to disable a preference
180
+
181
+ | Scenario | Recommendation |
182
+ |----------|----------------|
183
+ | Public-facing marketing page that does not show user data | `fetchUserProfile: false`, `fetchOrganizations: false` to avoid unnecessary SCIM calls |
184
+ | App has its own theming system | `inheritFromBranding: false` |
185
+ | Single-organization app where org context is never needed | `fetchOrganizations: false` |
186
+
187
+ ### Environment variables
188
+
189
+ Secrets and URLs can be supplied through environment variables. They take precedence over values in `nuxt.config.ts`.
190
+
191
+ | Variable | Corresponding config key |
192
+ |----------|--------------------------|
193
+ | `NUXT_PUBLIC_ASGARDEO_BASE_URL` | `asgardeo.baseUrl` |
194
+ | `NUXT_PUBLIC_ASGARDEO_CLIENT_ID` | `asgardeo.clientId` |
195
+ | `NUXT_PUBLIC_ASGARDEO_AFTER_SIGN_IN_URL` | `asgardeo.afterSignInUrl` |
196
+ | `NUXT_PUBLIC_ASGARDEO_AFTER_SIGN_OUT_URL` | `asgardeo.afterSignOutUrl` |
197
+ | `ASGARDEO_CLIENT_SECRET` | `asgardeo.clientSecret` (**server-only**) |
198
+ | `ASGARDEO_SESSION_SECRET` | `asgardeo.sessionSecret` (**server-only**) |
199
+
200
+ > **Security note:** `ASGARDEO_CLIENT_SECRET` and `ASGARDEO_SESSION_SECRET` are server-only values. They are never exposed to the browser. Do not set them via `NUXT_PUBLIC_*` prefixed variables.
201
+
202
+ ---
203
+
204
+ ## AsgardeoRoot wrapper
205
+
206
+ `<AsgardeoRoot>` is the Nuxt equivalent of `AsgardeoClientProvider` in the Next.js SDK. It is a single component that:
207
+
208
+ 1. Reads the five SSR-hydrated `useState` keys written by the Nitro plugin.
209
+ 2. Passes them as props to the Vue SDK's provider tree:
210
+ - `I18nProvider` — receives `preferences.i18n`
211
+ - `BrandingProvider` — receives `brandingPreference`
212
+ - `ThemeProvider` — receives `inheritFromBranding`
213
+ - `FlowProvider`
214
+ - `UserProvider` — receives `profile`, `flattenedProfile`, `schemas`, and callback props
215
+ - `OrganizationProvider` — receives `currentOrganization`, `myOrganizations`, and callback props
216
+ 3. Wires callback props (e.g. `updateProfile`, `onOrganizationSwitch`) to the corresponding Nitro API routes so downstream composables like `useUser()` and `useOrganization()` work out of the box.
217
+
218
+ ### Usage
219
+
220
+ Place it at the root of your app so every page has access to auth context:
221
+
222
+ ```vue
223
+ <!-- app.vue -->
224
+ <template>
225
+ <AsgardeoRoot>
226
+ <NuxtPage />
227
+ </AsgardeoRoot>
228
+ </template>
229
+ ```
230
+
231
+ ### Preference gating in AsgardeoRoot
232
+
233
+ `AsgardeoRoot` reads the same `preferences` flags as the Nitro plugin. When a flag is `false`, the corresponding provider receives `null` / empty values and its callbacks are omitted — keeping the client in sync with what the server decided to fetch.
234
+
235
+ | Flag | Effect on providers |
236
+ |------|---------------------|
237
+ | `fetchUserProfile: false` | `UserProvider` receives `profile=null`, `flattenedProfile=null`, `schemas=null`; update/revalidate callbacks are omitted |
238
+ | `fetchOrganizations: false` | `OrganizationProvider` receives `currentOrganization=null`, `myOrganizations=[]`; switch/list callbacks are omitted |
239
+ | `inheritFromBranding: false` | `BrandingProvider` receives `brandingPreference=null`; `ThemeProvider` receives `inheritFromBranding=false` |
240
+
241
+ ---
242
+
243
+ ## Composables
244
+
245
+ All composables from `@asgardeo/vue` work inside `<AsgardeoRoot>` because the provider tree is mounted there.
246
+
247
+ | Composable | Provided by | Description |
248
+ |------------|-------------|-------------|
249
+ | `useAsgardeo()` | Nuxt plugin (ASGARDEO_KEY) | Core auth state: `isSignedIn`, `user`, `isLoading`, `signIn()`, `signOut()`, `signUp()` |
250
+ | `useUser()` | `UserProvider` | SCIM2 user profile: `profile`, `flattenedProfile`, `schemas`, `updateProfile()` |
251
+ | `useOrganization()` | `OrganizationProvider` | Org context: `currentOrganization`, `myOrganizations`, `onOrganizationSwitch()`, `getAllOrganizations()` |
252
+ | `useBranding()` | `BrandingProvider` | `brandingPreference` object |
253
+ | `useTheme()` | `ThemeProvider` | Resolved theme tokens |
254
+ | `useAsgardeoI18n()` | `I18nProvider` | i18n helpers |
255
+
256
+ ### Protecting routes
257
+
258
+ Use the built-in `defineAsgardeoMiddleware` helper to protect any route:
259
+
260
+ ```ts
261
+ // middleware/auth.ts
262
+ export default defineAsgardeoMiddleware({
263
+ // Optional: redirect unauthenticated users to a custom page
264
+ redirectTo: '/login',
265
+
266
+ // Optional: require specific OAuth scopes
267
+ requireScopes: ['openid', 'profile', 'admin'],
268
+
269
+ // Optional: require the user to be inside an organisation
270
+ requireOrganization: true,
271
+ });
272
+ ```
273
+
274
+ ---
275
+
276
+ ## Embedded (app-native) auth flows
277
+
278
+ In addition to the standard redirect flow, `@asgardeo/nuxt` supports **embedded (app-native) authentication** — rendering the sign-in / sign-up UI inline without redirecting to a separate Asgardeo login page. All OAuth traffic happens server-side through Nitro API routes so no tokens are exposed in the browser.
279
+
280
+ ### How it works
281
+
282
+ | Step | What happens |
283
+ |------|-------------|
284
+ | 1 | `<AsgardeoSignIn>` renders inline. On mount it calls `POST /api/auth/signin` with an empty body to initialise the flow. |
285
+ | 2 | The server returns the first authentication step (e.g. username / password fields). The component renders the step UI. |
286
+ | 3 | The user fills in credentials and submits. The component calls `POST /api/auth/signin` with the step payload. |
287
+ | 4 | If Asgardeo returns `flowStatus: SUCCESS_COMPLETED` the server exchanges the auth code for tokens and issues a signed session cookie. |
288
+ | 5 | If an external authenticator (social login, etc.) redirects back with a `?code=` query parameter, the `<AsgardeoCallback>` component on `/callback` calls `POST /api/auth/callback` to complete the exchange. |
289
+
290
+ ### Embedded sign-in
291
+
292
+ ```vue
293
+ <!-- pages/login.vue -->
294
+ <template>
295
+ <AsgardeoSignIn
296
+ variant="outlined"
297
+ size="medium"
298
+ @success="onSuccess"
299
+ @error="onError"
300
+ />
301
+ </template>
302
+
303
+ <script setup lang="ts">
304
+ function onSuccess() {
305
+ navigateTo('/dashboard');
306
+ }
307
+ function onError(err: unknown) {
308
+ console.error(err);
309
+ }
310
+ </script>
311
+ ```
312
+
313
+ ### Embedded sign-up
314
+
315
+ ```vue
316
+ <!-- pages/register.vue -->
317
+ <template>
318
+ <AsgardeoSignUp
319
+ variant="outlined"
320
+ @success="onSuccess"
321
+ @error="onError"
322
+ />
323
+ </template>
324
+
325
+ <script setup lang="ts">
326
+ function onSuccess() {
327
+ navigateTo('/dashboard');
328
+ }
329
+ function onError(err: unknown) {
330
+ console.error(err);
331
+ }
332
+ </script>
333
+ ```
334
+
335
+ ### Callback page (required for embedded flows)
336
+
337
+ When an embedded authenticator step redirects back to your app (e.g. social login), you need a `/callback` page that uses `<AsgardeoCallback>`:
338
+
339
+ ```vue
340
+ <!-- pages/callback.vue -->
341
+ <template>
342
+ <AsgardeoCallback
343
+ @error="(err) => console.error(err)"
344
+ />
345
+ </template>
346
+ ```
347
+
348
+ Set `callbackUrl` in `nuxt.config.ts` to match the registered redirect URI in Asgardeo:
349
+
350
+ ```ts
351
+ // nuxt.config.ts
352
+ export default defineNuxtConfig({
353
+ asgardeo: {
354
+ baseUrl: '...',
355
+ clientId: '...',
356
+ callbackUrl: '/callback', // must match the registered redirect URI
357
+ },
358
+ });
359
+ ```
360
+
361
+ ### Embedded flow API routes
362
+
363
+ | Method | Route | Description |
364
+ |--------|-------|-------------|
365
+ | `POST` | `/api/auth/signin` | Initiate or advance an embedded sign-in flow step. Empty body → returns authorize URL; step payload → returns next step or exchanges code on completion. |
366
+ | `POST` | `/api/auth/signup` | Advance an embedded sign-up flow step. No payload → returns empty `signUpUrl`; step payload → returns next step or `afterSignUpUrl` on completion. |
367
+ | `POST` | `/api/auth/callback` | Exchange an authorization code for tokens after an external IdP redirect. Reads `code`, `state`, and `sessionState` from the request body. |
368
+
369
+ ---
370
+
371
+ ## Server-side data flow
372
+
373
+ The SDK uses a three-layer pipeline to resolve auth data on the server and hydrate the client without additional network round-trips.
374
+
375
+ ### How the Nitro plugin works
376
+
377
+ On every page request the Nitro server plugin (`asgardeo-ssr.ts`) runs **before** the page is rendered:
19
378
 
20
- # or using yarn
21
- yarn add @asgardeo/nuxt
22
379
  ```
380
+ Request arrives
381
+
382
+
383
+ [1] AsgardeoNuxtClient.initialize(config) — idempotent, runs once per process
384
+
385
+
386
+ [2] Verify JWT session cookie — resolves isSignedIn + session payload
387
+
388
+ ├── Not signed in → event.context.asgardeo = {session: null, isSignedIn: false}
389
+
390
+ └── Signed in ──────────────────────────────────────────────────────────────────┐
391
+
392
+ [3] Detect org context from ID token (user_org claim) │
393
+ → resolvedBaseUrl = baseUrl + '/o' when user is in an org │
394
+
395
+ [4] Parallel fetches (gated by preferences): │
396
+ ├── getUser(sessionId) — always │
397
+ ├── getUserProfile(sessionId) — if fetchUserProfile !== false │
398
+ ├── getMyOrganizations(sessionId) — if fetchOrganizations !== false │
399
+ ├── getCurrentOrganization(...) — if fetchOrganizations !== false │
400
+ └── getBrandingPreference(...) — if inheritFromBranding !== false │
401
+
402
+ [5] Write to event.context.asgardeo.ssr ────────────────────────────────────────┘
403
+ ```
404
+
405
+ Each fetch is independently wrapped in a `try/catch` — a failed SCIM call or branding lookup does not crash SSR. The client-side `revalidate*` callbacks on `AsgardeoRoot` are the recovery path when a server fetch fails.
406
+
407
+ ### SSR → client hydration
408
+
409
+ The universal Nuxt plugin (`plugins/asgardeo.ts`) runs on both the server and client.
410
+
411
+ On the **server** it seeds five `useState` keys from `event.context.asgardeo.ssr`. Nuxt automatically serialises these into the `__NUXT__` payload that is sent to the browser:
412
+
413
+ | useState key | Source field | Consumed by |
414
+ |---|---|---|
415
+ | `asgardeo:auth` | `isSignedIn`, `user` | `useAsgardeo()` |
416
+ | `asgardeo:user-profile` | `userProfile` | `UserProvider` |
417
+ | `asgardeo:current-org` | `currentOrganization` | `OrganizationProvider` |
418
+ | `asgardeo:my-orgs` | `myOrganizations` | `OrganizationProvider` |
419
+ | `asgardeo:branding` | `brandingPreference` | `BrandingProvider` / `ThemeProvider` |
420
+
421
+ On the **client**, `useState` rehydrates from the `__NUXT__` payload — no additional network requests are made during hydration.
422
+
423
+ ### AsgardeoRoot reads hydrated state
424
+
425
+ `<AsgardeoRoot>` calls `useState` (without initialiser factories) to read the keys that the Nuxt plugin already seeded. It passes the values directly as props to each Vue provider. Because `useState` returns reactive refs, any later update (e.g. `updateProfile()` writing to `asgardeo:user-profile`) is immediately reflected in downstream composables.
426
+
427
+ ```
428
+ Nitro plugin Nuxt plugin (server) AsgardeoRoot Composables
429
+ ───────────────── ────────────────────── ────────────────── ──────────────
430
+ event.context ──────► useState('asgardeo:*) ──► I18nProvider ► useAsgardeoI18n()
431
+ .asgardeo (seeded once, SSR) BrandingProvider ► useBranding()
432
+ .ssr ThemeProvider ► useTheme()
433
+ UserProvider ► useUser()
434
+ OrgProvider ► useOrganization()
435
+ ```
436
+
437
+ ---
438
+
439
+ ## Server API routes
440
+
441
+ The module registers the following Nitro routes automatically. These back the callbacks wired by `AsgardeoRoot` and can also be called directly from your own code.
442
+
443
+ ### Authentication
444
+
445
+ | Method | Route | Description |
446
+ |--------|-------|-------------|
447
+ | `GET` | `/api/auth/signin` | Initiates the OAuth 2.0 authorization code flow. Redirects to Asgardeo. |
448
+ | `GET` | `/api/auth/callback` | Handles the OAuth callback, exchanges the code for tokens, and issues a signed session cookie. |
449
+ | `GET` | `/api/auth/signout` | Clears the session cookie and redirects to Asgardeo's end-session endpoint. |
450
+ | `GET` | `/api/auth/session` | Returns the current session state `{isSignedIn, user}` as JSON. |
451
+ | `GET` | `/api/auth/token` | Returns the current access token (for use in client-side API calls). |
452
+ | `POST` | `/api/auth/signin` | Embedded flow: initiate or advance a sign-in step. |
453
+ | `POST` | `/api/auth/signup` | Embedded flow: advance a sign-up step. |
454
+ | `POST` | `/api/auth/callback` | Embedded flow: exchange auth code after external IdP redirect. |
455
+
456
+ ### User
457
+
458
+ | Method | Route | Description |
459
+ |--------|-------|-------------|
460
+ | `GET` | `/api/auth/user` | Returns the raw user object from the in-memory token store. |
461
+ | `GET` | `/api/auth/user-profile` | Returns the full SCIM2 user profile (`profile`, `flattenedProfile`, `schemas`). |
462
+ | `POST` | `/api/auth/profile` | Updates the SCIM2 `/Me` resource. Body: `UpdateMeProfileConfig`. Returns `{data: {user}, success, error}`. |
463
+
464
+ ### Organisations
465
+
466
+ | Method | Route | Description |
467
+ |--------|-------|-------------|
468
+ | `GET` | `/api/auth/my-orgs` | Returns the list of organisations the signed-in user is a member of. |
469
+ | `GET` | `/api/auth/orgs` | Returns a paginated list of all organisations (requires sufficient scope). |
470
+ | `POST` | `/api/auth/switch-org` | Performs an organisation token exchange. Body: `{organization: Organization}`. Re-issues the session cookie with the new organisation context. |
471
+
472
+ ---
473
+
474
+ ## Coming from the Next.js SDK
475
+
476
+ If you are familiar with `@asgardeo/nextjs`, the table below maps each concept to its Nuxt equivalent.
477
+
478
+ | Next.js concept | Nuxt equivalent | Notes |
479
+ |-----------------|-----------------|-------|
480
+ | `<AsgardeoServerProvider config={...}>` | Nitro plugin `asgardeo-ssr.ts` (installed automatically by the module) | Invisible to the user — no component to place. Config comes from `nuxt.config.ts`. |
481
+ | Props passed from server component to client component | SSR-hydrated `useState` keys (`asgardeo:auth`, `asgardeo:user-profile`, etc.) | Serialised into `__NUXT__` payload; zero extra network requests on hydration. |
482
+ | `<AsgardeoClientProvider user={...} userProfile={...} ...>` | `<AsgardeoRoot>` | Reads the hydrated state and passes it as props to Vue SDK providers. |
483
+ | Server actions (`signInAction`, `signOutAction`, …) | Nitro server routes (`/api/auth/signin`, `/api/auth/signout`, …) | Already implemented. |
484
+ | `AsgardeoContext.Provider` value | `nuxtApp.vueApp.provide(ASGARDEO_KEY, …)` in the Nuxt plugin | Same result: `useAsgardeo()` reads from `ASGARDEO_KEY`. |
485
+ | `config.preferences.*` on `<AsgardeoServerProvider>` | `asgardeo.preferences.*` in `nuxt.config.ts` | Identical flag names. |
486
+ | Client-side OAuth callback (`useEffect` detecting `?code&state`) | Not needed — `/api/auth/callback` handles the full exchange server-side | Nuxt never exposes the OAuth code to the browser, which is an improvement. |
487
+ | `useSearchParams()` / `useRouter()` inside client provider | Not needed | See above. |
488
+ | `handleSignIn` / `handleSignOut` wrapping server actions + `router.push` | `signIn()` / `signOut()` calling `navigateTo('/api/auth/signin')` | Functionally equivalent; slightly simpler in Nuxt because there is no server-action boundary. |
489
+
490
+ ### Key design insight
491
+
492
+ React Server Components and Nuxt's Nitro-plugin-plus-`useState` approach are two implementations of the same idea: the server resolves auth data and the client hydrates against it. The user-visible API deliberately uses Nuxt idioms rather than mimicking React Server Component tree structure.
493
+
494
+ - The **Nitro plugin** *is* `AsgardeoServerProvider`.
495
+ - **`<AsgardeoRoot>`** *is* `AsgardeoClientProvider`.
496
+ - The hand-off happens through `useState` instead of component props — but the result is identical.
497
+
498
+ ---
23
499
 
24
500
  ## License
25
501
 
26
- Apache-2.0
502
+ Licenses this source under the Apache License, Version 2.0 [LICENSE](./LICENSE), You may not use this file except in compliance with the License.
package/dist/module.d.mts CHANGED
@@ -1,34 +1,27 @@
1
- import { NuxtModule } from 'nuxt/schema';
2
- import { ModuleOptions } from '../dist/runtime/types.js';
3
- export { BasicUserInfo } from '../dist/runtime/types.js';
1
+ import * as __runtime_types from '../dist/runtime/types.js';
2
+ import { AsgardeoNuxtConfig } from '../dist/runtime/types.js';
3
+ import * as _nuxt_schema from '@nuxt/schema';
4
4
 
5
- /**
6
- * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
7
- *
8
- * WSO2 LLC. licenses this file to you under the Apache License,
9
- * Version 2.0 (the "License"); you may not use this file except
10
- * in compliance with the License.
11
- * You may obtain a copy of the License at
12
- *
13
- * http://www.apache.org/licenses/LICENSE-2.0
14
- *
15
- * Unless required by applicable law or agreed to in writing,
16
- * software distributed under the License is distributed on an
17
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18
- * KIND, either express or implied. See the License for the
19
- * specific language governing permissions and limitations
20
- * under the License.
21
- */
22
-
23
- declare const _default: NuxtModule<ModuleOptions, ModuleOptions, false>;
5
+ declare const _default: _nuxt_schema.NuxtModule<AsgardeoNuxtConfig, AsgardeoNuxtConfig, false>;
24
6
 
25
7
  declare module '@nuxt/schema' {
26
8
  interface PublicRuntimeConfig {
27
- asgardeoAuth: Pick<ModuleOptions, 'clientID' | 'baseUrl' | 'signInRedirectURL' | 'signOutRedirectURL' | 'scope'>;
9
+ asgardeo: {
10
+ afterSignInUrl: string;
11
+ afterSignOutUrl: string;
12
+ applicationId?: string;
13
+ baseUrl: string;
14
+ clientId: string;
15
+ preferences?: __runtime_types.AsgardeoNuxtConfig['preferences'];
16
+ scopes: string[];
17
+ signInUrl?: string;
18
+ signUpUrl?: string;
19
+ };
28
20
  }
29
21
  interface RuntimeConfig {
30
- asgardeoAuth: {
22
+ asgardeo: {
31
23
  clientSecret: string;
24
+ sessionSecret: string;
32
25
  };
33
26
  }
34
27
  }
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "configKey": "asgardeoAuth",
2
+ "configKey": "asgardeo",
3
3
  "name": "@asgardeo/nuxt",
4
- "version": "0.0.0",
4
+ "version": "0.1.0-alpha.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.1",
7
7
  "unbuild": "unknown"