@devcoffee/nuxt-core 1.1.1 → 1.2.3
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 +68 -0
- package/dist/module.d.mts +6 -5
- package/dist/module.d.ts +6 -5
- package/dist/module.json +1 -1
- package/dist/module.mjs +33 -23
- package/dist/runtime/app/composables/useAuthContext.js +33 -4
- package/dist/runtime/app/middleware/authts.js +2 -3
- package/dist/runtime/app/plugins/authts.js +28 -29
- package/dist/runtime/server/core/helpers.d.ts +2 -2
- package/dist/runtime/server/core/helpers.js +13 -2
- package/dist/runtime/server/core/nuxtAuthtsHandler.d.ts +6 -0
- package/dist/runtime/server/core/nuxtAuthtsHandler.js +19 -18
- package/dist/runtime/server/core/nuxtForwardHandler.js +3 -7
- package/dist/runtime/server/dev/route/session.d.ts +1 -1
- package/dist/runtime/server/dev/route/session.js +2 -6
- package/dist/runtime/server/plugins/authts.d.ts +2 -2
- package/dist/runtime/server/plugins/authts.js +31 -8
- package/dist/runtime/types/nitro.d.ts +2 -2
- package/package.json +8 -3
- package/dist/runtime/app/pages/authorize.d.vue.ts +0 -3
- package/dist/runtime/app/pages/authorize.vue +0 -32
- package/dist/runtime/app/pages/authorize.vue.d.ts +0 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,73 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v1.2.3
|
|
4
|
+
|
|
5
|
+
[compare changes](https://github.com/coolkg1412/devcoffee-nuxt-core/compare/v1.2.2...v1.2.3)
|
|
6
|
+
|
|
7
|
+
## v1.2.2
|
|
8
|
+
|
|
9
|
+
[compare changes](https://github.com/coolkg1412/devcoffee-nuxt-core/compare/v1.2.1...v1.2.2)
|
|
10
|
+
|
|
11
|
+
### 🩹 Fixes
|
|
12
|
+
|
|
13
|
+
- Ensure sanitizeError function returns H3Error type consistently ([de54a04](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/de54a04))
|
|
14
|
+
|
|
15
|
+
### 🏡 Chore
|
|
16
|
+
|
|
17
|
+
- Add publishConfig access public for scoped npm package ([3c080be](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/3c080be))
|
|
18
|
+
|
|
19
|
+
### ❤️ Contributors
|
|
20
|
+
|
|
21
|
+
- Hieu Nguyen <hieu.nguyen@devcoffee.tech>
|
|
22
|
+
|
|
23
|
+
## v1.2.1
|
|
24
|
+
|
|
25
|
+
[compare changes](https://github.com/coolkg1412/devcoffee-nuxt-core/compare/v1.2.0...v1.2.1)
|
|
26
|
+
|
|
27
|
+
### 🩹 Fixes
|
|
28
|
+
|
|
29
|
+
- Resolve session double encryption issue by decrypting tokenSet in validateSession and updating getSession usage in updateSession ([6ed8fb6](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/6ed8fb6))
|
|
30
|
+
- Populate nodeReferences and sharedReferences in prepare:types hook ([83b41e2](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/83b41e2))
|
|
31
|
+
- Include devcoffee-nitro-core.d.ts in server TypeScript project via nitro:config hook ([20b35e0](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/20b35e0))
|
|
32
|
+
- **typecheck:** Exclude test, playground, and eslint config from tsconfig.app.json ([9d9c857](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/9d9c857))
|
|
33
|
+
|
|
34
|
+
### ❤️ Contributors
|
|
35
|
+
|
|
36
|
+
- Hieu Nguyen <hieu.nguyen@devcoffee.tech>
|
|
37
|
+
|
|
38
|
+
## v1.2.0
|
|
39
|
+
|
|
40
|
+
[compare changes](https://github.com/coolkg1412/devcoffee-nuxt-core/compare/v1.1.1...v1.2.0)
|
|
41
|
+
|
|
42
|
+
### 🚀 Enhancements
|
|
43
|
+
|
|
44
|
+
- **quick-260328-uf7:** Create admin-board test fixture ([45dae18](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/45dae18))
|
|
45
|
+
- **quick-260328-uf7:** Add admin-board OIDC e2e test ([20bf504](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/20bf504))
|
|
46
|
+
|
|
47
|
+
### 🩹 Fixes
|
|
48
|
+
|
|
49
|
+
- **types:** Explicitly type module export as NuxtModule for better type inference ([33e140e](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/33e140e))
|
|
50
|
+
- **types:** Resolve TypeScript errors in middleware and plugins ([df23475](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/df23475))
|
|
51
|
+
- Resolve #devcoffee-core subpath import warnings in build ([#19](https://github.com/coolkg1412/devcoffee-nuxt-core/pull/19))
|
|
52
|
+
- Eliminate duplicate Redis sessions on SSR first load and refactor event.context.session ([#20](https://github.com/coolkg1412/devcoffee-nuxt-core/pull/20))
|
|
53
|
+
- Rotate session on logout and remove console.log debug statement ([fbe129f](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/fbe129f))
|
|
54
|
+
- Resolve autoFetchUser SSR divergence on first render ([1f15ac7](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/1f15ac7))
|
|
55
|
+
- **lint:** Remove unused destructure aliases in SSR session mapping ([cfe7884](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/cfe7884))
|
|
56
|
+
|
|
57
|
+
### 📖 Documentation
|
|
58
|
+
|
|
59
|
+
- **quick:** Create plan for admin-board OIDC e2e test ([ce8c611](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/ce8c611))
|
|
60
|
+
- **quick-260328-uf7:** Complete admin-board OIDC e2e plan ([23c0945](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/23c0945))
|
|
61
|
+
|
|
62
|
+
### ✅ Tests
|
|
63
|
+
|
|
64
|
+
- Update deleteSession tests to reflect renewSession LOGOUT behavior ([b444baa](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/b444baa))
|
|
65
|
+
|
|
66
|
+
### ❤️ Contributors
|
|
67
|
+
|
|
68
|
+
- Hieu Nguyen <hieu.nguyen@devcoffee.tech>
|
|
69
|
+
- Hiếu Nguyễn ([@coolkg1412](https://github.com/coolkg1412))
|
|
70
|
+
|
|
3
71
|
## v1.1.1
|
|
4
72
|
|
|
5
73
|
[compare changes](https://github.com/coolkg1412/devcoffee-nuxt-core/compare/v1.0...v1.1.1)
|
package/dist/module.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { NuxtModule } from '@nuxt/schema';
|
|
2
|
+
import { CookieSerializeOptions } from '../dist/runtime/server/adapters/http.js';
|
|
3
|
+
import { OidcUserInfo } from '../dist/runtime/server/adapters/oidc.js';
|
|
4
|
+
import { LogLevel as LogLevel$1, ConsolaOptions, ConsolaInstance } from 'consola';
|
|
4
5
|
|
|
5
6
|
interface AuthorizedUser {
|
|
6
7
|
id: string
|
|
@@ -294,7 +295,7 @@ type ModulePublicRuntimeConfig = Pick<ModuleOptions, 'defaultLocale' | 'defaultT
|
|
|
294
295
|
|
|
295
296
|
type InputModuleOptions = DeepPartial<ModuleOptions>
|
|
296
297
|
|
|
297
|
-
declare const
|
|
298
|
+
declare const _module: NuxtModule<InputModuleOptions>;
|
|
298
299
|
|
|
299
|
-
export {
|
|
300
|
+
export { _module as default };
|
|
300
301
|
export type { AuthData, AuthorizedUser, AuthtsMiddlewareMeta, AuthtsModuleOptions, CoreLogInstance, CoreLogLevel, InputModuleOptions, LoggingModuleOptions, LoggingOptions, ModuleOptions, ModulePublicRuntimeConfig, NuxtAuthOptions, NuxtCoreLogging, NuxtSessionContext, NuxtSessionUpdateContext, SessionContext };
|
package/dist/module.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { NuxtModule } from '@nuxt/schema';
|
|
2
|
+
import { CookieSerializeOptions } from '../dist/runtime/server/adapters/http.js';
|
|
3
|
+
import { OidcUserInfo } from '../dist/runtime/server/adapters/oidc.js';
|
|
4
|
+
import { LogLevel as LogLevel$1, ConsolaOptions, ConsolaInstance } from 'consola';
|
|
4
5
|
|
|
5
6
|
interface AuthorizedUser {
|
|
6
7
|
id: string
|
|
@@ -294,7 +295,7 @@ type ModulePublicRuntimeConfig = Pick<ModuleOptions, 'defaultLocale' | 'defaultT
|
|
|
294
295
|
|
|
295
296
|
type InputModuleOptions = DeepPartial<ModuleOptions>
|
|
296
297
|
|
|
297
|
-
declare const
|
|
298
|
+
declare const _module: NuxtModule<InputModuleOptions>;
|
|
298
299
|
|
|
299
|
-
export {
|
|
300
|
+
export { _module as default };
|
|
300
301
|
export type { AuthData, AuthorizedUser, AuthtsMiddlewareMeta, AuthtsModuleOptions, CoreLogInstance, CoreLogLevel, InputModuleOptions, LoggingModuleOptions, LoggingOptions, ModuleOptions, ModulePublicRuntimeConfig, NuxtAuthOptions, NuxtCoreLogging, NuxtSessionContext, NuxtSessionUpdateContext, SessionContext };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { addCustomTab } from '@nuxt/devtools-kit';
|
|
2
|
-
import { defineNuxtModule, useLogger, createResolver, addServerImports, addServerImportsDir, addServerPlugin, addImportsDir, addPlugin, addRouteMiddleware,
|
|
2
|
+
import { defineNuxtModule, useLogger, createResolver, addTemplate, addServerImports, addServerImportsDir, addServerPlugin, addImportsDir, addPlugin, addRouteMiddleware, addServerHandler } from '@nuxt/kit';
|
|
3
3
|
import { deepMerge, pick } from '../dist/runtime/utils.js';
|
|
4
4
|
|
|
5
|
-
const version = "1.
|
|
5
|
+
const version = "1.2.3";
|
|
6
6
|
|
|
7
7
|
const defaultLocale = "vi-VN";
|
|
8
8
|
const defaultLanguage = "vi";
|
|
@@ -113,7 +113,7 @@ function normalizePublicRuntimeConfig(inputOpts) {
|
|
|
113
113
|
|
|
114
114
|
const moduleName = "nuxt-core";
|
|
115
115
|
const configKey = "nuxtCore";
|
|
116
|
-
const
|
|
116
|
+
const _module = defineNuxtModule({
|
|
117
117
|
meta: {
|
|
118
118
|
name: moduleName,
|
|
119
119
|
version,
|
|
@@ -140,6 +140,25 @@ const module = defineNuxtModule({
|
|
|
140
140
|
}
|
|
141
141
|
});
|
|
142
142
|
_nuxt.options.alias["#devcoffee-core"] = resolver.resolve("./runtime");
|
|
143
|
+
const globalTypes = addTemplate({
|
|
144
|
+
filename: "types/devcoffee-global.d.ts",
|
|
145
|
+
src: resolver.resolve("./runtime/types/global.env.d.ts")
|
|
146
|
+
});
|
|
147
|
+
const nuxtTypes = addTemplate({
|
|
148
|
+
filename: "types/devcoffee-nuxt-core.d.ts",
|
|
149
|
+
src: resolver.resolve("./runtime/types/nuxt.d.ts")
|
|
150
|
+
});
|
|
151
|
+
const nitroTypes = addTemplate({
|
|
152
|
+
filename: "types/devcoffee-nitro-core.d.ts",
|
|
153
|
+
src: resolver.resolve("./runtime/types/nitro.d.ts")
|
|
154
|
+
});
|
|
155
|
+
_nuxt.options.nitro = deepMerge(_nuxt.options.nitro || {}, {
|
|
156
|
+
typescript: {
|
|
157
|
+
tsConfig: {
|
|
158
|
+
include: [globalTypes.dst]
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
143
162
|
addServerImports([
|
|
144
163
|
{
|
|
145
164
|
from: resolver.resolve("./runtime/server/core/nuxtAuthtsHandler"),
|
|
@@ -185,29 +204,20 @@ const module = defineNuxtModule({
|
|
|
185
204
|
addRouteMiddleware([{ name: "authts", path: resolver.resolve("./runtime/app/middleware/authts"), global: true }], {
|
|
186
205
|
prepend: true
|
|
187
206
|
});
|
|
188
|
-
const globalTypes = addTemplate({
|
|
189
|
-
filename: "types/devcoffee-global.d.ts",
|
|
190
|
-
src: resolver.resolve("./runtime/types/global.env.d.ts")
|
|
191
|
-
});
|
|
192
|
-
_nuxt.options.nitro = deepMerge(_nuxt.options.nitro || {}, {
|
|
193
|
-
typescript: {
|
|
194
|
-
tsConfig: {
|
|
195
|
-
include: [globalTypes.dst]
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
const nuxtTypes = addTemplate({
|
|
200
|
-
filename: "types/devcoffee-nuxt-core.d.ts",
|
|
201
|
-
src: resolver.resolve("./runtime/types/nuxt.d.ts")
|
|
202
|
-
});
|
|
203
|
-
const nitroTypes = addTemplate({
|
|
204
|
-
filename: "types/devcoffee-nitro-core.d.ts",
|
|
205
|
-
src: resolver.resolve("./runtime/types/nitro.d.ts")
|
|
206
|
-
});
|
|
207
207
|
_nuxt.hook("prepare:types", (opts) => {
|
|
208
208
|
opts.references.push({ path: globalTypes.dst });
|
|
209
209
|
opts.references.push({ path: nuxtTypes.dst });
|
|
210
210
|
opts.references.push({ path: nitroTypes.dst });
|
|
211
|
+
opts.nodeReferences.push({ path: globalTypes.dst });
|
|
212
|
+
opts.nodeReferences.push({ path: nitroTypes.dst });
|
|
213
|
+
opts.sharedReferences.push({ path: globalTypes.dst });
|
|
214
|
+
opts.sharedReferences.push({ path: globalTypes.dst });
|
|
215
|
+
});
|
|
216
|
+
_nuxt.hook("nitro:config", (nitroConfig) => {
|
|
217
|
+
nitroConfig.typescript ??= {};
|
|
218
|
+
nitroConfig.typescript.tsConfig ??= {};
|
|
219
|
+
nitroConfig.typescript.tsConfig.include ??= [];
|
|
220
|
+
nitroConfig.typescript.tsConfig.include.push(nitroTypes.dst);
|
|
211
221
|
});
|
|
212
222
|
if (_nuxt.options?.devtools) {
|
|
213
223
|
addCustomTab({
|
|
@@ -228,4 +238,4 @@ const module = defineNuxtModule({
|
|
|
228
238
|
}
|
|
229
239
|
});
|
|
230
240
|
|
|
231
|
-
export {
|
|
241
|
+
export { _module as default };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useRequestURL } from "#app";
|
|
1
|
+
import { useRequestEvent, useRequestURL, useRuntimeConfig } from "#app";
|
|
2
2
|
import {
|
|
3
3
|
computed,
|
|
4
4
|
createError,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
useRequestFetch,
|
|
10
10
|
useSessionContext
|
|
11
11
|
} from "#imports";
|
|
12
|
+
import { deleteCookie, setCookie } from "h3";
|
|
12
13
|
export function useAuthContext(initiator) {
|
|
13
14
|
const { callHook, runWithContext } = useNuxtApp();
|
|
14
15
|
const { getValue } = useSessionContext();
|
|
@@ -58,7 +59,15 @@ export function useAuthContext(initiator) {
|
|
|
58
59
|
processing.value = true;
|
|
59
60
|
}
|
|
60
61
|
}).then(
|
|
61
|
-
async ({ redirectUrl }) => runWithContext(async () =>
|
|
62
|
+
async ({ redirectUrl, cookies }) => runWithContext(async () => {
|
|
63
|
+
if (import.meta.server) {
|
|
64
|
+
const event = useRequestEvent();
|
|
65
|
+
if (event) {
|
|
66
|
+
cookies.forEach(([n, v, o]) => setCookie(event, n, v, o));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return await navigateTo(redirectUrl, { external: true, replace: true });
|
|
70
|
+
})
|
|
62
71
|
).catch((ex) => {
|
|
63
72
|
logger.log(`[login] failed error:${ex}`, ex);
|
|
64
73
|
throw sanitizeError(ex);
|
|
@@ -76,7 +85,18 @@ export function useAuthContext(initiator) {
|
|
|
76
85
|
await runWithContext(async () => await callHook("user:loggedIn"));
|
|
77
86
|
return response;
|
|
78
87
|
}).then(
|
|
79
|
-
async ({ redirectUrl }) => runWithContext(async () =>
|
|
88
|
+
async ({ redirectUrl }) => runWithContext(async () => {
|
|
89
|
+
if (import.meta.server) {
|
|
90
|
+
const event = useRequestEvent();
|
|
91
|
+
if (event) {
|
|
92
|
+
const { cookieOpts, names: cookienames } = useRuntimeConfig(event).nuxtCore.authts.sessions;
|
|
93
|
+
Array.of(cookienames.state, cookienames.pkce, cookienames.redirectUrl).forEach(
|
|
94
|
+
(cookie) => deleteCookie(event, cookie, cookieOpts)
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return await navigateTo(redirectUrl);
|
|
99
|
+
})
|
|
80
100
|
).catch((ex) => {
|
|
81
101
|
logger.log(`[authorize] failed error:${ex}`, ex);
|
|
82
102
|
throw sanitizeError(ex);
|
|
@@ -90,7 +110,16 @@ export function useAuthContext(initiator) {
|
|
|
90
110
|
processing.value = true;
|
|
91
111
|
}
|
|
92
112
|
}).then(async (response) => {
|
|
93
|
-
await runWithContext(async () =>
|
|
113
|
+
await runWithContext(async () => {
|
|
114
|
+
if (import.meta.server) {
|
|
115
|
+
const event = useRequestEvent();
|
|
116
|
+
if (event) {
|
|
117
|
+
const { cookieOpts, names: cookienames } = useRuntimeConfig(event).nuxtCore.authts.sessions;
|
|
118
|
+
deleteCookie(event, cookienames.sessionId, cookieOpts);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return await callHook("user:loggedOut");
|
|
122
|
+
});
|
|
94
123
|
return response;
|
|
95
124
|
}).then(
|
|
96
125
|
async ({ redirectUrl }) => runWithContext(async () => await navigateTo(redirectUrl))
|
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
createError,
|
|
4
4
|
defineNuxtRouteMiddleware,
|
|
5
5
|
navigateTo,
|
|
6
|
-
refreshNuxtData,
|
|
7
6
|
useCookie,
|
|
8
7
|
useNuxtApp,
|
|
9
8
|
useRequestEvent,
|
|
@@ -68,7 +67,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
|
|
|
68
67
|
logger.debug(`Bypassing auth checks for ignored path: ${normalizedPath}`);
|
|
69
68
|
return;
|
|
70
69
|
}
|
|
71
|
-
if (import.meta.
|
|
70
|
+
if (import.meta.dev && ignoreRegexPatternsDev.length && ignoreRegexPatternsDev.some((pattern) => pattern.test(normalizedPath))) {
|
|
72
71
|
logger.debug(`Bypassing auth checks for ignored path (dev): ${normalizedPath}`);
|
|
73
72
|
return;
|
|
74
73
|
}
|
|
@@ -83,7 +82,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
|
|
|
83
82
|
);
|
|
84
83
|
}
|
|
85
84
|
if (import.meta.client) {
|
|
86
|
-
await
|
|
85
|
+
await nuxtApp.$sessionContext.refetch();
|
|
87
86
|
}
|
|
88
87
|
const { isAuthenticated } = useAuthContext("core.app.authts.middleware");
|
|
89
88
|
const loginPath = loginUri.toLowerCase();
|
|
@@ -2,10 +2,10 @@ import { watch } from "vue";
|
|
|
2
2
|
import {
|
|
3
3
|
createError,
|
|
4
4
|
defineNuxtPlugin,
|
|
5
|
-
refreshNuxtData,
|
|
6
5
|
useAsyncData,
|
|
7
6
|
useCookie,
|
|
8
7
|
useNuxtApp,
|
|
8
|
+
useRequestEvent,
|
|
9
9
|
useRequestFetch,
|
|
10
10
|
useRuntimeConfig,
|
|
11
11
|
useState
|
|
@@ -21,8 +21,25 @@ export default defineNuxtPlugin(async (_nuxtApp) => {
|
|
|
21
21
|
}
|
|
22
22
|
);
|
|
23
23
|
async function __getServerSession(initiator) {
|
|
24
|
+
logger.debug(`[__getServerSession] Called with initiator: '${initiator}'`);
|
|
25
|
+
if (import.meta.server) {
|
|
26
|
+
const event = useRequestEvent();
|
|
27
|
+
const session = event?.context?.session ?? null;
|
|
28
|
+
if (!session) {
|
|
29
|
+
throw createError({
|
|
30
|
+
status: 500,
|
|
31
|
+
fatal: true,
|
|
32
|
+
statusMessage: "Failed to fetch session",
|
|
33
|
+
message: "Server session not found on event context"
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const { auth, ...rest } = session;
|
|
37
|
+
return {
|
|
38
|
+
...rest,
|
|
39
|
+
isAuthenticated: auth?.status === "authenticated" && Boolean(auth?.tokenSet && session.user?.id)
|
|
40
|
+
};
|
|
41
|
+
}
|
|
24
42
|
try {
|
|
25
|
-
logger.debug(`[__getServerSession] Called with initiator: '${initiator}'`);
|
|
26
43
|
return await fetchRequest("/api/_auth/session");
|
|
27
44
|
} catch (ex) {
|
|
28
45
|
throw createError({
|
|
@@ -41,36 +58,17 @@ export default defineNuxtPlugin(async (_nuxtApp) => {
|
|
|
41
58
|
_nuxtApp.provide("sessionReady", sessionReady);
|
|
42
59
|
const sessionId = useCookie(useRuntimeConfig().public.nuxtCore.authts.sessionCookie);
|
|
43
60
|
logger.debug(`Initial session fetch on plugin init with sessionId: ${sessionId.value}`);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
watch(data, (newData) => {
|
|
61
|
+
const { data, refresh } = await useAsyncData("authts:session", () => __getServerSession("plugin initialization"));
|
|
62
|
+
watch(
|
|
63
|
+
data,
|
|
64
|
+
(newData) => {
|
|
50
65
|
if (newData) context.value = newData;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
id: "",
|
|
55
|
-
isAuthenticated: false,
|
|
56
|
-
user: {
|
|
57
|
-
id: "",
|
|
58
|
-
sub: "",
|
|
59
|
-
email: "",
|
|
60
|
-
firstName: "Anonymous",
|
|
61
|
-
lastName: "User",
|
|
62
|
-
locale: "",
|
|
63
|
-
language: "",
|
|
64
|
-
timezone: ""
|
|
65
|
-
},
|
|
66
|
-
data: {}
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
resolveReady();
|
|
66
|
+
},
|
|
67
|
+
{ immediate: true }
|
|
68
|
+
);
|
|
70
69
|
_nuxtApp.hooks.addHooks({
|
|
71
|
-
// session:fetch calls refreshNuxtData to stay coherent with useAsyncData cache (D-04)
|
|
72
70
|
"session:fetch": async (_initiator) => {
|
|
73
|
-
await
|
|
71
|
+
await refresh({ dedupe: "cancel" });
|
|
74
72
|
},
|
|
75
73
|
"user:loggedIn": async () => {
|
|
76
74
|
await _nuxtApp.callHook("session:fetch", "user:loggedIn");
|
|
@@ -88,4 +86,5 @@ export default defineNuxtPlugin(async (_nuxtApp) => {
|
|
|
88
86
|
await _nuxtApp.callHook("session:fetch");
|
|
89
87
|
}
|
|
90
88
|
_nuxtApp.provide("sessionContext", { getValue, refetch });
|
|
89
|
+
resolveReady();
|
|
91
90
|
});
|
|
@@ -10,8 +10,8 @@ type SessionCreateOptions = {
|
|
|
10
10
|
/**
|
|
11
11
|
* Check whether a candidate redirect URL is same-origin with the request URL.
|
|
12
12
|
*
|
|
13
|
-
* Uses the WHATWG URL constructor —
|
|
14
|
-
*
|
|
13
|
+
* Uses the WHATWG URL constructor — relative paths are considered same-origin.
|
|
14
|
+
* Malformed URLs return false, guarding against attacker-controlled input.
|
|
15
15
|
*
|
|
16
16
|
* @param redirectUrl - The candidate redirect URL string (from query param or cookie).
|
|
17
17
|
* @param requestUrl - The trusted request URL from the h3 event.
|
|
@@ -47,8 +47,11 @@ function getSessionStorageKey(storagePrefix, sessionId) {
|
|
|
47
47
|
return storagePrefix ? `${storagePrefix}:${sessionId}` : sessionId;
|
|
48
48
|
}
|
|
49
49
|
export function isSameOrigin(redirectUrl, requestUrl) {
|
|
50
|
+
if (redirectUrl.includes(" ")) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
50
53
|
try {
|
|
51
|
-
return new URL(redirectUrl).origin === requestUrl.origin;
|
|
54
|
+
return new URL(redirectUrl, requestUrl.href).origin === requestUrl.origin;
|
|
52
55
|
} catch {
|
|
53
56
|
return false;
|
|
54
57
|
}
|
|
@@ -112,6 +115,14 @@ export async function validateSession(sessionCookieId, opts) {
|
|
|
112
115
|
await removeSessionData(opts.storageName, deleteSessionKey);
|
|
113
116
|
}
|
|
114
117
|
await setSessionData(opts.storageName, sessionKey, session, opts.expiresIn / 1e3 | 0);
|
|
118
|
+
if (session.auth?.tokenSet && session.auth.tokenSet.encrypted === true) {
|
|
119
|
+
if (opts.secret) {
|
|
120
|
+
const decrypted = decryptTokenSet(session.auth.tokenSet, opts.secret);
|
|
121
|
+
session.auth.tokenSet = decrypted ?? void 0;
|
|
122
|
+
} else {
|
|
123
|
+
session.auth.tokenSet = void 0;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
115
126
|
return session;
|
|
116
127
|
}
|
|
117
128
|
export async function updateSession(sessionId, input, opts) {
|
|
@@ -121,7 +132,7 @@ export async function updateSession(sessionId, input, opts) {
|
|
|
121
132
|
input,
|
|
122
133
|
["id", "issuedAt", "expiresAt"]
|
|
123
134
|
);
|
|
124
|
-
let session = await
|
|
135
|
+
let session = await getSession(sessionId, opts);
|
|
125
136
|
if (!session) {
|
|
126
137
|
throw createError({
|
|
127
138
|
status: 500,
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { NuxtAuthOptions } from '#devcoffee-core/server/adapters/http';
|
|
2
|
+
declare module 'nitropack' {
|
|
3
|
+
interface NitroApp {
|
|
4
|
+
/** Registered userInfo callback from NuxtAuthtsHandler — used by server plugin for SSR autoFetchUser enrichment. */
|
|
5
|
+
_sessionUserInfo?: NuxtAuthOptions['userInfo'];
|
|
6
|
+
}
|
|
7
|
+
}
|
|
2
8
|
/**
|
|
3
9
|
* Creates a universal authentication handler for Nuxt, integrating with OpenID Connect.
|
|
4
10
|
*
|
|
@@ -10,15 +10,14 @@ import {
|
|
|
10
10
|
useRuntimeConfig
|
|
11
11
|
} from "#devcoffee-core/server/adapters/http";
|
|
12
12
|
import { deepMerge, omit } from "#devcoffee-core/server/adapters/utils";
|
|
13
|
-
import { useStorage } from "nitropack/runtime";
|
|
13
|
+
import { useNitroApp, useStorage } from "nitropack/runtime";
|
|
14
14
|
import {
|
|
15
15
|
authorizationCodeGrant,
|
|
16
16
|
buildAuthorizationUrl,
|
|
17
17
|
constructTokenSet,
|
|
18
|
-
deleteSession,
|
|
19
18
|
fetchUserInfo,
|
|
20
|
-
getSession,
|
|
21
19
|
isSameOrigin,
|
|
20
|
+
renewSession,
|
|
22
21
|
revokeTokens,
|
|
23
22
|
updateSession
|
|
24
23
|
} from "./helpers.js";
|
|
@@ -67,20 +66,17 @@ const defaultNuxtAuthOptions = {
|
|
|
67
66
|
export default function NuxtAuthtsHandler(options) {
|
|
68
67
|
const { enabled: authEnabled, sessions: sessionConfig, openid, auth } = useRuntimeConfig().nuxtCore.authts;
|
|
69
68
|
const nuxtAuthOptions = deepMerge({ ...defaultNuxtAuthOptions }, options || {});
|
|
69
|
+
useNitroApp()._sessionUserInfo = nuxtAuthOptions.userInfo;
|
|
70
70
|
return eventHandler(async (event) => {
|
|
71
71
|
const requestUrl = getRequestURL(event);
|
|
72
72
|
const queryParams = getQuery(event);
|
|
73
73
|
const authAction = getAuthAction(requestUrl);
|
|
74
|
-
let session =
|
|
75
|
-
storageName: sessionConfig.storage.name,
|
|
76
|
-
storagePrefix: sessionConfig.storage.prefix,
|
|
77
|
-
secret: sessionConfig.secret || ""
|
|
78
|
-
});
|
|
74
|
+
let session = event.context.session;
|
|
79
75
|
if (!session) {
|
|
80
76
|
throw createError({
|
|
81
77
|
status: 500,
|
|
82
78
|
fatal: true,
|
|
83
|
-
message: `session
|
|
79
|
+
message: `session was not found on event context!`
|
|
84
80
|
});
|
|
85
81
|
}
|
|
86
82
|
if (!authEnabled && !["session" /* GET_SESSION */].includes(authAction)) {
|
|
@@ -114,7 +110,7 @@ export default function NuxtAuthtsHandler(options) {
|
|
|
114
110
|
secret: sessionConfig.secret || ""
|
|
115
111
|
});
|
|
116
112
|
}
|
|
117
|
-
event.context.
|
|
113
|
+
event.context.session = session;
|
|
118
114
|
return nuxtAuthOptions.session(omit(session, ["auth"]), session.auth);
|
|
119
115
|
case "authorize-url" /* AUTHORIZE_URL */:
|
|
120
116
|
const { authorizeUrl, state, pkceCodeVerifier } = await buildAuthorizationUrl(session, {
|
|
@@ -131,8 +127,10 @@ export default function NuxtAuthtsHandler(options) {
|
|
|
131
127
|
sessionStorageName: sessionConfig.storage.name,
|
|
132
128
|
sessionStoragePrefix: sessionConfig.storage.prefix
|
|
133
129
|
});
|
|
130
|
+
const result = { redirectUrl: authorizeUrl, cookies: [] };
|
|
134
131
|
if (pkceCodeVerifier) {
|
|
135
132
|
setCookie(event, sessionConfig.names.pkce, pkceCodeVerifier, authCookieOpts);
|
|
133
|
+
result.cookies.push([sessionConfig.names.pkce, pkceCodeVerifier, authCookieOpts]);
|
|
136
134
|
}
|
|
137
135
|
if (queryParams.redirectUrl) {
|
|
138
136
|
const candidateUrl = String(queryParams.redirectUrl);
|
|
@@ -144,10 +142,12 @@ export default function NuxtAuthtsHandler(options) {
|
|
|
144
142
|
});
|
|
145
143
|
}
|
|
146
144
|
setCookie(event, sessionConfig.names.redirectUrl, candidateUrl, authCookieOpts);
|
|
145
|
+
result.cookies.push([sessionConfig.names.redirectUrl, candidateUrl, authCookieOpts]);
|
|
147
146
|
}
|
|
148
147
|
setCookie(event, sessionConfig.names.state, state, authCookieOpts);
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
result.cookies.push([sessionConfig.names.state, state, authCookieOpts]);
|
|
149
|
+
event.context.session = session;
|
|
150
|
+
return result;
|
|
151
151
|
case "token" /* TOKEN */:
|
|
152
152
|
const formData = await readFormData(event);
|
|
153
153
|
const openIdTokenSet = await authorizationCodeGrant(
|
|
@@ -198,13 +198,13 @@ export default function NuxtAuthtsHandler(options) {
|
|
|
198
198
|
});
|
|
199
199
|
sessionData.user = await nuxtAuthOptions.userInfo(session.user, { openidUser, tokenSet });
|
|
200
200
|
}
|
|
201
|
-
await updateSession(session.id, sessionData, {
|
|
201
|
+
session = await updateSession(session.id, sessionData, {
|
|
202
202
|
storageName: sessionConfig.storage.name,
|
|
203
203
|
storagePrefix: sessionConfig.storage.prefix,
|
|
204
204
|
expiresIn: sessionConfig.expiresIn,
|
|
205
205
|
secret: sessionConfig.secret || ""
|
|
206
206
|
});
|
|
207
|
-
event.context.
|
|
207
|
+
event.context.session = session;
|
|
208
208
|
return { redirectUrl };
|
|
209
209
|
case "logout" /* LOGOUT */:
|
|
210
210
|
redirectUrl = auth.defaultLogoutRedirectUri;
|
|
@@ -217,14 +217,15 @@ export default function NuxtAuthtsHandler(options) {
|
|
|
217
217
|
wellKnownUrl: openid.wellKnownUrl
|
|
218
218
|
});
|
|
219
219
|
}
|
|
220
|
-
await
|
|
220
|
+
const newSession = await renewSession(session.id, {
|
|
221
221
|
storageName: sessionConfig.storage.name,
|
|
222
|
-
storagePrefix: sessionConfig.storage.prefix
|
|
222
|
+
storagePrefix: sessionConfig.storage.prefix,
|
|
223
|
+
expiresIn: sessionConfig.expiresIn,
|
|
224
|
+
secret: sessionConfig.secret || ""
|
|
223
225
|
});
|
|
224
226
|
const cacheStorage = useStorage("cache");
|
|
225
227
|
await cacheStorage.removeItem(`${openid.cache.prefix}:userinfo:${session.id}`);
|
|
226
|
-
|
|
227
|
-
event.context.sessionId = "";
|
|
228
|
+
event.context.session = newSession;
|
|
228
229
|
return { redirectUrl };
|
|
229
230
|
default:
|
|
230
231
|
break;
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "#devcoffee-core/server/adapters/http";
|
|
8
8
|
import { deepMerge } from "#devcoffee-core/server/adapters/utils";
|
|
9
9
|
import useServerLogger from "#devcoffee-core/server/composables/useServerLogger";
|
|
10
|
-
import { getOpenIdConfiguration
|
|
10
|
+
import { getOpenIdConfiguration } from "./helpers.js";
|
|
11
11
|
const defaultOpts = {
|
|
12
12
|
logLevel: 2,
|
|
13
13
|
proxyPrefix: ""
|
|
@@ -34,15 +34,11 @@ export default function NuxtForwardRequestHandler(opts) {
|
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
const {
|
|
37
|
-
openid: { wellKnownUrl, cache, clientId, clientSecret }
|
|
38
|
-
sessions: {
|
|
39
|
-
secret = "",
|
|
40
|
-
storage: { name: storageName, prefix: storagePrefix }
|
|
41
|
-
}
|
|
37
|
+
openid: { wellKnownUrl, cache, clientId, clientSecret }
|
|
42
38
|
} = useRuntimeConfig().nuxtCore.authts;
|
|
43
39
|
return eventHandler(async (event) => {
|
|
44
40
|
const oidConfig = await getOpenIdConfiguration(wellKnownUrl, { cache, clientId, clientSecret });
|
|
45
|
-
const session =
|
|
41
|
+
const session = event.context.session;
|
|
46
42
|
const headers = getRequestHeaders(event);
|
|
47
43
|
if (session?.auth?.status === "authenticated" && session.auth.tokenSet?.accessToken) {
|
|
48
44
|
headers.Authorization = `${session.auth.tokenSet.tokenType} ${session.auth.tokenSet?.accessToken}`;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest,
|
|
1
|
+
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, any>;
|
|
2
2
|
export default _default;
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import { defineEventHandler } from "h3";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export default defineEventHandler(async (event) => {
|
|
5
|
-
const { name: storageName, prefix: storagePrefix } = useRuntimeConfig(event).nuxtCore.authts.sessions.storage;
|
|
6
|
-
const { secret = "" } = useRuntimeConfig(event).nuxtCore.authts.sessions;
|
|
7
|
-
return await getSession(event.context.sessionId, { storageName, storagePrefix, secret });
|
|
2
|
+
export default defineEventHandler((event) => {
|
|
3
|
+
return event.context.session;
|
|
8
4
|
});
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* 🔐 Nitro plugin for session validation and cookie management.
|
|
3
3
|
*
|
|
4
4
|
* This plugin automatically validates the session ID from the incoming request cookie.
|
|
5
|
-
* If the session is invalid or expired, it will create or refresh the session
|
|
6
|
-
*
|
|
5
|
+
* If the session is invalid or expired, it will create or refresh the session and
|
|
6
|
+
* store the full session object on event.context.session for downstream handlers.
|
|
7
7
|
*
|
|
8
8
|
* @since 1.0.0
|
|
9
9
|
*/
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { defineNitroPlugin, getCookie, setCookie, useRuntimeConfig } from "#devcoffee-core/server/adapters/http";
|
|
2
2
|
import { signSessionId } from "#devcoffee-core/server/core/crypto";
|
|
3
|
-
import {
|
|
3
|
+
import { refreshTokenIfNeeded, updateSession, validateSession } from "#devcoffee-core/server/core/helpers";
|
|
4
|
+
import { useNitroApp, useStorage } from "nitropack/runtime";
|
|
4
5
|
export default defineNitroPlugin((nitroApp) => {
|
|
5
6
|
nitroApp.hooks.hook("request", async (event) => {
|
|
6
7
|
const {
|
|
7
8
|
enabled: authtsEnabled,
|
|
8
|
-
openid: {
|
|
9
|
+
openid: {
|
|
10
|
+
wellKnownUrl,
|
|
11
|
+
cache,
|
|
12
|
+
clientId,
|
|
13
|
+
clientSecret,
|
|
14
|
+
tokenRefreshBufferMs,
|
|
15
|
+
distributedLock,
|
|
16
|
+
autoFetchUser,
|
|
17
|
+
autoFetchUserTtl
|
|
18
|
+
},
|
|
9
19
|
sessions: {
|
|
10
20
|
expiresIn,
|
|
11
21
|
secret = "",
|
|
@@ -13,7 +23,7 @@ export default defineNitroPlugin((nitroApp) => {
|
|
|
13
23
|
names: { sessionId: cookieName }
|
|
14
24
|
}
|
|
15
25
|
} = useRuntimeConfig(event).nuxtCore.authts;
|
|
16
|
-
|
|
26
|
+
let session = await validateSession(getCookie(event, cookieName), {
|
|
17
27
|
storageName,
|
|
18
28
|
storagePrefix,
|
|
19
29
|
expiresIn,
|
|
@@ -30,22 +40,35 @@ export default defineNitroPlugin((nitroApp) => {
|
|
|
30
40
|
distributedLock
|
|
31
41
|
});
|
|
32
42
|
if (Object.keys(sessionUpdate).length > 0) {
|
|
33
|
-
await updateSession(session.id, sessionUpdate, { storageName, storagePrefix, expiresIn, secret });
|
|
43
|
+
session = await updateSession(session.id, sessionUpdate, { storageName, storagePrefix, expiresIn, secret });
|
|
44
|
+
}
|
|
45
|
+
if (autoFetchUser) {
|
|
46
|
+
const cacheStorage = useStorage("cache");
|
|
47
|
+
const userInfoCacheKey = `${cache.prefix}:userinfo:${session.id}`;
|
|
48
|
+
let cachedUser = await cacheStorage.getItem(userInfoCacheKey);
|
|
49
|
+
if (!cachedUser) {
|
|
50
|
+
const userInfoFn = useNitroApp()._sessionUserInfo;
|
|
51
|
+
if (userInfoFn && session.auth.tokenSet) {
|
|
52
|
+
cachedUser = await userInfoFn(session.user, { tokenSet: session.auth.tokenSet });
|
|
53
|
+
await cacheStorage.setItem(userInfoCacheKey, cachedUser, { ttl: autoFetchUserTtl });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (cachedUser) {
|
|
57
|
+
session = { ...session, user: cachedUser };
|
|
58
|
+
}
|
|
34
59
|
}
|
|
35
60
|
}
|
|
36
|
-
event.context.
|
|
61
|
+
event.context.session = session;
|
|
37
62
|
});
|
|
38
63
|
nitroApp.hooks.hook("beforeResponse", async (event) => {
|
|
39
64
|
const {
|
|
40
65
|
cookieOpts,
|
|
41
66
|
secret = "",
|
|
42
|
-
storage: { name: storageName, prefix: storagePrefix },
|
|
43
67
|
names: { sessionId: cookieName }
|
|
44
68
|
} = useRuntimeConfig(event).nuxtCore.authts.sessions;
|
|
45
|
-
const session =
|
|
69
|
+
const session = event.context.session;
|
|
46
70
|
if (session) {
|
|
47
71
|
const cookieValue = secret ? signSessionId(session.id, secret) : session.id;
|
|
48
|
-
event.context.sessionId = session.id;
|
|
49
72
|
setCookie(event, cookieName, cookieValue, {
|
|
50
73
|
...cookieOpts,
|
|
51
74
|
expires: new Date(session.expiresAt)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { CoreLogInstance, CoreLogLevel, NuxtAuthOptions } from '@devcoffee/nuxt-core'
|
|
1
|
+
import type { CoreLogInstance, CoreLogLevel, NuxtAuthOptions, SessionContext } from '@devcoffee/nuxt-core'
|
|
2
2
|
|
|
3
3
|
declare module 'h3' {
|
|
4
4
|
interface H3EventContext {
|
|
5
5
|
logger: CoreLogInstance
|
|
6
|
-
|
|
6
|
+
session: SessionContext | null
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devcoffee/nuxt-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.3",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
4
7
|
"author": "Hieu Nguyen <hieunguyen@devcoffee.tech>",
|
|
5
8
|
"description": "Nuxt 4 module providing OpenID Connect / OAuth 2.0 authorization code grant with PKCE, server-side session management via Nitro, client-side auth state composables, and universal route protection middleware.",
|
|
6
9
|
"keywords": [
|
|
@@ -51,13 +54,15 @@
|
|
|
51
54
|
"dev:build": "nuxi build playground",
|
|
52
55
|
"prepack": "nuxt-module-build build",
|
|
53
56
|
"release": "npm run lint && npm run test:all && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|
|
54
|
-
"lint": "eslint
|
|
57
|
+
"lint": "eslint",
|
|
58
|
+
"lint:fix": "eslint --fix",
|
|
55
59
|
"test": "cross-env NODE_OPTIONS=--no-deprecation vitest run test/unit",
|
|
56
60
|
"test:e2e": "cross-env NODE_OPTIONS=--no-deprecation vitest run test/e2e",
|
|
57
61
|
"test:e2e:ui": "cross-env NODE_OPTIONS=--no-deprecation PLAYWRIGHT_HEADLESS=false vitest run test/e2e",
|
|
58
62
|
"test:all": "cross-env NODE_OPTIONS=--no-deprecation vitest run",
|
|
59
63
|
"test:watch": "cross-env NODE_OPTIONS=--no-deprecation vitest watch test/unit",
|
|
60
|
-
"test:types": "vue-tsc --noEmit
|
|
64
|
+
"test:types": "vue-tsc --noEmit",
|
|
65
|
+
"typecheck": "vue-tsc --noEmit -p .nuxt/tsconfig.app.json"
|
|
61
66
|
},
|
|
62
67
|
"dependencies": {
|
|
63
68
|
"@nuxt/kit": "^4.1.3",
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
-
declare const _default: typeof __VLS_export;
|
|
3
|
-
export default _default;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import { computed, onMounted } from "vue";
|
|
3
|
-
import { createError, useRoute } from "#app";
|
|
4
|
-
import { useAuthContext } from "#imports";
|
|
5
|
-
const { query } = useRoute();
|
|
6
|
-
const { authorize } = useAuthContext("core.app.pages.authorize");
|
|
7
|
-
const searchParms = computed(() => {
|
|
8
|
-
const params = new URLSearchParams();
|
|
9
|
-
if (query.code) {
|
|
10
|
-
params.set("code", query.code);
|
|
11
|
-
}
|
|
12
|
-
if (query.state) {
|
|
13
|
-
params.set("state", query.state);
|
|
14
|
-
}
|
|
15
|
-
return params;
|
|
16
|
-
});
|
|
17
|
-
if (!searchParms.value.has("code")) {
|
|
18
|
-
throw createError({
|
|
19
|
-
status: 400,
|
|
20
|
-
message: "Invalid code params"
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
onMounted(async () => {
|
|
24
|
-
if (searchParms.value.has("code")) {
|
|
25
|
-
await authorize(searchParms.value);
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
</script>
|
|
29
|
-
|
|
30
|
-
<template>
|
|
31
|
-
<div>Nuxt module auth callback!</div>
|
|
32
|
-
</template>
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
-
declare const _default: typeof __VLS_export;
|
|
3
|
-
export default _default;
|