@thunderid/nuxt 0.0.1
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/LICENSE +201 -0
- package/dist/module.d.mts +46 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +216 -0
- package/dist/runtime/components/ThunderIDRoot.d.ts +52 -0
- package/dist/runtime/components/ThunderIDRoot.js +160 -0
- package/dist/runtime/components/actions/SignInButton.d.ts +37 -0
- package/dist/runtime/components/actions/SignInButton.js +51 -0
- package/dist/runtime/components/actions/SignOutButton.d.ts +34 -0
- package/dist/runtime/components/actions/SignOutButton.js +43 -0
- package/dist/runtime/components/actions/SignUpButton.d.ts +33 -0
- package/dist/runtime/components/actions/SignUpButton.js +48 -0
- package/dist/runtime/components/auth/Callback.d.ts +43 -0
- package/dist/runtime/components/auth/Callback.js +93 -0
- package/dist/runtime/components/auth/SignIn.d.ts +38 -0
- package/dist/runtime/components/auth/SignIn.js +60 -0
- package/dist/runtime/components/auth/SignUp.d.ts +40 -0
- package/dist/runtime/components/auth/SignUp.js +79 -0
- package/dist/runtime/components/control/Loading.d.ts +36 -0
- package/dist/runtime/components/control/Loading.js +17 -0
- package/dist/runtime/components/control/SignedIn.d.ts +38 -0
- package/dist/runtime/components/control/SignedIn.js +17 -0
- package/dist/runtime/components/control/SignedOut.d.ts +37 -0
- package/dist/runtime/components/control/SignedOut.js +17 -0
- package/dist/runtime/components/organization/CreateOrganization.d.ts +32 -0
- package/dist/runtime/components/organization/CreateOrganization.js +29 -0
- package/dist/runtime/components/organization/Organization.d.ts +39 -0
- package/dist/runtime/components/organization/Organization.js +17 -0
- package/dist/runtime/components/organization/OrganizationList.d.ts +34 -0
- package/dist/runtime/components/organization/OrganizationList.js +30 -0
- package/dist/runtime/components/organization/OrganizationProfile.d.ts +32 -0
- package/dist/runtime/components/organization/OrganizationProfile.js +32 -0
- package/dist/runtime/components/organization/OrganizationSwitcher.d.ts +36 -0
- package/dist/runtime/components/organization/OrganizationSwitcher.js +26 -0
- package/dist/runtime/components/user/User.d.ts +38 -0
- package/dist/runtime/components/user/User.js +17 -0
- package/dist/runtime/components/user/UserDropdown.d.ts +38 -0
- package/dist/runtime/components/user/UserDropdown.js +45 -0
- package/dist/runtime/components/user/UserProfile.d.ts +35 -0
- package/dist/runtime/components/user/UserProfile.js +35 -0
- package/dist/runtime/composables/useThunderID.d.ts +38 -0
- package/dist/runtime/composables/useThunderID.js +73 -0
- package/dist/runtime/errors/error-codes.d.ts +40 -0
- package/dist/runtime/errors/error-codes.js +19 -0
- package/dist/runtime/errors/index.d.ts +19 -0
- package/dist/runtime/errors/index.js +2 -0
- package/dist/runtime/errors/thunderid-error.d.ts +47 -0
- package/dist/runtime/errors/thunderid-error.js +15 -0
- package/dist/runtime/middleware/auth.d.ts +35 -0
- package/dist/runtime/middleware/auth.js +2 -0
- package/dist/runtime/middleware/defineThunderIDMiddleware.d.ts +53 -0
- package/dist/runtime/middleware/defineThunderIDMiddleware.js +24 -0
- package/dist/runtime/plugins/thunderid.d.ts +39 -0
- package/dist/runtime/plugins/thunderid.js +128 -0
- package/dist/runtime/server/ThunderIDNuxtClient.d.ts +186 -0
- package/dist/runtime/server/ThunderIDNuxtClient.js +384 -0
- package/dist/runtime/server/index.d.ts +33 -0
- package/dist/runtime/server/index.js +3 -0
- package/dist/runtime/server/plugins/thunderid-ssr.d.ts +40 -0
- package/dist/runtime/server/plugins/thunderid-ssr.js +135 -0
- package/dist/runtime/server/routes/auth/branding/branding.get.d.ts +31 -0
- package/dist/runtime/server/routes/auth/branding/branding.get.js +40 -0
- package/dist/runtime/server/routes/auth/organizations/current.get.d.ts +29 -0
- package/dist/runtime/server/routes/auth/organizations/current.get.js +24 -0
- package/dist/runtime/server/routes/auth/organizations/id.get.d.ts +28 -0
- package/dist/runtime/server/routes/auth/organizations/id.get.js +28 -0
- package/dist/runtime/server/routes/auth/organizations/index.get.d.ts +28 -0
- package/dist/runtime/server/routes/auth/organizations/index.get.js +24 -0
- package/dist/runtime/server/routes/auth/organizations/index.post.d.ts +30 -0
- package/dist/runtime/server/routes/auth/organizations/index.post.js +30 -0
- package/dist/runtime/server/routes/auth/organizations/me.get.d.ts +28 -0
- package/dist/runtime/server/routes/auth/organizations/me.get.js +24 -0
- package/dist/runtime/server/routes/auth/organizations/switch.post.d.ts +32 -0
- package/dist/runtime/server/routes/auth/organizations/switch.post.js +49 -0
- package/dist/runtime/server/routes/auth/session/callback.get.d.ts +27 -0
- package/dist/runtime/server/routes/auth/session/callback.get.js +91 -0
- package/dist/runtime/server/routes/auth/session/callback.post.d.ts +48 -0
- package/dist/runtime/server/routes/auth/session/callback.post.js +53 -0
- package/dist/runtime/server/routes/auth/session/session.get.d.ts +26 -0
- package/dist/runtime/server/routes/auth/session/session.get.js +22 -0
- package/dist/runtime/server/routes/auth/session/signin.get.d.ts +29 -0
- package/dist/runtime/server/routes/auth/session/signin.get.js +37 -0
- package/dist/runtime/server/routes/auth/session/signin.post.d.ts +37 -0
- package/dist/runtime/server/routes/auth/session/signin.post.js +102 -0
- package/dist/runtime/server/routes/auth/session/signout.post.d.ts +31 -0
- package/dist/runtime/server/routes/auth/session/signout.post.js +38 -0
- package/dist/runtime/server/routes/auth/session/signup.post.d.ts +36 -0
- package/dist/runtime/server/routes/auth/session/signup.post.js +30 -0
- package/dist/runtime/server/routes/auth/session/token.get.d.ts +29 -0
- package/dist/runtime/server/routes/auth/session/token.get.js +6 -0
- package/dist/runtime/server/routes/auth/user/profile.get.d.ts +29 -0
- package/dist/runtime/server/routes/auth/user/profile.get.js +24 -0
- package/dist/runtime/server/routes/auth/user/profile.patch.d.ts +35 -0
- package/dist/runtime/server/routes/auth/user/profile.patch.js +41 -0
- package/dist/runtime/server/routes/auth/user/user.get.d.ts +25 -0
- package/dist/runtime/server/routes/auth/user/user.get.js +21 -0
- package/dist/runtime/server/utils/event-context.d.ts +49 -0
- package/dist/runtime/server/utils/event-context.js +3 -0
- package/dist/runtime/server/utils/serverSession.d.ts +65 -0
- package/dist/runtime/server/utils/serverSession.js +44 -0
- package/dist/runtime/server/utils/session.d.ts +85 -0
- package/dist/runtime/server/utils/session.js +106 -0
- package/dist/runtime/server/utils/token-refresh.d.ts +42 -0
- package/dist/runtime/server/utils/token-refresh.js +65 -0
- package/dist/runtime/types.d.ts +161 -0
- package/dist/runtime/types.js +0 -0
- package/dist/runtime/utils/createRouteMatcher.d.ts +40 -0
- package/dist/runtime/utils/createRouteMatcher.js +7 -0
- package/dist/runtime/utils/index.d.ts +30 -0
- package/dist/runtime/utils/index.js +1 -0
- package/dist/runtime/utils/log.d.ts +44 -0
- package/dist/runtime/utils/log.js +25 -0
- package/dist/runtime/utils/url-validation.d.ts +49 -0
- package/dist/runtime/utils/url-validation.js +38 -0
- package/dist/types.d.mts +7 -0
- package/package.json +101 -0
|
@@ -0,0 +1,161 @@
|
|
|
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 { BrandingPreference, I18nPreferences, Organization, Platform, TokenEndpointAuthMethod, User, UserProfile } from '@thunderid/node';
|
|
19
|
+
import type { JWTPayload } from 'jose';
|
|
20
|
+
/**
|
|
21
|
+
* Configuration for the ThunderID Nuxt module.
|
|
22
|
+
*/
|
|
23
|
+
export interface ThunderIDNuxtConfig {
|
|
24
|
+
/** URL to redirect to after sign-in (default: '/') */
|
|
25
|
+
afterSignInUrl?: string;
|
|
26
|
+
/** URL to redirect to after sign-out (default: '/') */
|
|
27
|
+
afterSignOutUrl?: string;
|
|
28
|
+
/**
|
|
29
|
+
* ThunderID application id (`spId`) — appended to the redirect-based sign-up
|
|
30
|
+
* URL when present. Mirrors `applicationId` in the React/Next.js SDKs.
|
|
31
|
+
*/
|
|
32
|
+
applicationId?: string;
|
|
33
|
+
/** Base URL of the ThunderID 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;
|
|
39
|
+
/**
|
|
40
|
+
* Identity platform variant. Set to `Platform.ThunderIDV2` when connecting to
|
|
41
|
+
* a Thunder (ThunderIDV2) instance. Forwarded to the underlying Node client so
|
|
42
|
+
* platform-specific behaviours (e.g. issuer resolution) apply correctly.
|
|
43
|
+
*/
|
|
44
|
+
platform?: keyof typeof Platform;
|
|
45
|
+
/**
|
|
46
|
+
* Feature-gating preferences that control which server-side data fetches
|
|
47
|
+
* the Nitro plugin performs on every SSR request.
|
|
48
|
+
*/
|
|
49
|
+
preferences?: {
|
|
50
|
+
/** i18n configuration forwarded to `I18nProvider`. */
|
|
51
|
+
i18n?: I18nPreferences;
|
|
52
|
+
theme?: {
|
|
53
|
+
/**
|
|
54
|
+
* When true (default), the Nitro plugin fetches the branding preference
|
|
55
|
+
* from ThunderID and passes it to `BrandingProvider` / `ThemeProvider`.
|
|
56
|
+
*/
|
|
57
|
+
inheritFromBranding?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Theme mode forwarded to the Vue SDK's `ThemeProvider`.
|
|
60
|
+
* - `'light'` (default) | `'dark'`: Fixed color scheme. Toggle at runtime with `useTheme().toggleTheme()`.
|
|
61
|
+
* - `'system'`: Follows the OS `prefers-color-scheme`.
|
|
62
|
+
* - `'class'`: Reads a CSS class on `<html>` (works well with Tailwind dark-mode).
|
|
63
|
+
* - `'branding'`: Follows the active theme from the tenant's branding preference.
|
|
64
|
+
*/
|
|
65
|
+
mode?: 'light' | 'dark' | 'system' | 'class' | 'branding';
|
|
66
|
+
};
|
|
67
|
+
user?: {
|
|
68
|
+
/** Whether to fetch the user's organisations during SSR (default: true). */
|
|
69
|
+
fetchOrganizations?: boolean;
|
|
70
|
+
/** Whether to fetch the SCIM2 user profile during SSR (default: true). */
|
|
71
|
+
fetchUserProfile?: boolean;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
/** OAuth2 scopes to request */
|
|
75
|
+
scopes?: string[];
|
|
76
|
+
/** Secret for signing session JWTs (use ASGARDEO_SESSION_SECRET env var) */
|
|
77
|
+
sessionSecret?: string;
|
|
78
|
+
/**
|
|
79
|
+
* Optional override for the redirect-based sign-in URL. Reserved for
|
|
80
|
+
* parity with the React/Next.js SDKs; not currently used by the redirect
|
|
81
|
+
* flow (which goes through `/api/auth/signin`).
|
|
82
|
+
*/
|
|
83
|
+
signInUrl?: string;
|
|
84
|
+
/**
|
|
85
|
+
* Optional override for the redirect-based sign-up URL. When set,
|
|
86
|
+
* `<ThunderIDSignUpButton>` and `useThunderID().signUp()` (no-arg) navigate
|
|
87
|
+
* here instead of deriving the URL from `baseUrl`/`clientId`.
|
|
88
|
+
*/
|
|
89
|
+
signUpUrl?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Configuration for the token endpoint request.
|
|
92
|
+
*/
|
|
93
|
+
tokenRequest?: {
|
|
94
|
+
/**
|
|
95
|
+
* OAuth 2.0 client authentication method used at the token endpoint.
|
|
96
|
+
* Defaults to `client_secret_basic` for ThunderIDV2 and `client_secret_post`
|
|
97
|
+
* for all other platforms when not specified.
|
|
98
|
+
*/
|
|
99
|
+
authMethod?: TokenEndpointAuthMethod;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Payload stored in the session JWT cookie.
|
|
104
|
+
*/
|
|
105
|
+
export interface ThunderIDSessionPayload extends JWTPayload {
|
|
106
|
+
accessToken: string;
|
|
107
|
+
/** Unix timestamp (seconds) when the access token expires. Used for proactive refresh. */
|
|
108
|
+
accessTokenExpiresAt?: number;
|
|
109
|
+
exp: number;
|
|
110
|
+
iat: number;
|
|
111
|
+
/** Raw ID token string (for userinfo derivation without in-memory store). */
|
|
112
|
+
idToken?: string;
|
|
113
|
+
organizationId?: string;
|
|
114
|
+
/** Refresh token for obtaining new access tokens without re-authentication. */
|
|
115
|
+
refreshToken?: string;
|
|
116
|
+
scopes: string;
|
|
117
|
+
sessionId: string;
|
|
118
|
+
sub: string;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Payload stored in the temporary session JWT cookie (during OAuth flow).
|
|
122
|
+
*/
|
|
123
|
+
export interface ThunderIDTempSessionPayload extends JWTPayload {
|
|
124
|
+
/** URL to redirect to after successful sign-in */
|
|
125
|
+
returnTo?: string;
|
|
126
|
+
sessionId: string;
|
|
127
|
+
type: 'temp';
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Full SSR payload resolved by the Nitro plugin on each page request.
|
|
131
|
+
* Written to `event.context.thunderid.ssr` and subsequently seeded into
|
|
132
|
+
* hydrated `useState` keys so the client never re-fetches on first render.
|
|
133
|
+
*/
|
|
134
|
+
export interface ThunderIDSSRData {
|
|
135
|
+
/** Branding preference fetched from ThunderID (null when `preferences.theme.inheritFromBranding` is false). */
|
|
136
|
+
brandingPreference: BrandingPreference | null;
|
|
137
|
+
/** The organisation the user is currently acting within (null when not in an org). */
|
|
138
|
+
currentOrganization: Organization | null;
|
|
139
|
+
isSignedIn: boolean;
|
|
140
|
+
/** All organisations the user is a member of (empty array when `preferences.user.fetchOrganizations` is false). */
|
|
141
|
+
myOrganizations: Organization[];
|
|
142
|
+
/**
|
|
143
|
+
* The base URL actually used for this request.
|
|
144
|
+
* Equals `${baseUrl}/o` when the user is acting within an organisation
|
|
145
|
+
* (derived from the `user_org` claim in the ID token), otherwise equals
|
|
146
|
+
* the configured `baseUrl`.
|
|
147
|
+
*/
|
|
148
|
+
resolvedBaseUrl: string | null;
|
|
149
|
+
session: ThunderIDSessionPayload | null;
|
|
150
|
+
user: User | null;
|
|
151
|
+
/** Flattened SCIM2 profile + raw profile + schemas (null when `preferences.user.fetchUserProfile` is false). */
|
|
152
|
+
userProfile: UserProfile | null;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Auth state hydrated from server to client via useState.
|
|
156
|
+
*/
|
|
157
|
+
export interface ThunderIDAuthState {
|
|
158
|
+
isLoading: boolean;
|
|
159
|
+
isSignedIn: boolean;
|
|
160
|
+
user: User | null;
|
|
161
|
+
}
|
|
File without changes
|
|
@@ -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
|
+
* @thunderid/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 '@thunderid/nuxt/utils';
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export { createRouteMatcher } from './createRouteMatcher.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createRouteMatcher } from "./createRouteMatcher.js";
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
* Mask a token so it is safe to include in logs and error messages.
|
|
20
|
+
* Shows the first 4 and last 4 characters, replacing the middle with "…".
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* maskToken('eyJhbGciOiJIUzI1NiJ9.abc.xyz') // 'eyJh….xyz'
|
|
24
|
+
*/
|
|
25
|
+
export declare function maskToken(token: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Create a namespaced logger for a specific SDK subsystem.
|
|
28
|
+
*
|
|
29
|
+
* Debug output is suppressed unless the `ASGARDEO_DEBUG` environment
|
|
30
|
+
* variable is set (any truthy value).
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* const log = createLogger('session');
|
|
35
|
+
* log.info('Session created for', maskToken(accessToken));
|
|
36
|
+
* log.debug('Full payload', payload); // only logged when ASGARDEO_DEBUG=true
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function createLogger(subsystem: string): {
|
|
40
|
+
debug: (...args: unknown[]) => void;
|
|
41
|
+
error: (...args: unknown[]) => void;
|
|
42
|
+
info: (...args: unknown[]) => void;
|
|
43
|
+
warn: (...args: unknown[]) => void;
|
|
44
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const PREFIX = "@thunderid/nuxt";
|
|
2
|
+
export function maskToken(token) {
|
|
3
|
+
if (!token) return "(empty)";
|
|
4
|
+
if (token.length <= 8) return "***";
|
|
5
|
+
return `${token.slice(0, 4)}\u2026${token.slice(-4)}`;
|
|
6
|
+
}
|
|
7
|
+
export function createLogger(subsystem) {
|
|
8
|
+
const tag = `[${PREFIX}:${subsystem}]`;
|
|
9
|
+
return {
|
|
10
|
+
debug: (...args) => {
|
|
11
|
+
if (process.env["ASGARDEO_DEBUG"]) {
|
|
12
|
+
console.log(tag, ...args);
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
error: (...args) => {
|
|
16
|
+
console.error(tag, ...args);
|
|
17
|
+
},
|
|
18
|
+
info: (...args) => {
|
|
19
|
+
console.log(tag, ...args);
|
|
20
|
+
},
|
|
21
|
+
warn: (...args) => {
|
|
22
|
+
console.warn(tag, ...args);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
* Validate a `returnTo` / redirect URL supplied by the client.
|
|
20
|
+
*
|
|
21
|
+
* Rules (defence-in-depth against open-redirect attacks):
|
|
22
|
+
* 1. Must be a non-empty string.
|
|
23
|
+
* 2. Must start with `/` (relative path only — no protocol, no host).
|
|
24
|
+
* 3. Must NOT start with `//` (protocol-relative URL — resolves as absolute).
|
|
25
|
+
* 4. Must NOT contain a `\` after the leading `/` (browser normalises `\` to `/`).
|
|
26
|
+
* 5. Must NOT contain a `%2F` or `%5C` in the first two chars after `/`
|
|
27
|
+
* (encoded slashes/backslashes that bypass rule 3/4 after URL decoding).
|
|
28
|
+
*
|
|
29
|
+
* Returns the validated URL as-is on success, or throws `ThunderIDError`
|
|
30
|
+
* with `ErrorCode.OpenRedirectBlocked` on failure.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* const safe = validateReturnUrl('/dashboard'); // '/dashboard'
|
|
35
|
+
* validateReturnUrl('//evil.com'); // throws
|
|
36
|
+
* validateReturnUrl('https://evil.com'); // throws
|
|
37
|
+
* validateReturnUrl('/\\evil.com'); // throws
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function validateReturnUrl(url: unknown): string;
|
|
41
|
+
/**
|
|
42
|
+
* Safe variant of `validateReturnUrl` that returns a fallback instead of throwing.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* const url = safeReturnUrl(query.returnTo, '/dashboard');
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function safeReturnUrl(url: unknown, fallback?: string): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ThunderIDError } from "../errors/thunderid-error.js";
|
|
2
|
+
import { ErrorCode } from "../errors/error-codes.js";
|
|
3
|
+
export function validateReturnUrl(url) {
|
|
4
|
+
if (typeof url !== "string" || url.trim() === "") {
|
|
5
|
+
throw new ThunderIDError("returnTo must be a non-empty string.", ErrorCode.OpenRedirectBlocked, { statusCode: 400 });
|
|
6
|
+
}
|
|
7
|
+
const trimmed = url.trim();
|
|
8
|
+
if (!trimmed.startsWith("/") || trimmed.startsWith("//")) {
|
|
9
|
+
throw new ThunderIDError(
|
|
10
|
+
`Open redirect blocked: returnTo "${trimmed}" must be a relative path starting with a single "/".`,
|
|
11
|
+
ErrorCode.OpenRedirectBlocked,
|
|
12
|
+
{ statusCode: 400 }
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
if (trimmed.length > 1 && trimmed[1] === "\\") {
|
|
16
|
+
throw new ThunderIDError(
|
|
17
|
+
`Open redirect blocked: returnTo "${trimmed}" contains a backslash.`,
|
|
18
|
+
ErrorCode.OpenRedirectBlocked,
|
|
19
|
+
{ statusCode: 400 }
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
const decoded = decodeURIComponent(trimmed.slice(1, 5).toLowerCase());
|
|
23
|
+
if (decoded.startsWith("/") || decoded.startsWith("\\")) {
|
|
24
|
+
throw new ThunderIDError(
|
|
25
|
+
`Open redirect blocked: returnTo "${trimmed}" contains an encoded redirect sequence.`,
|
|
26
|
+
ErrorCode.OpenRedirectBlocked,
|
|
27
|
+
{ statusCode: 400 }
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
return trimmed;
|
|
31
|
+
}
|
|
32
|
+
export function safeReturnUrl(url, fallback = "/") {
|
|
33
|
+
try {
|
|
34
|
+
return validateReturnUrl(url);
|
|
35
|
+
} catch {
|
|
36
|
+
return fallback;
|
|
37
|
+
}
|
|
38
|
+
}
|
package/dist/types.d.mts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thunderid/nuxt",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Nuxt SDK for ThunderID",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"thunderid",
|
|
7
|
+
"nuxt",
|
|
8
|
+
"nuxtjs",
|
|
9
|
+
"ssr"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/thunder-id/thunderid/tree/main/sdks/nuxt#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/thunder-id/thunderid/issues"
|
|
14
|
+
},
|
|
15
|
+
"author": "WSO2",
|
|
16
|
+
"license": "Apache-2.0",
|
|
17
|
+
"type": "module",
|
|
18
|
+
"main": "./dist/module.mjs",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/types.d.mts",
|
|
22
|
+
"import": "./dist/module.mjs"
|
|
23
|
+
},
|
|
24
|
+
"./server": {
|
|
25
|
+
"types": "./dist/runtime/server/index.d.ts",
|
|
26
|
+
"import": "./dist/runtime/server/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./errors": {
|
|
29
|
+
"types": "./dist/runtime/errors/index.d.ts",
|
|
30
|
+
"import": "./dist/runtime/errors/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./utils": {
|
|
33
|
+
"types": "./dist/runtime/utils/index.d.ts",
|
|
34
|
+
"import": "./dist/runtime/utils/index.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"typesVersions": {
|
|
38
|
+
"*": {
|
|
39
|
+
".": [
|
|
40
|
+
"./dist/types.d.mts"
|
|
41
|
+
],
|
|
42
|
+
"server": [
|
|
43
|
+
"./dist/runtime/server/index.d.ts"
|
|
44
|
+
],
|
|
45
|
+
"errors": [
|
|
46
|
+
"./dist/runtime/errors/index.d.ts"
|
|
47
|
+
],
|
|
48
|
+
"utils": [
|
|
49
|
+
"./dist/runtime/utils/index.d.ts"
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"files": [
|
|
54
|
+
"dist",
|
|
55
|
+
"LICENSE",
|
|
56
|
+
"README.md"
|
|
57
|
+
],
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "https://github.com/thunder-id/thunderid",
|
|
61
|
+
"directory": "packages/nuxt"
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"@nuxt/kit": "3.16.2",
|
|
65
|
+
"defu": "6.1.5",
|
|
66
|
+
"jose": "5.2.0",
|
|
67
|
+
"@thunderid/browser": "^0.0.1",
|
|
68
|
+
"@thunderid/node": "^0.0.1",
|
|
69
|
+
"@thunderid/vue": "^0.0.1"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@nuxt/devtools": "2.4.0",
|
|
73
|
+
"@nuxt/module-builder": "1.0.1",
|
|
74
|
+
"@nuxt/schema": "3.16.2",
|
|
75
|
+
"@nuxt/test-utils": "3.17.2",
|
|
76
|
+
"@types/node": "24.7.2",
|
|
77
|
+
"eslint": "9.39.4",
|
|
78
|
+
"h3": "1.15.11",
|
|
79
|
+
"nuxt": "3.16.2",
|
|
80
|
+
"typescript": "5.9.3",
|
|
81
|
+
"vitest": "4.1.3",
|
|
82
|
+
"@thunderid/eslint-plugin": "^0.0.0",
|
|
83
|
+
"@thunderid/prettier-config": "^0.0.0"
|
|
84
|
+
},
|
|
85
|
+
"peerDependencies": {
|
|
86
|
+
"nuxt": ">=3.10.0",
|
|
87
|
+
"vue": ">=3.5.0"
|
|
88
|
+
},
|
|
89
|
+
"publishConfig": {
|
|
90
|
+
"access": "public"
|
|
91
|
+
},
|
|
92
|
+
"scripts": {
|
|
93
|
+
"build": "nuxt module-build prepare && nuxt module-build build",
|
|
94
|
+
"format:check": "prettier --check --cache .",
|
|
95
|
+
"format:fix": "prettier --write --cache .",
|
|
96
|
+
"lint": "nuxt prepare && eslint .",
|
|
97
|
+
"lint:fix": "nuxt prepare && eslint . --fix",
|
|
98
|
+
"test": "vitest run --passWithNoTests",
|
|
99
|
+
"typecheck": "nuxt module-build prepare && vue-tsc --noEmit"
|
|
100
|
+
}
|
|
101
|
+
}
|