@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.
Files changed (119) hide show
  1. package/README.md +482 -6
  2. package/dist/module.d.mts +17 -24
  3. package/dist/module.json +2 -2
  4. package/dist/module.mjs +174 -48
  5. package/dist/runtime/components/AsgardeoRoot.d.ts +52 -0
  6. package/dist/runtime/components/AsgardeoRoot.js +160 -0
  7. package/dist/runtime/components/actions/SignInButton.d.ts +37 -0
  8. package/dist/runtime/components/actions/SignInButton.js +51 -0
  9. package/dist/runtime/components/actions/SignOutButton.d.ts +34 -0
  10. package/dist/runtime/components/actions/SignOutButton.js +43 -0
  11. package/dist/runtime/components/actions/SignUpButton.d.ts +33 -0
  12. package/dist/runtime/components/actions/SignUpButton.js +48 -0
  13. package/dist/runtime/components/auth/Callback.d.ts +43 -0
  14. package/dist/runtime/components/auth/Callback.js +93 -0
  15. package/dist/runtime/components/auth/SignIn.d.ts +38 -0
  16. package/dist/runtime/components/auth/SignIn.js +60 -0
  17. package/dist/runtime/components/auth/SignUp.d.ts +40 -0
  18. package/dist/runtime/components/auth/SignUp.js +79 -0
  19. package/dist/runtime/components/control/Loading.d.ts +36 -0
  20. package/dist/runtime/components/control/Loading.js +17 -0
  21. package/dist/runtime/components/control/SignedIn.d.ts +38 -0
  22. package/dist/runtime/components/control/SignedIn.js +17 -0
  23. package/dist/runtime/components/control/SignedOut.d.ts +37 -0
  24. package/dist/runtime/components/control/SignedOut.js +17 -0
  25. package/dist/runtime/components/organization/CreateOrganization.d.ts +32 -0
  26. package/dist/runtime/components/organization/CreateOrganization.js +29 -0
  27. package/dist/runtime/components/organization/Organization.d.ts +39 -0
  28. package/dist/runtime/components/organization/Organization.js +17 -0
  29. package/dist/runtime/components/organization/OrganizationList.d.ts +34 -0
  30. package/dist/runtime/components/organization/OrganizationList.js +30 -0
  31. package/dist/runtime/components/organization/OrganizationProfile.d.ts +32 -0
  32. package/dist/runtime/components/organization/OrganizationProfile.js +32 -0
  33. package/dist/runtime/components/organization/OrganizationSwitcher.d.ts +36 -0
  34. package/dist/runtime/components/organization/OrganizationSwitcher.js +26 -0
  35. package/dist/runtime/components/user/User.d.ts +38 -0
  36. package/dist/runtime/components/user/User.js +17 -0
  37. package/dist/runtime/components/user/UserDropdown.d.ts +38 -0
  38. package/dist/runtime/components/user/UserDropdown.js +45 -0
  39. package/dist/runtime/components/user/UserProfile.d.ts +35 -0
  40. package/dist/runtime/components/user/UserProfile.js +35 -0
  41. package/dist/runtime/composables/useAsgardeo.d.ts +38 -0
  42. package/dist/runtime/composables/useAsgardeo.js +73 -0
  43. package/dist/runtime/errors/asgardeo-error.d.ts +47 -0
  44. package/dist/runtime/errors/asgardeo-error.js +15 -0
  45. package/dist/runtime/errors/error-codes.d.ts +40 -0
  46. package/dist/runtime/errors/error-codes.js +19 -0
  47. package/dist/runtime/{composables/asgardeo/useAuth.d.ts → errors/index.d.ts} +2 -2
  48. package/dist/runtime/errors/index.js +2 -0
  49. package/dist/runtime/middleware/auth.d.ts +35 -0
  50. package/dist/runtime/middleware/auth.js +2 -0
  51. package/dist/runtime/middleware/defineAsgardeoMiddleware.d.ts +53 -0
  52. package/dist/runtime/middleware/defineAsgardeoMiddleware.js +24 -0
  53. package/dist/runtime/plugins/asgardeo.d.ts +40 -0
  54. package/dist/runtime/plugins/asgardeo.js +129 -0
  55. package/dist/runtime/server/AsgardeoNuxtClient.d.ts +182 -0
  56. package/dist/runtime/server/AsgardeoNuxtClient.js +366 -0
  57. package/dist/runtime/server/index.d.ts +33 -0
  58. package/dist/runtime/server/index.js +3 -0
  59. package/dist/runtime/server/plugins/asgardeo-ssr.d.ts +41 -0
  60. package/dist/runtime/server/plugins/asgardeo-ssr.js +134 -0
  61. package/dist/runtime/server/routes/auth/branding/branding.get.d.ts +31 -0
  62. package/dist/runtime/server/routes/auth/branding/branding.get.js +40 -0
  63. package/dist/runtime/server/routes/auth/organizations/current.get.d.ts +29 -0
  64. package/dist/runtime/server/routes/auth/organizations/current.get.js +24 -0
  65. package/dist/runtime/server/routes/auth/organizations/id.get.d.ts +28 -0
  66. package/dist/runtime/server/routes/auth/organizations/id.get.js +28 -0
  67. package/dist/runtime/server/routes/auth/organizations/index.get.d.ts +28 -0
  68. package/dist/runtime/server/routes/auth/organizations/index.get.js +24 -0
  69. package/dist/runtime/server/routes/auth/organizations/index.post.d.ts +30 -0
  70. package/dist/runtime/server/routes/auth/organizations/index.post.js +30 -0
  71. package/dist/runtime/server/routes/auth/organizations/me.get.d.ts +28 -0
  72. package/dist/runtime/server/routes/auth/organizations/me.get.js +24 -0
  73. package/dist/runtime/server/routes/auth/organizations/switch.post.d.ts +32 -0
  74. package/dist/runtime/server/routes/auth/organizations/switch.post.js +49 -0
  75. package/dist/runtime/server/routes/auth/session/callback.get.d.ts +27 -0
  76. package/dist/runtime/server/routes/auth/session/callback.get.js +91 -0
  77. package/dist/runtime/server/routes/auth/session/callback.post.d.ts +48 -0
  78. package/dist/runtime/server/routes/auth/session/callback.post.js +53 -0
  79. package/dist/runtime/server/routes/auth/session/session.get.d.ts +26 -0
  80. package/dist/runtime/server/routes/auth/session/session.get.js +22 -0
  81. package/dist/runtime/server/routes/auth/session/signin.get.d.ts +29 -0
  82. package/dist/runtime/server/routes/auth/session/signin.get.js +37 -0
  83. package/dist/runtime/server/routes/auth/session/signin.post.d.ts +37 -0
  84. package/dist/runtime/server/routes/auth/session/signin.post.js +102 -0
  85. package/dist/runtime/server/routes/auth/session/signout.post.d.ts +31 -0
  86. package/dist/runtime/server/routes/auth/session/signout.post.js +38 -0
  87. package/dist/runtime/server/routes/auth/session/signup.post.d.ts +36 -0
  88. package/dist/runtime/server/routes/auth/session/signup.post.js +30 -0
  89. package/dist/runtime/server/routes/auth/session/token.get.d.ts +29 -0
  90. package/dist/runtime/server/routes/auth/session/token.get.js +6 -0
  91. package/dist/runtime/server/routes/auth/user/profile.get.d.ts +29 -0
  92. package/dist/runtime/server/routes/auth/user/profile.get.js +24 -0
  93. package/dist/runtime/server/{handler.d.ts → routes/auth/user/profile.patch.d.ts} +17 -13
  94. package/dist/runtime/server/routes/auth/user/profile.patch.js +33 -0
  95. package/dist/runtime/server/{services/asgardeo/index.d.ts → routes/auth/user/user.get.d.ts} +6 -4
  96. package/dist/runtime/server/routes/auth/user/user.get.js +21 -0
  97. package/dist/runtime/server/utils/event-context.d.ts +49 -0
  98. package/dist/runtime/server/utils/event-context.js +3 -0
  99. package/dist/runtime/server/utils/serverSession.d.ts +65 -0
  100. package/dist/runtime/server/utils/serverSession.js +44 -0
  101. package/dist/runtime/server/utils/session.d.ts +85 -0
  102. package/dist/runtime/server/utils/session.js +106 -0
  103. package/dist/runtime/server/utils/token-refresh.d.ts +42 -0
  104. package/dist/runtime/server/utils/token-refresh.js +65 -0
  105. package/dist/runtime/types/augments.d.ts +61 -0
  106. package/dist/runtime/types.d.ts +115 -38
  107. package/dist/runtime/utils/createRouteMatcher.d.ts +40 -0
  108. package/dist/runtime/utils/createRouteMatcher.js +7 -0
  109. package/dist/runtime/utils/index.d.ts +30 -0
  110. package/dist/runtime/utils/index.js +1 -0
  111. package/dist/runtime/utils/log.d.ts +44 -0
  112. package/dist/runtime/utils/log.js +25 -0
  113. package/dist/runtime/utils/url-validation.d.ts +49 -0
  114. package/dist/runtime/utils/url-validation.js +38 -0
  115. package/dist/types.d.mts +0 -2
  116. package/package.json +48 -23
  117. package/dist/runtime/composables/asgardeo/useAuth.js +0 -129
  118. package/dist/runtime/server/handler.js +0 -231
  119. package/dist/runtime/server/services/asgardeo/index.js +0 -18
