@peterbud/nuxt-aegis 1.1.0-alpha
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 +166 -0
- package/dist/module.d.mts +6 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +354 -0
- package/dist/runtime/app/composables/useAuth.d.ts +85 -0
- package/dist/runtime/app/composables/useAuth.js +187 -0
- package/dist/runtime/app/middleware/auth-logged-in.d.ts +16 -0
- package/dist/runtime/app/middleware/auth-logged-in.js +25 -0
- package/dist/runtime/app/middleware/auth-logged-out.d.ts +20 -0
- package/dist/runtime/app/middleware/auth-logged-out.js +17 -0
- package/dist/runtime/app/pages/AuthCallback.d.vue.ts +3 -0
- package/dist/runtime/app/pages/AuthCallback.vue +92 -0
- package/dist/runtime/app/pages/AuthCallback.vue.d.ts +3 -0
- package/dist/runtime/app/plugins/api.client.d.ts +11 -0
- package/dist/runtime/app/plugins/api.client.js +92 -0
- package/dist/runtime/app/plugins/api.server.d.ts +13 -0
- package/dist/runtime/app/plugins/api.server.js +28 -0
- package/dist/runtime/app/plugins/ssr-state.server.d.ts +2 -0
- package/dist/runtime/app/plugins/ssr-state.server.js +13 -0
- package/dist/runtime/app/router.options.d.ts +12 -0
- package/dist/runtime/app/router.options.js +11 -0
- package/dist/runtime/app/utils/logger.d.ts +18 -0
- package/dist/runtime/app/utils/logger.js +48 -0
- package/dist/runtime/app/utils/redirectValidation.d.ts +18 -0
- package/dist/runtime/app/utils/redirectValidation.js +21 -0
- package/dist/runtime/app/utils/routeMatching.d.ts +13 -0
- package/dist/runtime/app/utils/routeMatching.js +10 -0
- package/dist/runtime/app/utils/tokenStore.d.ts +24 -0
- package/dist/runtime/app/utils/tokenStore.js +14 -0
- package/dist/runtime/app/utils/tokenUtils.d.ts +17 -0
- package/dist/runtime/app/utils/tokenUtils.js +4 -0
- package/dist/runtime/server/middleware/auth.d.ts +6 -0
- package/dist/runtime/server/middleware/auth.js +82 -0
- package/dist/runtime/server/plugins/ssr-auth.d.ts +7 -0
- package/dist/runtime/server/plugins/ssr-auth.js +82 -0
- package/dist/runtime/server/providers/auth0.d.ts +12 -0
- package/dist/runtime/server/providers/auth0.js +57 -0
- package/dist/runtime/server/providers/github.d.ts +12 -0
- package/dist/runtime/server/providers/github.js +44 -0
- package/dist/runtime/server/providers/google.d.ts +12 -0
- package/dist/runtime/server/providers/google.js +46 -0
- package/dist/runtime/server/providers/mock.d.ts +37 -0
- package/dist/runtime/server/providers/mock.js +129 -0
- package/dist/runtime/server/providers/oauthBase.d.ts +72 -0
- package/dist/runtime/server/providers/oauthBase.js +183 -0
- package/dist/runtime/server/routes/impersonate.post.d.ts +21 -0
- package/dist/runtime/server/routes/impersonate.post.js +68 -0
- package/dist/runtime/server/routes/logout.post.d.ts +9 -0
- package/dist/runtime/server/routes/logout.post.js +24 -0
- package/dist/runtime/server/routes/me.get.d.ts +6 -0
- package/dist/runtime/server/routes/me.get.js +11 -0
- package/dist/runtime/server/routes/mock/authorize.get.d.ts +29 -0
- package/dist/runtime/server/routes/mock/authorize.get.js +103 -0
- package/dist/runtime/server/routes/mock/token.post.d.ts +31 -0
- package/dist/runtime/server/routes/mock/token.post.js +88 -0
- package/dist/runtime/server/routes/mock/userinfo.get.d.ts +27 -0
- package/dist/runtime/server/routes/mock/userinfo.get.js +59 -0
- package/dist/runtime/server/routes/password/change.post.d.ts +4 -0
- package/dist/runtime/server/routes/password/change.post.js +108 -0
- package/dist/runtime/server/routes/password/login-verify.get.d.ts +2 -0
- package/dist/runtime/server/routes/password/login-verify.get.js +79 -0
- package/dist/runtime/server/routes/password/login.post.d.ts +4 -0
- package/dist/runtime/server/routes/password/login.post.js +66 -0
- package/dist/runtime/server/routes/password/register-verify.get.d.ts +2 -0
- package/dist/runtime/server/routes/password/register-verify.get.js +86 -0
- package/dist/runtime/server/routes/password/register.post.d.ts +4 -0
- package/dist/runtime/server/routes/password/register.post.js +87 -0
- package/dist/runtime/server/routes/password/reset-complete.post.d.ts +4 -0
- package/dist/runtime/server/routes/password/reset-complete.post.js +75 -0
- package/dist/runtime/server/routes/password/reset-request.post.d.ts +5 -0
- package/dist/runtime/server/routes/password/reset-request.post.js +52 -0
- package/dist/runtime/server/routes/password/reset-verify.get.d.ts +2 -0
- package/dist/runtime/server/routes/password/reset-verify.get.js +50 -0
- package/dist/runtime/server/routes/refresh.post.d.ts +8 -0
- package/dist/runtime/server/routes/refresh.post.js +102 -0
- package/dist/runtime/server/routes/token.post.d.ts +28 -0
- package/dist/runtime/server/routes/token.post.js +90 -0
- package/dist/runtime/server/routes/unimpersonate.post.d.ts +16 -0
- package/dist/runtime/server/routes/unimpersonate.post.js +65 -0
- package/dist/runtime/server/tsconfig.json +3 -0
- package/dist/runtime/server/utils/auth.d.ts +94 -0
- package/dist/runtime/server/utils/auth.js +54 -0
- package/dist/runtime/server/utils/authCodeStore.d.ts +137 -0
- package/dist/runtime/server/utils/authCodeStore.js +123 -0
- package/dist/runtime/server/utils/cookies.d.ts +15 -0
- package/dist/runtime/server/utils/cookies.js +23 -0
- package/dist/runtime/server/utils/customClaims.d.ts +37 -0
- package/dist/runtime/server/utils/customClaims.js +45 -0
- package/dist/runtime/server/utils/handler.d.ts +77 -0
- package/dist/runtime/server/utils/handler.js +7 -0
- package/dist/runtime/server/utils/impersonation.d.ts +48 -0
- package/dist/runtime/server/utils/impersonation.js +259 -0
- package/dist/runtime/server/utils/jwt.d.ts +24 -0
- package/dist/runtime/server/utils/jwt.js +77 -0
- package/dist/runtime/server/utils/logger.d.ts +18 -0
- package/dist/runtime/server/utils/logger.js +49 -0
- package/dist/runtime/server/utils/magicCodeStore.d.ts +27 -0
- package/dist/runtime/server/utils/magicCodeStore.js +66 -0
- package/dist/runtime/server/utils/mockCodeStore.d.ts +89 -0
- package/dist/runtime/server/utils/mockCodeStore.js +71 -0
- package/dist/runtime/server/utils/password.d.ts +33 -0
- package/dist/runtime/server/utils/password.js +48 -0
- package/dist/runtime/server/utils/refreshToken.d.ts +74 -0
- package/dist/runtime/server/utils/refreshToken.js +108 -0
- package/dist/runtime/server/utils/resetSessionStore.d.ts +12 -0
- package/dist/runtime/server/utils/resetSessionStore.js +29 -0
- package/dist/runtime/tasks/cleanup/magic-codes.d.ts +10 -0
- package/dist/runtime/tasks/cleanup/magic-codes.js +79 -0
- package/dist/runtime/tasks/cleanup/refresh-tokens.d.ts +10 -0
- package/dist/runtime/tasks/cleanup/refresh-tokens.js +55 -0
- package/dist/runtime/tasks/cleanup/reset-sessions.d.ts +8 -0
- package/dist/runtime/tasks/cleanup/reset-sessions.js +45 -0
- package/dist/runtime/types/augmentation.d.ts +73 -0
- package/dist/runtime/types/augmentation.js +0 -0
- package/dist/runtime/types/authCode.d.ts +60 -0
- package/dist/runtime/types/authCode.js +0 -0
- package/dist/runtime/types/callbacks.d.ts +54 -0
- package/dist/runtime/types/callbacks.js +0 -0
- package/dist/runtime/types/config.d.ts +129 -0
- package/dist/runtime/types/config.js +0 -0
- package/dist/runtime/types/hooks.d.ts +118 -0
- package/dist/runtime/types/hooks.js +0 -0
- package/dist/runtime/types/index.d.ts +13 -0
- package/dist/runtime/types/index.js +1 -0
- package/dist/runtime/types/providers.d.ts +212 -0
- package/dist/runtime/types/providers.js +0 -0
- package/dist/runtime/types/refresh.d.ts +61 -0
- package/dist/runtime/types/refresh.js +0 -0
- package/dist/runtime/types/routes.d.ts +30 -0
- package/dist/runtime/types/routes.js +0 -0
- package/dist/runtime/types/token.d.ts +182 -0
- package/dist/runtime/types/token.js +0 -0
- package/dist/types.d.mts +7 -0
- package/package.json +80 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { useStorage } from "#imports";
|
|
3
|
+
import { createLogger } from "./logger.js";
|
|
4
|
+
const logger = createLogger("ResetSession");
|
|
5
|
+
export async function createResetSession(email, ttl = 300) {
|
|
6
|
+
const storage = useStorage();
|
|
7
|
+
const sessionId = randomBytes(32).toString("base64url");
|
|
8
|
+
const now = Date.now();
|
|
9
|
+
const data = {
|
|
10
|
+
email: email.toLowerCase(),
|
|
11
|
+
expiresAt: now + ttl * 1e3
|
|
12
|
+
};
|
|
13
|
+
await storage.setItem(`reset:${sessionId}`, data);
|
|
14
|
+
logger.debug(`Reset session created for ${email}`);
|
|
15
|
+
return sessionId;
|
|
16
|
+
}
|
|
17
|
+
export async function validateAndDeleteResetSession(sessionId) {
|
|
18
|
+
const storage = useStorage();
|
|
19
|
+
const key = `reset:${sessionId}`;
|
|
20
|
+
const data = await storage.getItem(key);
|
|
21
|
+
if (!data) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
await storage.removeItem(key);
|
|
25
|
+
if (Date.now() > data.expiresAt) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return data.email;
|
|
29
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { defineTask, useStorage } from "nitropack/runtime";
|
|
2
|
+
import { createLogger } from "../../server/utils/logger.js";
|
|
3
|
+
const logger = createLogger("Task:CleanupMagicCodes");
|
|
4
|
+
export default defineTask({
|
|
5
|
+
meta: {
|
|
6
|
+
name: "cleanup:magic-codes",
|
|
7
|
+
description: "Clean up expired magic codes and their lookup keys"
|
|
8
|
+
},
|
|
9
|
+
async run() {
|
|
10
|
+
logger.info("Starting magic code cleanup task...");
|
|
11
|
+
const storage = useStorage();
|
|
12
|
+
const now = Date.now();
|
|
13
|
+
const allKeys = await storage.getKeys();
|
|
14
|
+
const magicCodeKeys = allKeys.filter((key) => key.startsWith("magic:"));
|
|
15
|
+
const lookupKeys = allKeys.filter((key) => key.startsWith("magic-lookup:"));
|
|
16
|
+
let deletedCount = 0;
|
|
17
|
+
let errorCount = 0;
|
|
18
|
+
let skippedCount = 0;
|
|
19
|
+
const deletedLookupKeys = /* @__PURE__ */ new Set();
|
|
20
|
+
for (const key of magicCodeKeys) {
|
|
21
|
+
try {
|
|
22
|
+
const data = await storage.getItem(key);
|
|
23
|
+
if (!data) {
|
|
24
|
+
skippedCount++;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (data.expiresAt < now) {
|
|
28
|
+
await storage.removeItem(key);
|
|
29
|
+
deletedCount++;
|
|
30
|
+
const lookupKey = `magic-lookup:${data.email}:${data.type}`;
|
|
31
|
+
deletedLookupKeys.add(lookupKey);
|
|
32
|
+
logger.debug(`Deleted expired magic code for ${data.email} (${data.type})`);
|
|
33
|
+
}
|
|
34
|
+
} catch (error) {
|
|
35
|
+
errorCount++;
|
|
36
|
+
logger.error(`Error processing magic code ${key}:`, error);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
let lookupDeletedCount = 0;
|
|
40
|
+
for (const lookupKey of deletedLookupKeys) {
|
|
41
|
+
try {
|
|
42
|
+
await storage.removeItem(lookupKey);
|
|
43
|
+
lookupDeletedCount++;
|
|
44
|
+
} catch (error) {
|
|
45
|
+
errorCount++;
|
|
46
|
+
logger.error(`Error deleting lookup key ${lookupKey}:`, error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
let orphanedCount = 0;
|
|
50
|
+
for (const lookupKey of lookupKeys) {
|
|
51
|
+
try {
|
|
52
|
+
const code = await storage.getItem(lookupKey);
|
|
53
|
+
if (code) {
|
|
54
|
+
const magicCodeKey = `magic:${code}`;
|
|
55
|
+
const exists = await storage.getItem(magicCodeKey);
|
|
56
|
+
if (!exists) {
|
|
57
|
+
await storage.removeItem(lookupKey);
|
|
58
|
+
orphanedCount++;
|
|
59
|
+
logger.debug(`Deleted orphaned lookup key: ${lookupKey}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
errorCount++;
|
|
64
|
+
logger.error(`Error processing lookup key ${lookupKey}:`, error);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const result = {
|
|
68
|
+
totalProcessed: magicCodeKeys.length,
|
|
69
|
+
deleted: deletedCount,
|
|
70
|
+
lookupKeysDeleted: lookupDeletedCount,
|
|
71
|
+
orphanedKeysDeleted: orphanedCount,
|
|
72
|
+
skipped: skippedCount,
|
|
73
|
+
errors: errorCount,
|
|
74
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
75
|
+
};
|
|
76
|
+
logger.info(`Magic code cleanup completed: ${deletedCount} codes deleted, ${lookupDeletedCount} lookup keys deleted, ${orphanedCount} orphaned keys deleted, ${skippedCount} skipped, ${errorCount} errors`);
|
|
77
|
+
return { result };
|
|
78
|
+
}
|
|
79
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { defineTask, useStorage } from "nitropack/runtime";
|
|
2
|
+
import { getRefreshTokenData } from "../../server/utils/refreshToken.js";
|
|
3
|
+
import { createLogger } from "../../server/utils/logger.js";
|
|
4
|
+
const logger = createLogger("Task:CleanupRefreshTokens");
|
|
5
|
+
export default defineTask({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "cleanup:refresh-tokens",
|
|
8
|
+
description: "Clean up expired and revoked refresh tokens from storage"
|
|
9
|
+
},
|
|
10
|
+
async run() {
|
|
11
|
+
logger.info("Starting refresh token cleanup task...");
|
|
12
|
+
const storage = useStorage("refreshTokenStore");
|
|
13
|
+
const keys = await storage.getKeys();
|
|
14
|
+
const now = Date.now();
|
|
15
|
+
let deletedCount = 0;
|
|
16
|
+
let revokedCount = 0;
|
|
17
|
+
let expiredCount = 0;
|
|
18
|
+
let errorCount = 0;
|
|
19
|
+
let skippedCount = 0;
|
|
20
|
+
for (const tokenHash of keys) {
|
|
21
|
+
try {
|
|
22
|
+
const data = await getRefreshTokenData(tokenHash);
|
|
23
|
+
if (!data) {
|
|
24
|
+
skippedCount++;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (data.expiresAt < now || data.isRevoked) {
|
|
28
|
+
await storage.removeItem(tokenHash);
|
|
29
|
+
deletedCount++;
|
|
30
|
+
if (data.isRevoked) {
|
|
31
|
+
revokedCount++;
|
|
32
|
+
logger.debug(`Deleted revoked refresh token: ${tokenHash.substring(0, 8)}...`);
|
|
33
|
+
} else {
|
|
34
|
+
expiredCount++;
|
|
35
|
+
logger.debug(`Deleted expired refresh token: ${tokenHash.substring(0, 8)}...`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
} catch (error) {
|
|
39
|
+
errorCount++;
|
|
40
|
+
logger.error(`Error processing token ${tokenHash.substring(0, 8)}...:`, error);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const result = {
|
|
44
|
+
totalProcessed: keys.length,
|
|
45
|
+
deleted: deletedCount,
|
|
46
|
+
expired: expiredCount,
|
|
47
|
+
revoked: revokedCount,
|
|
48
|
+
skipped: skippedCount,
|
|
49
|
+
errors: errorCount,
|
|
50
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
51
|
+
};
|
|
52
|
+
logger.info(`Refresh token cleanup completed: ${deletedCount} deleted (${expiredCount} expired, ${revokedCount} revoked), ${skippedCount} skipped, ${errorCount} errors`);
|
|
53
|
+
return { result };
|
|
54
|
+
}
|
|
55
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { defineTask, useStorage } from "nitropack/runtime";
|
|
2
|
+
import { createLogger } from "../../server/utils/logger.js";
|
|
3
|
+
const logger = createLogger("Task:CleanupResetSessions");
|
|
4
|
+
export default defineTask({
|
|
5
|
+
meta: {
|
|
6
|
+
name: "cleanup:reset-sessions",
|
|
7
|
+
description: "Clean up expired password reset sessions"
|
|
8
|
+
},
|
|
9
|
+
async run() {
|
|
10
|
+
logger.info("Starting reset session cleanup task...");
|
|
11
|
+
const storage = useStorage();
|
|
12
|
+
const allKeys = await storage.getKeys();
|
|
13
|
+
const resetKeys = allKeys.filter((key) => key.startsWith("reset:"));
|
|
14
|
+
const now = Date.now();
|
|
15
|
+
let deletedCount = 0;
|
|
16
|
+
let errorCount = 0;
|
|
17
|
+
let skippedCount = 0;
|
|
18
|
+
for (const key of resetKeys) {
|
|
19
|
+
try {
|
|
20
|
+
const data = await storage.getItem(key);
|
|
21
|
+
if (!data) {
|
|
22
|
+
skippedCount++;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (data.expiresAt < now) {
|
|
26
|
+
await storage.removeItem(key);
|
|
27
|
+
deletedCount++;
|
|
28
|
+
logger.debug(`Deleted expired reset session for ${data.email}`);
|
|
29
|
+
}
|
|
30
|
+
} catch (error) {
|
|
31
|
+
errorCount++;
|
|
32
|
+
logger.error(`Error processing reset session ${key}:`, error);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const result = {
|
|
36
|
+
totalProcessed: resetKeys.length,
|
|
37
|
+
deleted: deletedCount,
|
|
38
|
+
skipped: skippedCount,
|
|
39
|
+
errors: errorCount,
|
|
40
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
41
|
+
};
|
|
42
|
+
logger.info(`Reset session cleanup completed: ${deletedCount} deleted, ${skippedCount} skipped, ${errorCount} errors`);
|
|
43
|
+
return { result };
|
|
44
|
+
}
|
|
45
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { NuxtAegisRuntimeConfig, RedirectConfig, LoggingConfig } from './config.js';
|
|
2
|
+
import type { TokenRefreshConfig } from './refresh.js';
|
|
3
|
+
import type { TokenPayload } from './token.js';
|
|
4
|
+
import type { ClientMiddlewareConfig } from './routes.js';
|
|
5
|
+
import type { SuccessHookPayload } from './hooks.js';
|
|
6
|
+
/**
|
|
7
|
+
* Module augmentations for external libraries
|
|
8
|
+
*/
|
|
9
|
+
declare module '@nuxt/schema' {
|
|
10
|
+
interface RuntimeConfig {
|
|
11
|
+
nuxtAegis?: NuxtAegisRuntimeConfig;
|
|
12
|
+
}
|
|
13
|
+
interface PublicRuntimeConfig {
|
|
14
|
+
nuxtAegis: {
|
|
15
|
+
authPath: string;
|
|
16
|
+
loginPath: string;
|
|
17
|
+
callbackPath: string;
|
|
18
|
+
logoutPath: string;
|
|
19
|
+
refreshPath: string;
|
|
20
|
+
userInfoPath: string;
|
|
21
|
+
redirect: RedirectConfig;
|
|
22
|
+
tokenRefresh: TokenRefreshConfig;
|
|
23
|
+
clientMiddleware?: ClientMiddlewareConfig;
|
|
24
|
+
logging: LoggingConfig;
|
|
25
|
+
enableSSR: boolean;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
declare module 'nitropack' {
|
|
30
|
+
interface NitroRuntimeHooks {
|
|
31
|
+
/**
|
|
32
|
+
* Hook called after successful authentication.
|
|
33
|
+
* Use this for logging, analytics, or database operations.
|
|
34
|
+
*/
|
|
35
|
+
'nuxt-aegis:success': (payload: SuccessHookPayload) => Promise<void> | void;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
declare module 'h3' {
|
|
39
|
+
interface H3EventContext {
|
|
40
|
+
/**
|
|
41
|
+
* Authenticated user data from JWT token
|
|
42
|
+
* Available when request is authenticated via the auth middleware
|
|
43
|
+
*/
|
|
44
|
+
user?: TokenPayload;
|
|
45
|
+
/**
|
|
46
|
+
* Original user data before impersonation
|
|
47
|
+
* Available when impersonation is active
|
|
48
|
+
*/
|
|
49
|
+
originalUser?: {
|
|
50
|
+
sub: string;
|
|
51
|
+
email?: string;
|
|
52
|
+
name?: string;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
declare module '#app' {
|
|
57
|
+
interface NuxtApp {
|
|
58
|
+
/**
|
|
59
|
+
* Custom $fetch instance with automatic bearer token injection
|
|
60
|
+
* Configured by the Nuxt Aegis plugin
|
|
61
|
+
*/
|
|
62
|
+
$api: typeof $fetch;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
declare module 'vue' {
|
|
66
|
+
interface ComponentCustomProperties {
|
|
67
|
+
/**
|
|
68
|
+
* Custom $fetch instance with automatic bearer token injection
|
|
69
|
+
* Configured by the Nuxt Aegis plugin
|
|
70
|
+
*/
|
|
71
|
+
$api: typeof $fetch;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authorization Code Flow Types
|
|
3
|
+
* Types for the CODE-based authentication flow
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Authorization code data stored in the key-value store
|
|
7
|
+
*/
|
|
8
|
+
export interface AuthCodeData {
|
|
9
|
+
/** Complete OAuth provider user data (NOT the JWT payload) - used for custom claims generation */
|
|
10
|
+
providerUserInfo: Record<string, unknown>;
|
|
11
|
+
/** Provider tokens received from OAuth provider */
|
|
12
|
+
providerTokens: {
|
|
13
|
+
/** OAuth provider access token */
|
|
14
|
+
access_token: string;
|
|
15
|
+
/** Optional OAuth provider refresh token */
|
|
16
|
+
refresh_token?: string;
|
|
17
|
+
/** Optional OAuth provider ID token (OpenID Connect) */
|
|
18
|
+
id_token?: string;
|
|
19
|
+
/** Optional token expiration time in seconds */
|
|
20
|
+
expires_in?: number;
|
|
21
|
+
};
|
|
22
|
+
/** Timestamp when the code expires (milliseconds since epoch) */
|
|
23
|
+
expiresAt: number;
|
|
24
|
+
/** Timestamp when the code was created (milliseconds since epoch) */
|
|
25
|
+
createdAt: number;
|
|
26
|
+
/** Provider name (e.g., 'google', 'github', 'microsoft', 'auth0') */
|
|
27
|
+
provider: string;
|
|
28
|
+
/** Resolved custom claims (already processed from static or callback config) */
|
|
29
|
+
customClaims?: Record<string, unknown>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Request body for token exchange endpoint
|
|
33
|
+
* Client sends this to /auth/token to exchange CODE for tokens
|
|
34
|
+
*/
|
|
35
|
+
export interface TokenExchangeRequest {
|
|
36
|
+
/** Authorization code received from OAuth callback */
|
|
37
|
+
code: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Response from token exchange endpoint
|
|
41
|
+
* Server returns access token in JSON response body
|
|
42
|
+
*/
|
|
43
|
+
export interface TokenExchangeResponse {
|
|
44
|
+
/** JWT access token for API authentication */
|
|
45
|
+
accessToken: string;
|
|
46
|
+
/** Token type, always "Bearer" for JWT */
|
|
47
|
+
tokenType: 'Bearer';
|
|
48
|
+
/** Optional expiration time in seconds */
|
|
49
|
+
expiresIn?: number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Configuration for authorization code flow
|
|
53
|
+
*/
|
|
54
|
+
export interface AuthCodeConfig {
|
|
55
|
+
/**
|
|
56
|
+
* Expiration time for authorization codes in seconds
|
|
57
|
+
* @default 60
|
|
58
|
+
*/
|
|
59
|
+
expiresIn: number;
|
|
60
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { H3Error, H3Event } from 'h3';
|
|
2
|
+
/**
|
|
3
|
+
* Callback and error handler type definitions
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Error handler callback type
|
|
7
|
+
*/
|
|
8
|
+
export type OnError = (event: H3Event, error: H3Error) => Promise<void> | void;
|
|
9
|
+
/**
|
|
10
|
+
* User information transformation hook
|
|
11
|
+
* Called after fetching user info from the provider, before storing it
|
|
12
|
+
* Allows provider-specific user object shaping
|
|
13
|
+
*
|
|
14
|
+
* This receives the complete OAuth provider response, NOT the JWT payload
|
|
15
|
+
*
|
|
16
|
+
* @param providerUserInfo - Complete user object from OAuth provider
|
|
17
|
+
* @param tokens - Provider tokens (access_token, refresh_token, id_token, expires_in)
|
|
18
|
+
* @param event - H3 event for server context access
|
|
19
|
+
* @returns Transformed user object that will be stored and used for custom claims
|
|
20
|
+
*/
|
|
21
|
+
export type OnUserInfo = (providerUserInfo: Record<string, unknown>, tokens: {
|
|
22
|
+
access_token: string;
|
|
23
|
+
refresh_token?: string;
|
|
24
|
+
id_token?: string;
|
|
25
|
+
expires_in?: number;
|
|
26
|
+
}, event: H3Event) => Promise<Record<string, unknown>> | Record<string, unknown>;
|
|
27
|
+
/**
|
|
28
|
+
* Success hook parameters
|
|
29
|
+
*/
|
|
30
|
+
export interface OnSuccessParams {
|
|
31
|
+
/** Transformed provider user data (post-onUserInfo transformation) */
|
|
32
|
+
providerUserInfo: Record<string, unknown>;
|
|
33
|
+
/** Provider tokens */
|
|
34
|
+
tokens: {
|
|
35
|
+
access_token: string;
|
|
36
|
+
refresh_token?: string;
|
|
37
|
+
id_token?: string;
|
|
38
|
+
expires_in?: number;
|
|
39
|
+
};
|
|
40
|
+
/** Provider name (e.g., 'google', 'github', 'microsoft', 'auth0') */
|
|
41
|
+
provider: string;
|
|
42
|
+
/** H3 event for server context access */
|
|
43
|
+
event: H3Event;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Success hook type
|
|
47
|
+
* Called after successful authentication, before generating authorization CODE
|
|
48
|
+
* Provider-agnostic hook for side effects like database storage
|
|
49
|
+
*
|
|
50
|
+
* This receives the transformed OAuth provider data, NOT the JWT payload
|
|
51
|
+
*
|
|
52
|
+
* @param params - Success hook parameters
|
|
53
|
+
*/
|
|
54
|
+
export type OnSuccess = (params: OnSuccessParams) => Promise<void> | void;
|
|
File without changes
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { GoogleProviderConfig, MicrosoftProviderConfig, GithubProviderConfig, Auth0ProviderConfig, MockProviderConfig, CustomProviderConfig, PasswordProviderConfig } from './providers.js';
|
|
2
|
+
import type { TokenConfig, ClaimsValidationConfig } from './token.js';
|
|
3
|
+
import type { TokenRefreshConfig } from './refresh.js';
|
|
4
|
+
import type { ClientMiddlewareConfig } from './routes.js';
|
|
5
|
+
import type { AuthCodeConfig } from './authCode.js';
|
|
6
|
+
/**
|
|
7
|
+
* Module and runtime configuration types
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Redirect URL configuration
|
|
11
|
+
*/
|
|
12
|
+
export interface RedirectConfig {
|
|
13
|
+
/** Redirect URL after logout (default: '/') */
|
|
14
|
+
logout?: string;
|
|
15
|
+
/** Redirect URL after successful authentication (default: '/') */
|
|
16
|
+
success?: string;
|
|
17
|
+
/** Redirect URL when authentication fails (default: '/') */
|
|
18
|
+
error?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* API endpoint path configuration
|
|
22
|
+
*/
|
|
23
|
+
export interface EndpointConfig {
|
|
24
|
+
/** Base path for authentication API routes (default: '/auth') */
|
|
25
|
+
authPath?: string;
|
|
26
|
+
/** Base path for login endpoints without provider (default: '/auth'). Login URLs are constructed as '[loginPath]/[provider]' */
|
|
27
|
+
loginPath?: string;
|
|
28
|
+
/** Path for callback endpoints (default: '/auth/callback') */
|
|
29
|
+
callbackPath?: string;
|
|
30
|
+
/** Path for logout endpoint (default: '/auth/logout') */
|
|
31
|
+
logoutPath?: string;
|
|
32
|
+
/** Path for token refresh endpoint (default: '/auth/refresh') */
|
|
33
|
+
refreshPath?: string;
|
|
34
|
+
/** Path for user info endpoint (default: '/api/user/me') */
|
|
35
|
+
userInfoPath?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Logging configuration
|
|
39
|
+
*/
|
|
40
|
+
export interface LoggingConfig {
|
|
41
|
+
/** Log level: 'silent' | 'error' | 'warn' | 'info' | 'debug' (default: 'info') */
|
|
42
|
+
level?: 'silent' | 'error' | 'warn' | 'info' | 'debug';
|
|
43
|
+
/** Enable security event logging (default: false, enabled when level is 'debug') */
|
|
44
|
+
security?: boolean;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Impersonation configuration
|
|
48
|
+
*/
|
|
49
|
+
export interface ImpersonationConfig {
|
|
50
|
+
/** Enable user impersonation feature (default: false, opt-in for security) */
|
|
51
|
+
enabled?: boolean;
|
|
52
|
+
/** Token expiration time for impersonated sessions in seconds (default: 900 = 15 minutes) */
|
|
53
|
+
tokenExpiration?: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Runtime config for Nuxt Aegis
|
|
57
|
+
*/
|
|
58
|
+
export interface NuxtAegisRuntimeConfig {
|
|
59
|
+
token?: TokenConfig;
|
|
60
|
+
tokenRefresh?: TokenRefreshConfig;
|
|
61
|
+
authCode?: AuthCodeConfig;
|
|
62
|
+
endpoints?: EndpointConfig;
|
|
63
|
+
authPath?: string;
|
|
64
|
+
logging?: LoggingConfig;
|
|
65
|
+
impersonation?: ImpersonationConfig;
|
|
66
|
+
providers?: {
|
|
67
|
+
google?: GoogleProviderConfig;
|
|
68
|
+
microsoft?: MicrosoftProviderConfig;
|
|
69
|
+
github?: GithubProviderConfig;
|
|
70
|
+
auth0?: Auth0ProviderConfig;
|
|
71
|
+
mock?: MockProviderConfig;
|
|
72
|
+
password?: PasswordProviderConfig;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Nuxt Aegis module configuration options
|
|
77
|
+
*/
|
|
78
|
+
export interface ModuleOptions {
|
|
79
|
+
/** Enable Nuxt DevTools integration (default: true) */
|
|
80
|
+
devtools?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* OAuth provider configurations
|
|
83
|
+
* Configure one or more authentication providers
|
|
84
|
+
*/
|
|
85
|
+
providers?: {
|
|
86
|
+
/** Google OAuth provider configuration */
|
|
87
|
+
google?: GoogleProviderConfig;
|
|
88
|
+
/** Microsoft OAuth provider configuration */
|
|
89
|
+
microsoft?: MicrosoftProviderConfig;
|
|
90
|
+
/** GitHub OAuth provider configuration */
|
|
91
|
+
github?: GithubProviderConfig;
|
|
92
|
+
/** Auth0 OAuth provider configuration */
|
|
93
|
+
auth0?: Auth0ProviderConfig;
|
|
94
|
+
/** Mock OAuth provider configuration (development/testing only) */
|
|
95
|
+
mock?: MockProviderConfig;
|
|
96
|
+
/** Password provider configuration */
|
|
97
|
+
password?: PasswordProviderConfig;
|
|
98
|
+
/** Custom OAuth provider configurations */
|
|
99
|
+
custom?: CustomProviderConfig[];
|
|
100
|
+
};
|
|
101
|
+
/** Token configuration */
|
|
102
|
+
token?: TokenConfig;
|
|
103
|
+
/** Token refresh configuration */
|
|
104
|
+
tokenRefresh?: TokenRefreshConfig;
|
|
105
|
+
/**
|
|
106
|
+
* Authorization code configuration (CODE-based flow)
|
|
107
|
+
* Default: 60 seconds (recommended for security)
|
|
108
|
+
*/
|
|
109
|
+
authCode?: AuthCodeConfig;
|
|
110
|
+
/** Redirect URL configuration */
|
|
111
|
+
redirect?: RedirectConfig;
|
|
112
|
+
/** Client-side middleware configuration for route protection */
|
|
113
|
+
clientMiddleware?: ClientMiddlewareConfig;
|
|
114
|
+
/** Claims validation configuration */
|
|
115
|
+
claimsValidation?: ClaimsValidationConfig;
|
|
116
|
+
/** API endpoint path configuration */
|
|
117
|
+
endpoints?: EndpointConfig;
|
|
118
|
+
/** Logging configuration */
|
|
119
|
+
logging?: LoggingConfig;
|
|
120
|
+
/** Impersonation configuration (opt-in feature) */
|
|
121
|
+
impersonation?: ImpersonationConfig;
|
|
122
|
+
/**
|
|
123
|
+
* Enable SSR-compatible authentication state restoration
|
|
124
|
+
* When true (default), authentication state will be restored on client after SSR hydration
|
|
125
|
+
* When false, plugin skips execution after server-side rendering (backward compatibility)
|
|
126
|
+
* @default true
|
|
127
|
+
*/
|
|
128
|
+
enableSSR?: boolean;
|
|
129
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { H3Event } from 'h3';
|
|
2
|
+
import type { TokenPayload } from './token.js';
|
|
3
|
+
/**
|
|
4
|
+
* Nitro hook type definitions for Nuxt Aegis
|
|
5
|
+
* These hooks allow users to customize authentication behavior via server plugins
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Payload for the nuxt-aegis:userInfo hook
|
|
9
|
+
* Called after fetching user info from the provider, before storing it
|
|
10
|
+
*
|
|
11
|
+
* This receives the complete OAuth provider response, NOT the JWT payload
|
|
12
|
+
*/
|
|
13
|
+
export interface UserInfoHookPayload {
|
|
14
|
+
/** Complete user object from OAuth provider (e.g., Google, GitHub, Microsoft) */
|
|
15
|
+
providerUserInfo: Record<string, unknown>;
|
|
16
|
+
/** Provider tokens */
|
|
17
|
+
tokens: {
|
|
18
|
+
access_token: string;
|
|
19
|
+
refresh_token?: string;
|
|
20
|
+
id_token?: string;
|
|
21
|
+
expires_in?: number;
|
|
22
|
+
};
|
|
23
|
+
/** Provider name (e.g., 'google', 'github', 'microsoft', 'auth0') */
|
|
24
|
+
provider: string;
|
|
25
|
+
/** H3 event for server context access */
|
|
26
|
+
event: H3Event;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Payload for the nuxt-aegis:success hook
|
|
30
|
+
* Called after successful authentication
|
|
31
|
+
*
|
|
32
|
+
* This receives the transformed OAuth provider data, NOT the JWT payload
|
|
33
|
+
*/
|
|
34
|
+
export interface SuccessHookPayload {
|
|
35
|
+
/** Transformed provider user data (post-userInfo hook transformation) */
|
|
36
|
+
providerUserInfo: Record<string, unknown>;
|
|
37
|
+
/** Provider tokens */
|
|
38
|
+
tokens: {
|
|
39
|
+
access_token: string;
|
|
40
|
+
refresh_token?: string;
|
|
41
|
+
id_token?: string;
|
|
42
|
+
expires_in?: number;
|
|
43
|
+
};
|
|
44
|
+
/** Provider name (e.g., 'google', 'github', 'microsoft', 'auth0') */
|
|
45
|
+
provider: string;
|
|
46
|
+
/** H3 event for server context access */
|
|
47
|
+
event: H3Event;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Payload for the nuxt-aegis:impersonate:check hook
|
|
51
|
+
* Called to determine if a user is allowed to impersonate others
|
|
52
|
+
*/
|
|
53
|
+
export interface ImpersonateCheckPayload {
|
|
54
|
+
/** JWT payload of the user requesting impersonation */
|
|
55
|
+
requester: TokenPayload;
|
|
56
|
+
/** Target user ID to impersonate */
|
|
57
|
+
targetUserId: string;
|
|
58
|
+
/** Optional reason for impersonation (for audit) */
|
|
59
|
+
reason?: string;
|
|
60
|
+
/** H3 event for server context access */
|
|
61
|
+
event: H3Event;
|
|
62
|
+
/** Client IP address (for audit) */
|
|
63
|
+
ip: string;
|
|
64
|
+
/** User agent string (for audit) */
|
|
65
|
+
userAgent: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Payload for the nuxt-aegis:impersonate:fetchTarget hook
|
|
69
|
+
* Called to fetch the target user's data
|
|
70
|
+
*
|
|
71
|
+
* This hook MUST be implemented by the user to return the target user's data
|
|
72
|
+
*/
|
|
73
|
+
export interface ImpersonateFetchTargetPayload {
|
|
74
|
+
/** JWT payload of the user requesting impersonation */
|
|
75
|
+
requester: TokenPayload;
|
|
76
|
+
/** Target user ID to impersonate */
|
|
77
|
+
targetUserId: string;
|
|
78
|
+
/** H3 event for server context access */
|
|
79
|
+
event: H3Event;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Payload for the nuxt-aegis:impersonate:start hook
|
|
83
|
+
* Called after impersonation starts successfully (fire-and-forget for audit logging)
|
|
84
|
+
*/
|
|
85
|
+
export interface ImpersonateStartPayload {
|
|
86
|
+
/** JWT payload of the user who initiated impersonation */
|
|
87
|
+
requester: TokenPayload;
|
|
88
|
+
/** JWT payload of the impersonated user */
|
|
89
|
+
targetUser: TokenPayload;
|
|
90
|
+
/** Reason for impersonation */
|
|
91
|
+
reason?: string;
|
|
92
|
+
/** H3 event for server context access */
|
|
93
|
+
event: H3Event;
|
|
94
|
+
/** Client IP address (for audit) */
|
|
95
|
+
ip: string;
|
|
96
|
+
/** User agent string (for audit) */
|
|
97
|
+
userAgent: string;
|
|
98
|
+
/** Timestamp of impersonation */
|
|
99
|
+
timestamp: Date;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Payload for the nuxt-aegis:impersonate:end hook
|
|
103
|
+
* Called after impersonation ends successfully (fire-and-forget for audit logging)
|
|
104
|
+
*/
|
|
105
|
+
export interface ImpersonateEndPayload {
|
|
106
|
+
/** JWT payload of the restored original user */
|
|
107
|
+
restoredUser: TokenPayload;
|
|
108
|
+
/** JWT payload of the user who was being impersonated */
|
|
109
|
+
impersonatedUser: TokenPayload;
|
|
110
|
+
/** H3 event for server context access */
|
|
111
|
+
event: H3Event;
|
|
112
|
+
/** Client IP address (for audit) */
|
|
113
|
+
ip: string;
|
|
114
|
+
/** User agent string (for audit) */
|
|
115
|
+
userAgent: string;
|
|
116
|
+
/** Timestamp when impersonation ended */
|
|
117
|
+
timestamp: Date;
|
|
118
|
+
}
|