@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.
- package/README.md +482 -6
- package/dist/module.d.mts +17 -24
- package/dist/module.json +2 -2
- package/dist/module.mjs +174 -48
- package/dist/runtime/components/AsgardeoRoot.d.ts +52 -0
- package/dist/runtime/components/AsgardeoRoot.js +160 -0
- package/dist/runtime/components/actions/SignInButton.d.ts +37 -0
- package/dist/runtime/components/actions/SignInButton.js +51 -0
- package/dist/runtime/components/actions/SignOutButton.d.ts +34 -0
- package/dist/runtime/components/actions/SignOutButton.js +43 -0
- package/dist/runtime/components/actions/SignUpButton.d.ts +33 -0
- package/dist/runtime/components/actions/SignUpButton.js +48 -0
- package/dist/runtime/components/auth/Callback.d.ts +43 -0
- package/dist/runtime/components/auth/Callback.js +93 -0
- package/dist/runtime/components/auth/SignIn.d.ts +38 -0
- package/dist/runtime/components/auth/SignIn.js +60 -0
- package/dist/runtime/components/auth/SignUp.d.ts +40 -0
- package/dist/runtime/components/auth/SignUp.js +79 -0
- package/dist/runtime/components/control/Loading.d.ts +36 -0
- package/dist/runtime/components/control/Loading.js +17 -0
- package/dist/runtime/components/control/SignedIn.d.ts +38 -0
- package/dist/runtime/components/control/SignedIn.js +17 -0
- package/dist/runtime/components/control/SignedOut.d.ts +37 -0
- package/dist/runtime/components/control/SignedOut.js +17 -0
- package/dist/runtime/components/organization/CreateOrganization.d.ts +32 -0
- package/dist/runtime/components/organization/CreateOrganization.js +29 -0
- package/dist/runtime/components/organization/Organization.d.ts +39 -0
- package/dist/runtime/components/organization/Organization.js +17 -0
- package/dist/runtime/components/organization/OrganizationList.d.ts +34 -0
- package/dist/runtime/components/organization/OrganizationList.js +30 -0
- package/dist/runtime/components/organization/OrganizationProfile.d.ts +32 -0
- package/dist/runtime/components/organization/OrganizationProfile.js +32 -0
- package/dist/runtime/components/organization/OrganizationSwitcher.d.ts +36 -0
- package/dist/runtime/components/organization/OrganizationSwitcher.js +26 -0
- package/dist/runtime/components/user/User.d.ts +38 -0
- package/dist/runtime/components/user/User.js +17 -0
- package/dist/runtime/components/user/UserDropdown.d.ts +38 -0
- package/dist/runtime/components/user/UserDropdown.js +45 -0
- package/dist/runtime/components/user/UserProfile.d.ts +35 -0
- package/dist/runtime/components/user/UserProfile.js +35 -0
- package/dist/runtime/composables/useAsgardeo.d.ts +38 -0
- package/dist/runtime/composables/useAsgardeo.js +73 -0
- package/dist/runtime/errors/asgardeo-error.d.ts +47 -0
- package/dist/runtime/errors/asgardeo-error.js +15 -0
- package/dist/runtime/errors/error-codes.d.ts +40 -0
- package/dist/runtime/errors/error-codes.js +19 -0
- package/dist/runtime/{composables/asgardeo/useAuth.d.ts → errors/index.d.ts} +2 -2
- package/dist/runtime/errors/index.js +2 -0
- package/dist/runtime/middleware/auth.d.ts +35 -0
- package/dist/runtime/middleware/auth.js +2 -0
- package/dist/runtime/middleware/defineAsgardeoMiddleware.d.ts +53 -0
- package/dist/runtime/middleware/defineAsgardeoMiddleware.js +24 -0
- package/dist/runtime/plugins/asgardeo.d.ts +40 -0
- package/dist/runtime/plugins/asgardeo.js +129 -0
- package/dist/runtime/server/AsgardeoNuxtClient.d.ts +182 -0
- package/dist/runtime/server/AsgardeoNuxtClient.js +366 -0
- package/dist/runtime/server/index.d.ts +33 -0
- package/dist/runtime/server/index.js +3 -0
- package/dist/runtime/server/plugins/asgardeo-ssr.d.ts +41 -0
- package/dist/runtime/server/plugins/asgardeo-ssr.js +134 -0
- package/dist/runtime/server/routes/auth/branding/branding.get.d.ts +31 -0
- package/dist/runtime/server/routes/auth/branding/branding.get.js +40 -0
- package/dist/runtime/server/routes/auth/organizations/current.get.d.ts +29 -0
- package/dist/runtime/server/routes/auth/organizations/current.get.js +24 -0
- package/dist/runtime/server/routes/auth/organizations/id.get.d.ts +28 -0
- package/dist/runtime/server/routes/auth/organizations/id.get.js +28 -0
- package/dist/runtime/server/routes/auth/organizations/index.get.d.ts +28 -0
- package/dist/runtime/server/routes/auth/organizations/index.get.js +24 -0
- package/dist/runtime/server/routes/auth/organizations/index.post.d.ts +30 -0
- package/dist/runtime/server/routes/auth/organizations/index.post.js +30 -0
- package/dist/runtime/server/routes/auth/organizations/me.get.d.ts +28 -0
- package/dist/runtime/server/routes/auth/organizations/me.get.js +24 -0
- package/dist/runtime/server/routes/auth/organizations/switch.post.d.ts +32 -0
- package/dist/runtime/server/routes/auth/organizations/switch.post.js +49 -0
- package/dist/runtime/server/routes/auth/session/callback.get.d.ts +27 -0
- package/dist/runtime/server/routes/auth/session/callback.get.js +91 -0
- package/dist/runtime/server/routes/auth/session/callback.post.d.ts +48 -0
- package/dist/runtime/server/routes/auth/session/callback.post.js +53 -0
- package/dist/runtime/server/routes/auth/session/session.get.d.ts +26 -0
- package/dist/runtime/server/routes/auth/session/session.get.js +22 -0
- package/dist/runtime/server/routes/auth/session/signin.get.d.ts +29 -0
- package/dist/runtime/server/routes/auth/session/signin.get.js +37 -0
- package/dist/runtime/server/routes/auth/session/signin.post.d.ts +37 -0
- package/dist/runtime/server/routes/auth/session/signin.post.js +102 -0
- package/dist/runtime/server/routes/auth/session/signout.post.d.ts +31 -0
- package/dist/runtime/server/routes/auth/session/signout.post.js +38 -0
- package/dist/runtime/server/routes/auth/session/signup.post.d.ts +36 -0
- package/dist/runtime/server/routes/auth/session/signup.post.js +30 -0
- package/dist/runtime/server/routes/auth/session/token.get.d.ts +29 -0
- package/dist/runtime/server/routes/auth/session/token.get.js +6 -0
- package/dist/runtime/server/routes/auth/user/profile.get.d.ts +29 -0
- package/dist/runtime/server/routes/auth/user/profile.get.js +24 -0
- package/dist/runtime/server/{handler.d.ts → routes/auth/user/profile.patch.d.ts} +17 -13
- package/dist/runtime/server/routes/auth/user/profile.patch.js +33 -0
- package/dist/runtime/server/{services/asgardeo/index.d.ts → routes/auth/user/user.get.d.ts} +6 -4
- package/dist/runtime/server/routes/auth/user/user.get.js +21 -0
- package/dist/runtime/server/utils/event-context.d.ts +49 -0
- package/dist/runtime/server/utils/event-context.js +3 -0
- package/dist/runtime/server/utils/serverSession.d.ts +65 -0
- package/dist/runtime/server/utils/serverSession.js +44 -0
- package/dist/runtime/server/utils/session.d.ts +85 -0
- package/dist/runtime/server/utils/session.js +106 -0
- package/dist/runtime/server/utils/token-refresh.d.ts +42 -0
- package/dist/runtime/server/utils/token-refresh.js +65 -0
- package/dist/runtime/types/augments.d.ts +61 -0
- package/dist/runtime/types.d.ts +115 -38
- package/dist/runtime/utils/createRouteMatcher.d.ts +40 -0
- package/dist/runtime/utils/createRouteMatcher.js +7 -0
- package/dist/runtime/utils/index.d.ts +30 -0
- package/dist/runtime/utils/index.js +1 -0
- package/dist/runtime/utils/log.d.ts +44 -0
- package/dist/runtime/utils/log.js +25 -0
- package/dist/runtime/utils/url-validation.d.ts +49 -0
- package/dist/runtime/utils/url-validation.js +38 -0
- package/dist/types.d.mts +0 -2
- package/package.json +48 -23
- package/dist/runtime/composables/asgardeo/useAuth.js +0 -129
- package/dist/runtime/server/handler.js +0 -231
- 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
|
|
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
|
-
#
|
|
37
|
+
# npm
|
|
15
38
|
npm install @asgardeo/nuxt
|
|
16
39
|
|
|
17
|
-
#
|
|
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
|
|
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
|
|
2
|
-
import {
|
|
3
|
-
|
|
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
|
-
|
|
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
|
-
|
|
22
|
+
asgardeo: {
|
|
31
23
|
clientSecret: string;
|
|
24
|
+
sessionSecret: string;
|
|
32
25
|
};
|
|
33
26
|
}
|
|
34
27
|
}
|