@@ -0,0 +1,44 @@
1
+ import { getCookie, createError } from "h3";
2
+ import { verifySessionToken, getSessionCookieName } from "./session.js";
3
+ import AsgardeoNuxtClient from "../AsgardeoNuxtClient.js";
4
+ import { useRuntimeConfig } from "#imports";
5
+ export async function useServerSession(event) {
6
+ const config = useRuntimeConfig();
7
+ const sessionSecret = config.asgardeo?.sessionSecret;
8
+ const sessionCookie = getCookie(event, getSessionCookieName());
9
+ if (!sessionCookie) {
10
+ return null;
11
+ }
12
+ try {
13
+ return await verifySessionToken(sessionCookie, sessionSecret);
14
+ } catch {
15
+ return null;
16
+ }
17
+ }
18
+ export async function requireServerSession(event) {
19
+ const session = await useServerSession(event);
20
+ if (!session) {
21
+ throw createError({
22
+ statusCode: 401,
23
+ statusMessage: "Unauthorized: Authentication required."
24
+ });
25
+ }
26
+ return session;
27
+ }
28
+ export async function verifyAndRehydrateSession(event, sessionSecret) {
29
+ const sessionCookie = getCookie(event, getSessionCookieName());
30
+ if (!sessionCookie) {
31
+ return null;
32
+ }
33
+ let session;
34
+ try {
35
+ session = await verifySessionToken(sessionCookie, sessionSecret);
36
+ } catch {
37
+ return null;
38
+ }
39
+ try {
40
+ await AsgardeoNuxtClient.getInstance().rehydrateSessionFromPayload(session);
41
+ } catch {
42
+ }
43
+ return session;
44
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3
+ *
4
+ * WSO2 LLC. licenses this file to you under the Apache License,
5
+ * Version 2.0 (the "License"); you may not use this file except
6
+ * in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing,
12
+ * software distributed under the License is distributed on an
13
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ * KIND, either express or implied. See the License for the
15
+ * specific language governing permissions and limitations
16
+ * under the License.
17
+ */
18
+ import type { TokenResponse } from '@asgardeo/node';
19
+ import type { H3Event } from 'h3';
20
+ import type { AsgardeoSessionPayload } from '../../types.js';
21
+ /**
22
+ * Create a signed JWT session token.
23
+ */
24
+ export declare function createSessionToken(params: {
25
+ accessToken: string;
26
+ /** Unix timestamp (seconds) when the access token expires. */
27
+ accessTokenExpiresAt?: number;
28
+ expirySeconds?: number;
29
+ /** Raw ID token string. */
30
+ idToken?: string;
31
+ organizationId?: string;
32
+ /** Refresh token for silent re-auth. */
33
+ refreshToken?: string;
34
+ scopes: string;
35
+ sessionId: string;
36
+ userId: string;
37
+ }, sessionSecret?: string): Promise<string>;
38
+ /**
39
+ * Create a signed JWT temp session token (used during OAuth flow).
40
+ */
41
+ export declare function createTempSessionToken(sessionId: string, sessionSecret?: string, returnTo?: string): Promise<string>;
42
+ /**
43
+ * Verify and decode a session JWT.
44
+ */
45
+ export declare function verifySessionToken(token: string, sessionSecret?: string): Promise<AsgardeoSessionPayload>;
46
+ /**
47
+ * Verify and decode a temp session JWT.
48
+ */
49
+ export declare function verifyTempSessionToken(token: string, sessionSecret?: string): Promise<{
50
+ returnTo?: string;
51
+ sessionId: string;
52
+ }>;
53
+ /**
54
+ * Session cookie name.
55
+ */
56
+ export declare function getSessionCookieName(): string;
57
+ /**
58
+ * Temp session cookie name.
59
+ */
60
+ export declare function getTempSessionCookieName(): string;
61
+ /**
62
+ * Session cookie options.
63
+ */
64
+ type SessionCookieOptions = {
65
+ httpOnly: boolean;
66
+ maxAge: number;
67
+ path: string;
68
+ sameSite: 'lax';
69
+ secure: boolean;
70
+ };
71
+ export declare function getSessionCookieOptions(): SessionCookieOptions;
72
+ /**
73
+ * Temp session cookie options (15 min TTL).
74
+ */
75
+ export declare function getTempSessionCookieOptions(): SessionCookieOptions;
76
+ /**
77
+ * Decode a token response into a signed session JWT and write it as the
78
+ * session cookie on the H3 event.
79
+ *
80
+ * Extracted from the inline blocks in `callback.get.ts` and
81
+ * `organizations/switch.post.ts` so that all three callers (callback.get,
82
+ * switch.post, and the new `signin.post`) share one implementation.
83
+ */
84
+ export declare function issueSessionCookie(event: H3Event, sessionId: string, tokenResponse: TokenResponse, sessionSecret?: string): Promise<void>;
85
+ export {};
@@ -0,0 +1,106 @@
1
+ import { CookieConfig } from "@asgardeo/node";
2
+ import { setCookie } from "h3";
3
+ import { SignJWT, jwtVerify } from "jose";
4
+ const DEFAULT_EXPIRY_SECONDS = 3600;
5
+ function getSecret(sessionSecret) {
6
+ const secret = sessionSecret || process.env["ASGARDEO_SESSION_SECRET"];
7
+ if (!secret) {
8
+ if (process.env["NODE_ENV"] === "production") {
9
+ throw new Error(
10
+ "[asgardeo] ASGARDEO_SESSION_SECRET environment variable is required in production. Set it to a secure random string of at least 32 characters."
11
+ );
12
+ }
13
+ console.warn(
14
+ "[asgardeo] Using default session secret for development. Set ASGARDEO_SESSION_SECRET for production."
15
+ );
16
+ return new TextEncoder().encode("asgardeo-dev-secret-not-for-production");
17
+ }
18
+ return new TextEncoder().encode(secret);
19
+ }
20
+ export async function createSessionToken(params, sessionSecret) {
21
+ const secret = getSecret(sessionSecret);
22
+ return new SignJWT({
23
+ accessToken: params.accessToken,
24
+ accessTokenExpiresAt: params.accessTokenExpiresAt,
25
+ idToken: params.idToken,
26
+ organizationId: params.organizationId,
27
+ refreshToken: params.refreshToken,
28
+ scopes: params.scopes,
29
+ sessionId: params.sessionId,
30
+ type: "session"
31
+ }).setProtectedHeader({ alg: "HS256" }).setSubject(params.userId).setIssuedAt().setExpirationTime(Date.now() / 1e3 + (params.expirySeconds ?? DEFAULT_EXPIRY_SECONDS)).sign(secret);
32
+ }
33
+ export async function createTempSessionToken(sessionId, sessionSecret, returnTo) {
34
+ const secret = getSecret(sessionSecret);
35
+ const payload = {
36
+ sessionId,
37
+ type: "temp"
38
+ };
39
+ if (returnTo) {
40
+ payload["returnTo"] = returnTo;
41
+ }
42
+ return new SignJWT(payload).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setExpirationTime("15m").sign(secret);
43
+ }
44
+ export async function verifySessionToken(token, sessionSecret) {
45
+ const secret = getSecret(sessionSecret);
46
+ const { payload } = await jwtVerify(token, secret);
47
+ return payload;
48
+ }
49
+ export async function verifyTempSessionToken(token, sessionSecret) {
50
+ const secret = getSecret(sessionSecret);
51
+ const { payload } = await jwtVerify(token, secret);
52
+ if (payload["type"] !== "temp") {
53
+ throw new Error("Invalid token type: expected temp session");
54
+ }
55
+ return {
56
+ returnTo: payload["returnTo"],
57
+ sessionId: payload["sessionId"]
58
+ };
59
+ }
60
+ export function getSessionCookieName() {
61
+ return CookieConfig.SESSION_COOKIE_NAME;
62
+ }
63
+ export function getTempSessionCookieName() {
64
+ return CookieConfig.TEMP_SESSION_COOKIE_NAME;
65
+ }
66
+ export function getSessionCookieOptions() {
67
+ return {
68
+ httpOnly: true,
69
+ maxAge: DEFAULT_EXPIRY_SECONDS,
70
+ path: "/",
71
+ sameSite: "lax",
72
+ secure: process.env["NODE_ENV"] === "production"
73
+ };
74
+ }
75
+ export function getTempSessionCookieOptions() {
76
+ return {
77
+ httpOnly: true,
78
+ maxAge: 15 * 60,
79
+ path: "/",
80
+ sameSite: "lax",
81
+ secure: process.env["NODE_ENV"] === "production"
82
+ };
83
+ }
84
+ export async function issueSessionCookie(event, sessionId, tokenResponse, sessionSecret) {
85
+ const { default: AsgardeoNuxtClient } = await import("../AsgardeoNuxtClient.js");
86
+ const client = AsgardeoNuxtClient.getInstance();
87
+ const idToken = await client.getDecodedIdToken(sessionId, tokenResponse.idToken);
88
+ const userId = idToken.sub || sessionId;
89
+ const organizationId = idToken["user_org"] || idToken["organization_id"];
90
+ const expiresInSeconds = parseInt(tokenResponse.expiresIn ?? "3600", 10);
91
+ const accessTokenExpiresAt = Math.floor(Date.now() / 1e3) + (Number.isFinite(expiresInSeconds) ? expiresInSeconds : 3600);
92
+ const sessionToken = await createSessionToken(
93
+ {
94
+ accessToken: tokenResponse.accessToken,
95
+ accessTokenExpiresAt,
96
+ idToken: tokenResponse.idToken || void 0,
97
+ organizationId,
98
+ refreshToken: tokenResponse.refreshToken || void 0,
99
+ scopes: tokenResponse.scope || "",
100
+ sessionId,
101
+ userId
102
+ },
103
+ sessionSecret
104
+ );
105
+ setCookie(event, getSessionCookieName(), sessionToken, getSessionCookieOptions());
106
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3
+ *
4
+ * WSO2 LLC. licenses this file to you under the Apache License,
5
+ * Version 2.0 (the "License"); you may not use this file except
6
+ * in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing,
12
+ * software distributed under the License is distributed on an
13
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ * KIND, either express or implied. See the License for the
15
+ * specific language governing permissions and limitations
16
+ * under the License.
17
+ */
18
+ import { type H3Event } from 'h3';
19
+ /**
20
+ * Return a valid access token for the current request.
21
+ *
22
+ * If the stored access token is still fresh (or has no expiry metadata —
23
+ * e.g. sessions created before Phase 2), it is returned as-is.
24
+ *
25
+ * When the token is within `REFRESH_SKEW_SECONDS` of expiring and a
26
+ * refresh token is present, a `refresh_token` grant is sent to the OIDC
27
+ * token endpoint. On success the session cookie is reissued with the new
28
+ * tokens so subsequent calls within the same browser session are also fresh.
29
+ *
30
+ * Throws a 401 if the token is expired and no refresh token is available, or
31
+ * if the refresh call itself fails.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * // In a Nitro API route:
36
+ * export default defineEventHandler(async (event) => {
37
+ * const accessToken = await getValidAccessToken(event);
38
+ * // use accessToken to call a protected API
39
+ * });
40
+ * ```
41
+ */
42
+ export declare function getValidAccessToken(event: H3Event): Promise<string>;
@@ -0,0 +1,65 @@
1
+ import { createError, setCookie } from "h3";
2
+ import { requireServerSession } from "./serverSession.js";
3
+ import { createSessionToken, getSessionCookieName, getSessionCookieOptions } from "./session.js";
4
+ import { useRuntimeConfig } from "#imports";
5
+ const REFRESH_SKEW_SECONDS = 60;
6
+ export async function getValidAccessToken(event) {
7
+ const session = await requireServerSession(event);
8
+ const now = Math.floor(Date.now() / 1e3);
9
+ if (!session.accessTokenExpiresAt || session.accessTokenExpiresAt - REFRESH_SKEW_SECONDS > now) {
10
+ return session.accessToken;
11
+ }
12
+ if (!session.refreshToken) {
13
+ throw createError({
14
+ statusCode: 401,
15
+ statusMessage: "Session expired. Please sign in again."
16
+ });
17
+ }
18
+ const config = useRuntimeConfig(event);
19
+ const publicConfig = config.public.asgardeo;
20
+ const privateConfig = config.asgardeo;
21
+ const tokenEndpoint = `${publicConfig.baseUrl}/oauth2/token`;
22
+ const body = new URLSearchParams({
23
+ client_id: publicConfig.clientId,
24
+ grant_type: "refresh_token",
25
+ refresh_token: session.refreshToken
26
+ });
27
+ if (privateConfig?.clientSecret) {
28
+ body.set("client_secret", privateConfig.clientSecret);
29
+ }
30
+ let refreshed;
31
+ try {
32
+ const res = await fetch(tokenEndpoint, {
33
+ body,
34
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
35
+ method: "POST"
36
+ });
37
+ if (!res.ok) {
38
+ const errText = await res.text().catch(() => String(res.status));
39
+ throw new Error(`Token endpoint returned ${res.status}: ${errText}`);
40
+ }
41
+ refreshed = await res.json();
42
+ } catch (err) {
43
+ const msg = err instanceof Error ? err.message : String(err);
44
+ console.error("[asgardeo] Token refresh failed:", msg);
45
+ throw createError({
46
+ statusCode: 401,
47
+ statusMessage: "Token refresh failed. Please sign in again."
48
+ });
49
+ }
50
+ const newSessionToken = await createSessionToken(
51
+ {
52
+ accessToken: refreshed.access_token,
53
+ accessTokenExpiresAt: now + (refreshed.expires_in ?? 3600),
54
+ idToken: refreshed.id_token ?? session.idToken,
55
+ organizationId: session.organizationId,
56
+ refreshToken: refreshed.refresh_token ?? session.refreshToken,
57
+ scopes: refreshed.scope ?? session.scopes,
58
+ sessionId: session.sessionId,
59
+ userId: session.sub
60
+ },
61
+ privateConfig?.sessionSecret
62
+ );
63
+ setCookie(event, getSessionCookieName(), newSessionToken, getSessionCookieOptions());
64
+ return refreshed.access_token;
65
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3
+ *
4
+ * WSO2 LLC. licenses this file to you under the Apache License,
5
+ * Version 2.0 (the "License"); you may not use this file except
6
+ * in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing,
12
+ * software distributed under the License is distributed on an
13
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ * KIND, either express or implied. See the License for the
15
+ * specific language governing permissions and limitations
16
+ * under the License.
17
+ */
18
+
19
+ import type {AsgardeoSessionPayload, AsgardeoSSRData} from './types';
20
+
21
+ /**
22
+ * Nuxt schema augmentation — adds `asgardeo` to NuxtConfig / NuxtOptions
23
+ * and ensures the runtime config shapes are fully typed.
24
+ */
25
+ declare module '@nuxt/schema' {
26
+ interface NuxtConfig {
27
+ asgardeo?: import('./types').AsgardeoNuxtConfig;
28
+ }
29
+ interface NuxtOptions {
30
+ asgardeo?: import('./types').AsgardeoNuxtConfig;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * H3 event context augmentation — provides a typed `event.context.asgardeo`
36
+ * property so server plugins and API routes no longer need `as any` casts.
37
+ *
38
+ * Set by the Nitro `asgardeo-ssr` plugin on every page request.
39
+ */
40
+ declare module 'h3' {
41
+ interface H3EventContext {
42
+ /**
43
+ * Resolved auth state for the current request.
44
+ * Populated by the Nitro `asgardeo-ssr` plugin during SSR page requests.
45
+ * `null` when the request is an API route or when the session is absent/invalid.
46
+ */
47
+ asgardeo?: {
48
+ isSignedIn: boolean;
49
+ session: AsgardeoSessionPayload | null;
50
+ /**
51
+ * Rich SSR payload populated by the Nitro `asgardeo-ssr` plugin.
52
+ * Contains the user, userProfile, organisations, and branding data
53
+ * resolved on the server and seeded into `useState` keys for
54
+ * zero-cost client hydration.
55
+ */
56
+ ssr?: AsgardeoSSRData;
57
+ };
58
+ }
59
+ }
60
+
61
+ export {};
@@ -15,53 +15,130 @@
15
15
  * specific language governing permissions and limitations
16
16
  * under the License.
17
17
  */
18
- import type { BasicUserInfo, DataLayer, IdTokenPayload, OIDCEndpoints } from '@asgardeo/auth-node';
19
- export interface ModuleOptions {
18
+ import type { BrandingPreference, I18nPreferences, Organization, User, UserProfile } from '@asgardeo/node';
19
+ import type { JWTPayload } from 'jose';
20
+ /**
21
+ * Configuration for the Asgardeo Nuxt module.
22
+ */
23
+ export interface AsgardeoNuxtConfig {
24
+ /** URL to redirect to after sign-in (default: '/') */
25
+ afterSignInUrl?: string;
26
+ /** URL to redirect to after sign-out (default: '/') */
27
+ afterSignOutUrl?: string;
20
28
  /**
21
- * The base URL of your Asgardeo organization tenant.
22
- * e.g., https://api.asgardeo.io/t/your_org_name
23
- * @default process.env.ASGARDEO_BASE_URL
29
+ * Asgardeo application id (`spId`) appended to the redirect-based sign-up
30
+ * URL when present. Mirrors `applicationId` in the React/Next.js SDKs.
24
31
  */
25
- baseUrl: string;
32
+ applicationId?: string;
33
+ /** Base URL of the Asgardeo org tenant (e.g. https://api.asgardeo.io/t/your_org) */
34
+ baseUrl?: string;
35
+ /** OAuth2 Client ID */
36
+ clientId?: string;
37
+ /** OAuth2 Client Secret (server-only, use ASGARDEO_CLIENT_SECRET env var) */
38
+ clientSecret?: string;
26
39
  /**
27
- * Asgardeo Application Client ID.
28
- * @default process.env.ASGARDEO_CLIENT_ID
40
+ * Feature-gating preferences that control which server-side data fetches
41
+ * the Nitro plugin performs on every SSR request.
29
42
  */
30
- clientID: string;
43
+ preferences?: {
44
+ /** i18n configuration forwarded to `I18nProvider`. */
45
+ i18n?: I18nPreferences;
46
+ theme?: {
47
+ /**
48
+ * When true (default), the Nitro plugin fetches the branding preference
49
+ * from Asgardeo and passes it to `BrandingProvider` / `ThemeProvider`.
50
+ */
51
+ inheritFromBranding?: boolean;
52
+ /**
53
+ * Theme mode forwarded to the Vue SDK's `ThemeProvider`.
54
+ * - `'light'` (default) | `'dark'`: Fixed color scheme. Toggle at runtime with `useTheme().toggleTheme()`.
55
+ * - `'system'`: Follows the OS `prefers-color-scheme`.
56
+ * - `'class'`: Reads a CSS class on `<html>` (works well with Tailwind dark-mode).
57
+ * - `'branding'`: Follows the active theme from the tenant's branding preference.
58
+ */
59
+ mode?: 'light' | 'dark' | 'system' | 'class' | 'branding';
60
+ };
61
+ user?: {
62
+ /** Whether to fetch the user's organisations during SSR (default: true). */
63
+ fetchOrganizations?: boolean;
64
+ /** Whether to fetch the SCIM2 user profile during SSR (default: true). */
65
+ fetchUserProfile?: boolean;
66
+ };
67
+ };
68
+ /** OAuth2 scopes to request */
69
+ scopes?: string[];
70
+ /** Secret for signing session JWTs (use ASGARDEO_SESSION_SECRET env var) */
71
+ sessionSecret?: string;
31
72
  /**
32
- * Asgardeo Application Client Secret. (Server-side only)
33
- * @default process.env.ASGARDEO_CLIENT_SECRET
73
+ * Optional override for the redirect-based sign-in URL. Reserved for
74
+ * parity with the React/Next.js SDKs; not currently used by the redirect
75
+ * flow (which goes through `/api/auth/signin`).
34
76
  */
35
- clientSecret?: string;
77
+ signInUrl?: string;
36
78
  /**
37
- * Authentication scopes to request from Asgardeo.
38
- * @default ['openid', 'profile']
79
+ * Optional override for the redirect-based sign-up URL. When set,
80
+ * `<AsgardeoSignUpButton>` and `useAsgardeo().signUp()` (no-arg) navigate
81
+ * here instead of deriving the URL from `baseUrl`/`clientId`.
39
82
  */
40
- scope?: string[];
41
- /**
42
- * The absolute redirect URI where Asgardeo should redirect after sign-in.
43
- * Must match the URI configured in your Asgardeo app.
44
- * @default process.env.ASGARDEO_SIGN_IN_REDIRECT_URL
45
- */
46
- signInRedirectURL: string;
83
+ signUpUrl?: string;
84
+ }
85
+ /**
86
+ * Payload stored in the session JWT cookie.
87
+ */
88
+ export interface AsgardeoSessionPayload extends JWTPayload {
89
+ accessToken: string;
90
+ /** Unix timestamp (seconds) when the access token expires. Used for proactive refresh. */
91
+ accessTokenExpiresAt?: number;
92
+ exp: number;
93
+ iat: number;
94
+ /** Raw ID token string (for userinfo derivation without in-memory store). */
95
+ idToken?: string;
96
+ organizationId?: string;
97
+ /** Refresh token for obtaining new access tokens without re-authentication. */
98
+ refreshToken?: string;
99
+ scopes: string;
100
+ sessionId: string;
101
+ sub: string;
102
+ }
103
+ /**
104
+ * Payload stored in the temporary session JWT cookie (during OAuth flow).
105
+ */
106
+ export interface AsgardeoTempSessionPayload extends JWTPayload {
107
+ /** URL to redirect to after successful sign-in */
108
+ returnTo?: string;
109
+ sessionId: string;
110
+ type: 'temp';
111
+ }
112
+ /**
113
+ * Full SSR payload resolved by the Nitro plugin on each page request.
114
+ * Written to `event.context.asgardeo.ssr` and subsequently seeded into
115
+ * hydrated `useState` keys so the client never re-fetches on first render.
116
+ */
117
+ export interface AsgardeoSSRData {
118
+ /** Branding preference fetched from Asgardeo (null when `preferences.theme.inheritFromBranding` is false). */
119
+ brandingPreference: BrandingPreference | null;
120
+ /** The organisation the user is currently acting within (null when not in an org). */
121
+ currentOrganization: Organization | null;
122
+ isSignedIn: boolean;
123
+ /** All organisations the user is a member of (empty array when `preferences.user.fetchOrganizations` is false). */
124
+ myOrganizations: Organization[];
47
125
  /**
48
- * The absolute URI to redirect to after sign-out completes.
49
- * @default process.env.ASGARDEO_SIGN_OUT_REDIRECT_URL
126
+ * The base URL actually used for this request.
127
+ * Equals `${baseUrl}/o` when the user is acting within an organisation
128
+ * (derived from the `user_org` claim in the ID token), otherwise equals
129
+ * the configured `baseUrl`.
50
130
  */
51
- signOutRedirectURL: string;
131
+ resolvedBaseUrl: string | null;
132
+ session: AsgardeoSessionPayload | null;
133
+ user: User | null;
134
+ /** Flattened SCIM2 profile + raw profile + schemas (null when `preferences.user.fetchUserProfile` is false). */
135
+ userProfile: UserProfile | null;
52
136
  }
53
- export interface AuthInterface {
54
- getAccessToken: () => Promise<string | null>;
55
- getBasicUserInfo: () => Promise<BasicUserInfo | null>;
56
- getDataLayer: () => Promise<DataLayer<any> | null>;
57
- getDecodedIDToken: () => Promise<IdTokenPayload | null>;
58
- getIdToken: () => Promise<string | null>;
59
- getOIDCServiceEndpoints: () => Promise<OIDCEndpoints | null>;
60
- isAuthenticated: () => Promise<boolean>;
61
- revokeAccessToken: () => Promise<void>;
62
- signIn: (callbackUrl?: string) => Promise<void>;
63
- signOut: () => Promise<void>;
137
+ /**
138
+ * Auth state hydrated from server to client via useState.
139
+ */
140
+ export interface AsgardeoAuthState {
141
+ isLoading: boolean;
142
+ isSignedIn: boolean;
143
+ user: User | null;
64
144
  }
65
- export type SessionLastRefreshedAt = Date | undefined;
66
- export type SessionStatus = 'authenticated' | 'unauthenticated' | 'loading';
67
- export type { BasicUserInfo };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3
+ *
4
+ * WSO2 LLC. licenses this file to you under the Apache License,
5
+ * Version 2.0 (the "License"); you may not use this file except
6
+ * in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing,
12
+ * software distributed under the License is distributed on an
13
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ * KIND, either express or implied. See the License for the
15
+ * specific language governing permissions and limitations
16
+ * under the License.
17
+ */
18
+ /**
19
+ * Create a route matcher function from an array of glob-like patterns.
20
+ *
21
+ * Patterns support:
22
+ * - Literal paths: `/dashboard`
23
+ * - Wildcard segments: `/admin/*` matches `/admin/users` but not `/admin/users/1`
24
+ * - Deep wildcards: `/admin/**` matches `/admin/users` and `/admin/users/1`
25
+ * - Explicit regex groups: `/api/(users|posts)` stays as-is
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * const isProtectedRoute = createRouteMatcher(['/dashboard/**', '/admin/**']);
30
+ * const isPublicRoute = createRouteMatcher(['/', '/about', '/sign-in']);
31
+ *
32
+ * // In a global middleware:
33
+ * export default defineNuxtRouteMiddleware((to) => {
34
+ * if (isProtectedRoute(to.path) && !authState.value?.isSignedIn) {
35
+ * return navigateTo('/api/auth/signin', { external: true });
36
+ * }
37
+ * });
38
+ * ```
39
+ */
40
+ export declare function createRouteMatcher(patterns: string[]): (path: string) => boolean;
@@ -0,0 +1,7 @@
1
+ export function createRouteMatcher(patterns) {
2
+ const regexes = patterns.map((pattern) => {
3
+ const regexStr = pattern.replace(/[.+^${}|[\]\\]/g, "\\$&").replace(/\*\*/g, "___DOUBLE_STAR___").replace(/\*/g, "[^/]*").replace(/___DOUBLE_STAR___/g, ".*");
4
+ return new RegExp(`^${regexStr}$`);
5
+ });
6
+ return (path) => regexes.some((regex) => regex.test(path));
7
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3
+ *
4
+ * WSO2 LLC. licenses this file to you under the Apache License,
5
+ * Version 2.0 (the "License"); you may not use this file except
6
+ * in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing,
12
+ * software distributed under the License is distributed on an
13
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ * KIND, either express or implied. See the License for the
15
+ * specific language governing permissions and limitations
16
+ * under the License.
17
+ */
18
+ /**
19
+ * @asgardeo/nuxt/utils
20
+ *
21
+ * Public utilities barrel. Import from this subpath to access
22
+ * utilities such as createRouteMatcher without polluting the
23
+ * global auto-import namespace.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { createRouteMatcher } from '@asgardeo/nuxt/utils';
28
+ * ```
29
+ */
30
+ export { createRouteMatcher } from './createRouteMatcher.js';
@@ -0,0 +1 @@
1
+ export { createRouteMatcher } from "./createRouteMatcher.js";