@habityzer/nuxt-symfony-kinde-layer 2.4.0 → 2.4.2
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/CHANGELOG.md +14 -0
- package/README.md +20 -0
- package/app/composables/useAuth.ts +3 -2
- package/app/plugins/auth-guard.client.ts +4 -3
- package/package.json +1 -2
- package/server/api/symfony/[...].ts +30 -48
- package/server/middleware/auth-guard.ts +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [2.4.2](https://github.com/Habityzer/nuxt-symfony-kinde-layer/compare/v2.4.1...v2.4.2) (2026-03-19)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* Remove unused @nuxt/image dependency ([631f4f6](https://github.com/Habityzer/nuxt-symfony-kinde-layer/commit/631f4f601e8dbb5753d06adc5471f7a54632a636))
|
|
7
|
+
|
|
8
|
+
## [2.4.1](https://github.com/Habityzer/nuxt-symfony-kinde-layer/compare/v2.4.0...v2.4.1) (2026-03-17)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* Improve logging in Symfony proxy and auth guard middleware ([4613f74](https://github.com/Habityzer/nuxt-symfony-kinde-layer/commit/4613f74fc9d9d6a4ed796675367176d46f1e0a7e))
|
|
14
|
+
|
|
1
15
|
# [2.4.0](https://github.com/Habityzer/nuxt-symfony-kinde-layer/compare/v2.3.0...v2.4.0) (2026-03-16)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -224,6 +224,22 @@ kindeAuth: {
|
|
|
224
224
|
}
|
|
225
225
|
```
|
|
226
226
|
|
|
227
|
+
### Disabling layer modules
|
|
228
|
+
|
|
229
|
+
You can disable individual modules provided by the layer by setting them to `false` in your project's `nuxt.config.ts`. The layer is still used via `extends`; only the module is disabled. For example, if you do not use `@nuxt/image`:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
export default defineNuxtConfig({
|
|
233
|
+
extends: ['@habityzer/nuxt-symfony-kinde-layer'],
|
|
234
|
+
image: false,
|
|
235
|
+
// ...
|
|
236
|
+
})
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Route groups (optional)
|
|
240
|
+
|
|
241
|
+
As an alternative to listing only public routes, you can use Nuxt route groups (e.g. `(protected)/dashboard`) and check `to.meta.groups` in middleware. For example, put protected pages under `pages/(protected)/` and in a custom middleware use `if (to.meta.groups?.includes('protected') && !isAuthenticated()) return navigateTo('/login')`. The layer's auth guard uses `publicRoutes` / `protectedRoutes` by default; route groups are optional for projects that prefer convention-based protection.
|
|
242
|
+
|
|
227
243
|
## E2E Testing
|
|
228
244
|
|
|
229
245
|
The layer supports E2E testing with app tokens:
|
|
@@ -353,6 +369,10 @@ Add these to your workflow:
|
|
|
353
369
|
|
|
354
370
|
## Troubleshooting
|
|
355
371
|
|
|
372
|
+
### Error handling and Nuxt 5 readiness
|
|
373
|
+
|
|
374
|
+
The layer uses Nuxt 4.4+ / Nuxt 5 style errors: `createError({ status, statusText })` instead of the deprecated `statusCode`/`statusMessage`. When handling errors from the proxy or auth composable, prefer reading `error.status` and `error.statusText`. The deprecated `statusCode` and `statusMessage` remain supported on `NuxtError` for backward compatibility during migration.
|
|
375
|
+
|
|
356
376
|
### Cookie Name Conflicts
|
|
357
377
|
|
|
358
378
|
If you see authentication issues, ensure each project has a unique cookie prefix:
|
|
@@ -90,8 +90,9 @@ export const useAuth = () => {
|
|
|
90
90
|
userProfile.value = response
|
|
91
91
|
return response
|
|
92
92
|
} catch (error) {
|
|
93
|
-
// Silently handle auth errors on public pages
|
|
94
|
-
|
|
93
|
+
// Silently handle auth errors on public pages (support both status and statusCode for Nuxt 4.4+ / 5)
|
|
94
|
+
const err = error as { status?: number, statusCode?: number } | undefined
|
|
95
|
+
if (err && typeof err === 'object' && (err.status === 401 || err.statusCode === 401)) {
|
|
95
96
|
console.debug('Auth check failed - user not logged in')
|
|
96
97
|
} else {
|
|
97
98
|
console.error('Failed to fetch user profile:', error)
|
|
@@ -12,9 +12,10 @@ export default defineNuxtPlugin(() => {
|
|
|
12
12
|
const e2eTokenCookieName = requireString(middlewareConfig.e2eTokenCookieName, 'kindeAuth.middleware.e2eTokenCookieName')
|
|
13
13
|
const appTokenPrefix = requireString(middlewareConfig.appTokenPrefix, 'kindeAuth.middleware.appTokenPrefix')
|
|
14
14
|
const clockSkewSeconds = requireNonNegativeNumber(middlewareConfig.clockSkewSeconds, 'kindeAuth.middleware.clockSkewSeconds')
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
15
|
+
const cookieOptions = { maxAge: 60 * 60 * 24 * 7, refresh: true }
|
|
16
|
+
const idToken = useCookie<string | null>(`${cookiePrefix}${idTokenBaseName}`, cookieOptions)
|
|
17
|
+
const accessToken = useCookie<string | null>(`${cookiePrefix}${accessTokenBaseName}`, cookieOptions)
|
|
18
|
+
const e2eToken = useCookie<string | null>(`${cookiePrefix}${e2eTokenCookieName}`, cookieOptions)
|
|
18
19
|
const mode = middlewareConfig.mode || 'privateByDefault'
|
|
19
20
|
const publicRoutes: string[] = middlewareConfig.publicRoutes || ['/']
|
|
20
21
|
const protectedRoutes: string[] = middlewareConfig.protectedRoutes || []
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@habityzer/nuxt-symfony-kinde-layer",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
4
4
|
"description": "Shared Nuxt layer for Symfony + Kinde authentication integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./nuxt.config.ts",
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@habityzer/nuxt-kinde-auth": "^1.2.2",
|
|
27
27
|
"@nuxt/eslint": "^1.9.0",
|
|
28
|
-
"@nuxt/image": "^1.11.0",
|
|
29
28
|
"@nuxt/ui": "^4.0.1",
|
|
30
29
|
"@pinia/nuxt": "^0.11.2",
|
|
31
30
|
"@vueuse/core": "^13.9.0",
|
|
@@ -47,7 +47,9 @@ export default defineEventHandler(async (event) => {
|
|
|
47
47
|
|
|
48
48
|
// Skip authentication for public routes
|
|
49
49
|
if (isPublicRoute) {
|
|
50
|
-
|
|
50
|
+
if (!process.env.E2E_TEST_MODE) {
|
|
51
|
+
console.log('[SYMFONY PROXY]', event.method, path, '(public)')
|
|
52
|
+
}
|
|
51
53
|
// Set token to empty to skip auth headers
|
|
52
54
|
token = ''
|
|
53
55
|
} else {
|
|
@@ -65,8 +67,8 @@ export default defineEventHandler(async (event) => {
|
|
|
65
67
|
|
|
66
68
|
if (!kinde?.client || !kinde?.sessionManager) {
|
|
67
69
|
throw createError({
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
status: 500,
|
|
71
|
+
statusText:
|
|
70
72
|
'Kinde authentication not initialized. Module may not be loaded correctly.'
|
|
71
73
|
})
|
|
72
74
|
}
|
|
@@ -97,15 +99,15 @@ export default defineEventHandler(async (event) => {
|
|
|
97
99
|
|
|
98
100
|
if (!token || token.trim() === '') {
|
|
99
101
|
throw createError({
|
|
100
|
-
|
|
101
|
-
|
|
102
|
+
status: 401,
|
|
103
|
+
statusText: 'Unauthorized - Please log in'
|
|
102
104
|
})
|
|
103
105
|
}
|
|
104
106
|
} catch (error) {
|
|
105
107
|
console.error('❌ [SYMFONY PROXY] Auth error:', error)
|
|
106
108
|
throw createError({
|
|
107
|
-
|
|
108
|
-
|
|
109
|
+
status: 401,
|
|
110
|
+
statusText:
|
|
109
111
|
error instanceof Error ? error.message : 'Authentication failed'
|
|
110
112
|
})
|
|
111
113
|
}
|
|
@@ -114,8 +116,8 @@ export default defineEventHandler(async (event) => {
|
|
|
114
116
|
|
|
115
117
|
if (!token && !isPublicRoute) {
|
|
116
118
|
throw createError({
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
status: 401,
|
|
120
|
+
statusText: 'No authentication token available'
|
|
119
121
|
})
|
|
120
122
|
}
|
|
121
123
|
|
|
@@ -162,19 +164,10 @@ export default defineEventHandler(async (event) => {
|
|
|
162
164
|
headers['Accept'] = accept
|
|
163
165
|
}
|
|
164
166
|
|
|
165
|
-
// Log
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
method,
|
|
170
|
-
headers: {
|
|
171
|
-
...headers,
|
|
172
|
-
Authorization: token && token !== '' ? `Bearer kinde_${token.substring(0, 10)}...` : 'none'
|
|
173
|
-
},
|
|
174
|
-
query,
|
|
175
|
-
hasBody: !!body,
|
|
176
|
-
isMultipart: contentType.includes('multipart/form-data')
|
|
177
|
-
})
|
|
167
|
+
// Log one short line per request (method + path only); skip in e2e to reduce output
|
|
168
|
+
if (!process.env.E2E_TEST_MODE) {
|
|
169
|
+
console.log('[SYMFONY PROXY]', method, path)
|
|
170
|
+
}
|
|
178
171
|
|
|
179
172
|
// Forward request to Symfony with Kinde token
|
|
180
173
|
const response = await $fetch(path, {
|
|
@@ -187,41 +180,30 @@ export default defineEventHandler(async (event) => {
|
|
|
187
180
|
timeout: 30000 // 30 second timeout
|
|
188
181
|
})
|
|
189
182
|
|
|
190
|
-
console.log('✅ [SYMFONY PROXY] Backend response received:', {
|
|
191
|
-
url: backendUrl,
|
|
192
|
-
method,
|
|
193
|
-
status: 'success'
|
|
194
|
-
})
|
|
195
|
-
|
|
196
183
|
return response
|
|
197
184
|
} catch (error) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
statusCode
|
|
201
|
-
|
|
202
|
-
? error.statusCode
|
|
203
|
-
: 'unknown',
|
|
204
|
-
message: error instanceof Error ? error.message : 'unknown'
|
|
205
|
-
})
|
|
206
|
-
// Handle Symfony API errors
|
|
207
|
-
const statusCode
|
|
208
|
-
= error && typeof error === 'object' && 'statusCode' in error
|
|
209
|
-
? (error.statusCode as number)
|
|
185
|
+
const err = error as Record<string, unknown> | undefined
|
|
186
|
+
const status
|
|
187
|
+
= err && typeof err === 'object' && ('status' in err || 'statusCode' in err)
|
|
188
|
+
? (err.status as number) ?? (err.statusCode as number)
|
|
210
189
|
: 500
|
|
211
|
-
const
|
|
212
|
-
=
|
|
213
|
-
? (
|
|
190
|
+
const statusText
|
|
191
|
+
= err && typeof err === 'object' && ('statusText' in err || 'statusMessage' in err)
|
|
192
|
+
? (err.statusText as string) ?? (err.statusMessage as string)
|
|
214
193
|
: error instanceof Error
|
|
215
194
|
? error.message
|
|
216
195
|
: 'Symfony API error'
|
|
196
|
+
console.error('❌ [SYMFONY PROXY] Symfony API error:', {
|
|
197
|
+
path,
|
|
198
|
+
status,
|
|
199
|
+
message: statusText
|
|
200
|
+
})
|
|
217
201
|
const data
|
|
218
|
-
=
|
|
219
|
-
? error.data
|
|
220
|
-
: undefined
|
|
202
|
+
= err && typeof err === 'object' && 'data' in err ? err.data : undefined
|
|
221
203
|
|
|
222
204
|
throw createError({
|
|
223
|
-
|
|
224
|
-
|
|
205
|
+
status,
|
|
206
|
+
statusText,
|
|
225
207
|
data
|
|
226
208
|
})
|
|
227
209
|
}
|
|
@@ -127,6 +127,10 @@ function logServer(event: string, details: Record<string, unknown>) {
|
|
|
127
127
|
if (process.env.NODE_ENV === 'production') {
|
|
128
128
|
return
|
|
129
129
|
}
|
|
130
|
+
// Only log when explicitly enabled (reduces noise in e2e and dev)
|
|
131
|
+
if (!process.env.NUXT_AUTH_GUARD_DEBUG) {
|
|
132
|
+
return
|
|
133
|
+
}
|
|
130
134
|
|
|
131
135
|
console.warn(`[AUTH GUARD SERVER] ${event}`, details)
|
|
132
136
|
}
|