@asgardeo/nuxt 0.0.0 → 0.1.0-alpha.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.
- package/README.md +482 -6
- package/dist/module.d.mts +17 -24
- package/dist/module.json +2 -2
- package/dist/module.mjs +174 -48
- package/dist/runtime/components/AsgardeoRoot.d.ts +52 -0
- package/dist/runtime/components/AsgardeoRoot.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/useAsgardeo.d.ts +38 -0
- package/dist/runtime/composables/useAsgardeo.js +73 -0
- package/dist/runtime/errors/asgardeo-error.d.ts +47 -0
- package/dist/runtime/errors/asgardeo-error.js +15 -0
- package/dist/runtime/errors/error-codes.d.ts +40 -0
- package/dist/runtime/errors/error-codes.js +19 -0
- package/dist/runtime/{composables/asgardeo/useAuth.d.ts → errors/index.d.ts} +2 -2
- package/dist/runtime/errors/index.js +2 -0
- package/dist/runtime/middleware/auth.d.ts +35 -0
- package/dist/runtime/middleware/auth.js +2 -0
- package/dist/runtime/middleware/defineAsgardeoMiddleware.d.ts +53 -0
- package/dist/runtime/middleware/defineAsgardeoMiddleware.js +24 -0
- package/dist/runtime/plugins/asgardeo.d.ts +40 -0
- package/dist/runtime/plugins/asgardeo.js +129 -0
- package/dist/runtime/server/AsgardeoNuxtClient.d.ts +182 -0
- package/dist/runtime/server/AsgardeoNuxtClient.js +366 -0
- package/dist/runtime/server/index.d.ts +33 -0
- package/dist/runtime/server/index.js +3 -0
- package/dist/runtime/server/plugins/asgardeo-ssr.d.ts +41 -0
- package/dist/runtime/server/plugins/asgardeo-ssr.js +134 -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/{handler.d.ts → routes/auth/user/profile.patch.d.ts} +17 -13
- package/dist/runtime/server/routes/auth/user/profile.patch.js +33 -0
- package/dist/runtime/server/{services/asgardeo/index.d.ts → routes/auth/user/user.get.d.ts} +6 -4
- 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/augments.d.ts +61 -0
- package/dist/runtime/types.d.ts +115 -38
- 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 +0 -2
- package/package.json +48 -23
- package/dist/runtime/composables/asgardeo/useAuth.js +0 -129
- package/dist/runtime/server/handler.js +0 -231
- package/dist/runtime/server/services/asgardeo/index.js +0 -18
|
@@ -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 = "@asgardeo/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 `AsgardeoError`
|
|
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 { AsgardeoError } from "../errors/asgardeo-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 AsgardeoError("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 AsgardeoError(
|
|
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 AsgardeoError(
|
|
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 AsgardeoError(
|
|
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
CHANGED
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asgardeo/nuxt",
|
|
3
|
-
"version": "0.0.0",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
4
|
"description": "Nuxt module for Asgardeo - Authentication and Identity Management",
|
|
5
5
|
"author": "WSO2",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
|
-
"homepage": "https://github.com/asgardeo/
|
|
7
|
+
"homepage": "https://github.com/asgardeo/javascript/tree/main/packages/nuxt#readme",
|
|
8
8
|
"bugs": {
|
|
9
|
-
"url": "https://github.com/asgardeo/
|
|
9
|
+
"url": "https://github.com/asgardeo/javascript/issues"
|
|
10
10
|
},
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
13
|
-
"url": "https://github.com/asgardeo/
|
|
13
|
+
"url": "https://github.com/asgardeo/javascript",
|
|
14
14
|
"directory": "packages/nuxt"
|
|
15
15
|
},
|
|
16
16
|
"keywords": [
|
|
@@ -30,6 +30,18 @@
|
|
|
30
30
|
".": {
|
|
31
31
|
"types": "./dist/types.d.mts",
|
|
32
32
|
"import": "./dist/module.mjs"
|
|
33
|
+
},
|
|
34
|
+
"./server": {
|
|
35
|
+
"types": "./dist/runtime/server/index.d.ts",
|
|
36
|
+
"import": "./dist/runtime/server/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./errors": {
|
|
39
|
+
"types": "./dist/runtime/errors/index.d.ts",
|
|
40
|
+
"import": "./dist/runtime/errors/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./utils": {
|
|
43
|
+
"types": "./dist/runtime/utils/index.d.ts",
|
|
44
|
+
"import": "./dist/runtime/utils/index.js"
|
|
33
45
|
}
|
|
34
46
|
},
|
|
35
47
|
"main": "./dist/module.mjs",
|
|
@@ -37,6 +49,15 @@
|
|
|
37
49
|
"*": {
|
|
38
50
|
".": [
|
|
39
51
|
"./dist/types.d.mts"
|
|
52
|
+
],
|
|
53
|
+
"server": [
|
|
54
|
+
"./dist/runtime/server/index.d.ts"
|
|
55
|
+
],
|
|
56
|
+
"errors": [
|
|
57
|
+
"./dist/runtime/errors/index.d.ts"
|
|
58
|
+
],
|
|
59
|
+
"utils": [
|
|
60
|
+
"./dist/runtime/utils/index.d.ts"
|
|
40
61
|
]
|
|
41
62
|
}
|
|
42
63
|
},
|
|
@@ -46,35 +67,39 @@
|
|
|
46
67
|
"README.md"
|
|
47
68
|
],
|
|
48
69
|
"dependencies": {
|
|
49
|
-
"@
|
|
50
|
-
"
|
|
51
|
-
"
|
|
70
|
+
"@nuxt/kit": "3.16.2",
|
|
71
|
+
"defu": "6.1.4",
|
|
72
|
+
"jose": "^6.0.11",
|
|
73
|
+
"@asgardeo/browser": "0.7.0",
|
|
74
|
+
"@asgardeo/vue": "0.3.3",
|
|
75
|
+
"@asgardeo/node": "0.0.75"
|
|
76
|
+
},
|
|
77
|
+
"peerDependencies": {
|
|
78
|
+
"nuxt": ">=3.10.0",
|
|
79
|
+
"vue": ">=3.5.0"
|
|
52
80
|
},
|
|
53
81
|
"devDependencies": {
|
|
54
|
-
"@nuxt/devtools": "
|
|
55
|
-
"@nuxt/
|
|
56
|
-
"@nuxt/
|
|
57
|
-
"@nuxt/
|
|
58
|
-
"@
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"cookie-es": "^2.0.0",
|
|
82
|
+
"@nuxt/devtools": "2.4.0",
|
|
83
|
+
"@nuxt/module-builder": "1.0.1",
|
|
84
|
+
"@nuxt/schema": "3.16.2",
|
|
85
|
+
"@nuxt/test-utils": "3.17.2",
|
|
86
|
+
"@types/node": "22.13.4",
|
|
87
|
+
"changelogen": "0.6.1",
|
|
88
|
+
"cookie-es": "2.0.0",
|
|
62
89
|
"eslint": "8.57.0",
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
90
|
+
"h3": "1.15.11",
|
|
91
|
+
"nuxt": "3.16.2",
|
|
92
|
+
"typescript": "5.8.3",
|
|
93
|
+
"vitest": "3.1.1",
|
|
94
|
+
"vue-tsc": "2.2.8"
|
|
67
95
|
},
|
|
68
96
|
"publishConfig": {
|
|
69
97
|
"access": "public"
|
|
70
98
|
},
|
|
71
99
|
"scripts": {
|
|
72
100
|
"build": "nuxt module-build prepare && nuxt module-build build",
|
|
73
|
-
"dev": "nuxi dev playground",
|
|
74
|
-
"dev:build": "nuxi build playground",
|
|
75
|
-
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
76
101
|
"lint": "nuxt prepare && eslint .",
|
|
77
102
|
"test": "vitest run --passWithNoTests",
|
|
78
|
-
"typecheck": "nuxt prepare && vue-tsc --noEmit"
|
|
103
|
+
"typecheck": "nuxt module-build prepare && vue-tsc --noEmit"
|
|
79
104
|
}
|
|
80
105
|
}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { navigateTo } from "#imports";
|
|
2
|
-
export const useAuth = () => {
|
|
3
|
-
const signIn = async (callbackUrl) => {
|
|
4
|
-
const options = {
|
|
5
|
-
external: true,
|
|
6
|
-
query: {}
|
|
7
|
-
};
|
|
8
|
-
const redirectParam = callbackUrl || (typeof window !== "undefined" ? window.location.pathname : "/");
|
|
9
|
-
options.query = { callbackUrl: redirectParam };
|
|
10
|
-
options.external = true;
|
|
11
|
-
await navigateTo("/api/auth/signin", options);
|
|
12
|
-
};
|
|
13
|
-
const getIdToken = async () => {
|
|
14
|
-
try {
|
|
15
|
-
const response = await fetch("/api/auth/get-id-token", {
|
|
16
|
-
credentials: "include",
|
|
17
|
-
method: "GET"
|
|
18
|
-
});
|
|
19
|
-
if (!response.ok) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
const data = await response.json();
|
|
23
|
-
return data.idToken;
|
|
24
|
-
} catch (error) {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
const getAccessToken = async () => {
|
|
29
|
-
try {
|
|
30
|
-
const response = await fetch("/api/auth/get-access-token", {
|
|
31
|
-
credentials: "include",
|
|
32
|
-
method: "GET"
|
|
33
|
-
});
|
|
34
|
-
if (!response.ok) {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
const data = await response.json();
|
|
38
|
-
return data.accessToken;
|
|
39
|
-
} catch (error) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
const getDecodedIDToken = async () => {
|
|
44
|
-
try {
|
|
45
|
-
const response = await fetch(`/api/auth/get-decoded-id-token`, {
|
|
46
|
-
credentials: "include",
|
|
47
|
-
method: "GET"
|
|
48
|
-
});
|
|
49
|
-
if (!response.ok) {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
const data = await response.json();
|
|
53
|
-
return data.decodedIDToken;
|
|
54
|
-
} catch (error) {
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
const revokeAccessToken = async () => {
|
|
59
|
-
await fetch("/api/auth/revoke-token", {
|
|
60
|
-
method: "POST"
|
|
61
|
-
}).catch((error) => error.data);
|
|
62
|
-
};
|
|
63
|
-
const isAuthenticated = async () => {
|
|
64
|
-
try {
|
|
65
|
-
const response = await fetch("/api/auth/isAuthenticated", {
|
|
66
|
-
credentials: "include",
|
|
67
|
-
method: "GET"
|
|
68
|
-
});
|
|
69
|
-
if (!response.ok) {
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
return await response.json();
|
|
73
|
-
} catch (error) {
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
const signOut = async () => {
|
|
78
|
-
const options = { external: true };
|
|
79
|
-
await navigateTo("/api/auth/signout", options);
|
|
80
|
-
};
|
|
81
|
-
const getBasicUserInfo = async () => {
|
|
82
|
-
try {
|
|
83
|
-
const userInfo = await $fetch("/api/auth/user", {
|
|
84
|
-
method: "GET"
|
|
85
|
-
});
|
|
86
|
-
return userInfo;
|
|
87
|
-
} catch (error) {
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
const getOIDCServiceEndpoints = async () => {
|
|
92
|
-
try {
|
|
93
|
-
const response = await fetch("/api/auth/get-oidc-endpoints", {
|
|
94
|
-
method: "GET"
|
|
95
|
-
});
|
|
96
|
-
if (!response.ok) {
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
return await response.json();
|
|
100
|
-
} catch (error) {
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
const getDataLayer = async () => {
|
|
105
|
-
try {
|
|
106
|
-
const response = await fetch("/api/auth/get-data-layer", {
|
|
107
|
-
method: "GET"
|
|
108
|
-
});
|
|
109
|
-
if (!response.ok) {
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
return await response.json();
|
|
113
|
-
} catch (error) {
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
return {
|
|
118
|
-
getAccessToken,
|
|
119
|
-
getBasicUserInfo,
|
|
120
|
-
getDataLayer,
|
|
121
|
-
getDecodedIDToken,
|
|
122
|
-
getIdToken,
|
|
123
|
-
getOIDCServiceEndpoints,
|
|
124
|
-
isAuthenticated,
|
|
125
|
-
revokeAccessToken,
|
|
126
|
-
signIn,
|
|
127
|
-
signOut
|
|
128
|
-
};
|
|
129
|
-
};
|
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { defineEventHandler, sendRedirect, setCookie, deleteCookie, getQuery, getCookie, createError } from "h3";
|
|
3
|
-
import { getAsgardeoSdkInstance } from "./services/asgardeo/index.js";
|
|
4
|
-
function mergeCookieOptions(base, specific) {
|
|
5
|
-
const defaultBase = {
|
|
6
|
-
httpOnly: true,
|
|
7
|
-
path: "/",
|
|
8
|
-
sameSite: "lax",
|
|
9
|
-
secure: process.env.NODE_ENV === "production"
|
|
10
|
-
};
|
|
11
|
-
return { ...defaultBase, ...base, ...specific };
|
|
12
|
-
}
|
|
13
|
-
export const AsgardeoAuthHandler = (config, options) => {
|
|
14
|
-
const defaultCookieOptsFromUser = options?.cookies?.defaultOptions ?? {};
|
|
15
|
-
const sessionIdCookieName = options?.cookies?.sessionId ?? "ASGARDEO_SESSION_ID";
|
|
16
|
-
const sessionIdCookieOptions = mergeCookieOptions(
|
|
17
|
-
{
|
|
18
|
-
// Base defaults (already includes secure, httpOnly, path, sameSite)
|
|
19
|
-
maxAge: 9e5 / 1e3
|
|
20
|
-
// Default session length (15 minutes)
|
|
21
|
-
},
|
|
22
|
-
{ ...defaultCookieOptsFromUser, ...options?.cookies?.sessionIdOptions }
|
|
23
|
-
);
|
|
24
|
-
return defineEventHandler(async (event) => {
|
|
25
|
-
const action = event.context.params?._;
|
|
26
|
-
const { method } = event.node.req;
|
|
27
|
-
const authClient = getAsgardeoSdkInstance(config);
|
|
28
|
-
if (action === "signin" && method === "GET") {
|
|
29
|
-
try {
|
|
30
|
-
const sessionId = randomUUID();
|
|
31
|
-
setCookie(event, sessionIdCookieName, sessionId, sessionIdCookieOptions);
|
|
32
|
-
await authClient.signIn(
|
|
33
|
-
(authorizationUrl) => {
|
|
34
|
-
sendRedirect(event, authorizationUrl, 302);
|
|
35
|
-
},
|
|
36
|
-
sessionId,
|
|
37
|
-
getQuery(event).code?.toString(),
|
|
38
|
-
getQuery(event).session_state?.toString(),
|
|
39
|
-
getQuery(event).state?.toString(),
|
|
40
|
-
{}
|
|
41
|
-
);
|
|
42
|
-
return null;
|
|
43
|
-
} catch (error) {
|
|
44
|
-
throw createError({
|
|
45
|
-
data: error.message,
|
|
46
|
-
statusCode: 500,
|
|
47
|
-
statusMessage: "Failed to initiate sign in"
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
} else if (action === "callback" && method === "GET") {
|
|
51
|
-
const sessionId = getCookie(event, sessionIdCookieName);
|
|
52
|
-
if (!sessionId) {
|
|
53
|
-
throw createError({
|
|
54
|
-
statusCode: 400,
|
|
55
|
-
statusMessage: "Authentication callback error: Session ID missing."
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
const { code, session_state, state, error, error_description } = getQuery(event);
|
|
59
|
-
if (!code) {
|
|
60
|
-
if (error) {
|
|
61
|
-
throw createError({
|
|
62
|
-
statusCode: 400,
|
|
63
|
-
statusMessage: `Authentication failed: ${error_description ?? error}`
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
throw createError({
|
|
67
|
-
statusCode: 400,
|
|
68
|
-
statusMessage: "Authorization code missing in callback."
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
const tokenResponse = await authClient.signIn(
|
|
73
|
-
() => {
|
|
74
|
-
},
|
|
75
|
-
// no-op redirect callback
|
|
76
|
-
sessionId,
|
|
77
|
-
code.toString(),
|
|
78
|
-
session_state?.toString() ?? "",
|
|
79
|
-
state?.toString() ?? ""
|
|
80
|
-
);
|
|
81
|
-
if (!tokenResponse?.accessToken && !tokenResponse?.idToken) {
|
|
82
|
-
throw createError({
|
|
83
|
-
statusCode: 500,
|
|
84
|
-
statusMessage: "Token exchange failed: Invalid response from Identity Provider."
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
return await sendRedirect(event, options?.defaultCallbackUrl ?? "/", 302);
|
|
88
|
-
} catch (err) {
|
|
89
|
-
throw createError({
|
|
90
|
-
data: err.message ?? "An unexpected error occurred during token exchange",
|
|
91
|
-
statusCode: 500,
|
|
92
|
-
statusMessage: "Token exchange failed."
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
} else if (action === "user" && method === "GET") {
|
|
96
|
-
const sessionId = getCookie(event, sessionIdCookieName);
|
|
97
|
-
if (!sessionId) {
|
|
98
|
-
throw createError({
|
|
99
|
-
statusCode: 401,
|
|
100
|
-
statusMessage: "Unauthorized: No active session found."
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
try {
|
|
104
|
-
return await authClient.getBasicUserInfo(sessionId);
|
|
105
|
-
} catch {
|
|
106
|
-
throw createError({
|
|
107
|
-
statusCode: 500,
|
|
108
|
-
statusMessage: "Failed to retrieve user information."
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
} else if (action === "isAuthenticated" && method === "GET") {
|
|
112
|
-
const sessionId = getCookie(event, sessionIdCookieName);
|
|
113
|
-
if (!sessionId) return false;
|
|
114
|
-
try {
|
|
115
|
-
return await authClient.isAuthenticated(sessionId);
|
|
116
|
-
} catch {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
} else if (action === "get-id-token" && method === "GET") {
|
|
120
|
-
const sessionId = getCookie(event, sessionIdCookieName);
|
|
121
|
-
if (!sessionId) {
|
|
122
|
-
throw createError({
|
|
123
|
-
statusCode: 401,
|
|
124
|
-
statusMessage: "Unauthorized: No active session found."
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
try {
|
|
128
|
-
const idToken = await authClient.getIDToken(sessionId);
|
|
129
|
-
return { idToken };
|
|
130
|
-
} catch {
|
|
131
|
-
throw createError({
|
|
132
|
-
statusCode: 500,
|
|
133
|
-
statusMessage: "Failed to retrieve ID token."
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
} else if (action === "get-access-token" && method === "GET") {
|
|
137
|
-
const sessionId = getCookie(event, sessionIdCookieName);
|
|
138
|
-
if (!sessionId) {
|
|
139
|
-
throw createError({
|
|
140
|
-
statusCode: 401,
|
|
141
|
-
statusMessage: "Unauthorized: No active session found."
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
try {
|
|
145
|
-
const accessToken = await authClient.getAccessToken(sessionId);
|
|
146
|
-
return { accessToken };
|
|
147
|
-
} catch {
|
|
148
|
-
throw createError({
|
|
149
|
-
statusCode: 500,
|
|
150
|
-
statusMessage: "Failed to retrieve access token."
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
} else if (action === "get-decoded-id-token" && method === "GET") {
|
|
154
|
-
const sessionId = getCookie(event, sessionIdCookieName);
|
|
155
|
-
if (!sessionId) {
|
|
156
|
-
throw createError({
|
|
157
|
-
statusCode: 401,
|
|
158
|
-
statusMessage: "Unauthorized: No active session found."
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
try {
|
|
162
|
-
return await authClient.getDecodedIDToken(sessionId);
|
|
163
|
-
} catch {
|
|
164
|
-
throw createError({
|
|
165
|
-
statusCode: 500,
|
|
166
|
-
statusMessage: "Failed to retrieve decoded ID token."
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
} else if (action === "revoke-token" && method === "POST") {
|
|
170
|
-
const sessionId = getCookie(event, sessionIdCookieName);
|
|
171
|
-
if (!sessionId) {
|
|
172
|
-
throw createError({
|
|
173
|
-
statusCode: 401,
|
|
174
|
-
statusMessage: "Unauthorized: No active session found."
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
try {
|
|
178
|
-
return await authClient.revokeAccessToken(sessionId);
|
|
179
|
-
} catch {
|
|
180
|
-
throw createError({
|
|
181
|
-
statusCode: 500,
|
|
182
|
-
statusMessage: "Failed to revoke tokens."
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
} else if (action === "get-oidc-endpoints" && method === "GET") {
|
|
186
|
-
try {
|
|
187
|
-
return await authClient.getOIDCServiceEndpoints();
|
|
188
|
-
} catch {
|
|
189
|
-
throw createError({
|
|
190
|
-
statusCode: 500,
|
|
191
|
-
statusMessage: "Failed to retrieve OIDC service endpoints."
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
} else if (action === "signout" && method === "GET") {
|
|
195
|
-
const sessionId = getCookie(event, sessionIdCookieName);
|
|
196
|
-
if (!sessionId) {
|
|
197
|
-
return sendRedirect(event, options?.defaultCallbackUrl ?? "/", 302);
|
|
198
|
-
}
|
|
199
|
-
try {
|
|
200
|
-
const signOutURL = await authClient.signOut(sessionId);
|
|
201
|
-
deleteCookie(event, sessionIdCookieName, sessionIdCookieOptions);
|
|
202
|
-
if (!signOutURL) {
|
|
203
|
-
return await sendRedirect(event, "/?error=signout_url_missing", 302);
|
|
204
|
-
}
|
|
205
|
-
return await sendRedirect(event, signOutURL, 302);
|
|
206
|
-
} catch (error) {
|
|
207
|
-
deleteCookie(event, sessionIdCookieName, sessionIdCookieOptions);
|
|
208
|
-
throw createError({
|
|
209
|
-
data: error.message || "An unexpected error occurred during sign out",
|
|
210
|
-
statusCode: 500,
|
|
211
|
-
statusMessage: "Sign out failed."
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
} else if (action === "get-data-layer" && method === "GET") {
|
|
215
|
-
try {
|
|
216
|
-
const dataLayer = await authClient.getDataLayer();
|
|
217
|
-
return dataLayer;
|
|
218
|
-
} catch (error) {
|
|
219
|
-
throw createError({
|
|
220
|
-
statusCode: 500,
|
|
221
|
-
statusMessage: "Failed to retrieve Data Layer."
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
} else {
|
|
225
|
-
throw createError({
|
|
226
|
-
statusCode: 404,
|
|
227
|
-
statusMessage: `Authentication endpoint not found or method not allowed for action: ${action}`
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { AsgardeoNodeClient } from "@asgardeo/auth-node";
|
|
2
|
-
let authClientInstance = null;
|
|
3
|
-
export function getAsgardeoSdkInstance(config) {
|
|
4
|
-
if (authClientInstance) {
|
|
5
|
-
return authClientInstance;
|
|
6
|
-
}
|
|
7
|
-
if (!config) {
|
|
8
|
-
throw new Error(
|
|
9
|
-
"[Asgardeo] No configuration provided. You must call getAsgardeoSdkInstance(config) with a valid AuthClientConfig on the first use."
|
|
10
|
-
);
|
|
11
|
-
}
|
|
12
|
-
try {
|
|
13
|
-
authClientInstance = new AsgardeoNodeClient(config);
|
|
14
|
-
} catch (error) {
|
|
15
|
-
throw new Error("[Asgardeo] SDK initialization failed. Check provided configuration and SDK compatibility.");
|
|
16
|
-
}
|
|
17
|
-
return authClientInstance;
|
|
18
|
-
}
|