@scalar/mock-server 0.8.35 → 0.8.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @scalar/mock-server
|
|
2
2
|
|
|
3
|
+
## 0.8.37
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#8146](https://github.com/scalar/scalar/pull/8146): fix: oauth2 confirmation page shows broken logo
|
|
8
|
+
- [#8146](https://github.com/scalar/scalar/pull/8146): feat: show requested scopes on oauth2 confirmation page
|
|
9
|
+
|
|
10
|
+
#### Updated Dependencies
|
|
11
|
+
|
|
12
|
+
- **@scalar/helpers@0.2.12**
|
|
13
|
+
- [#8178](https://github.com/scalar/scalar/pull/8178): chore: package bump due to ci failure
|
|
14
|
+
|
|
15
|
+
- **@scalar/oas-utils@0.6.42**
|
|
16
|
+
|
|
17
|
+
- **@scalar/json-magic@0.11.1**
|
|
18
|
+
|
|
19
|
+
- **@scalar/openapi-parser@0.24.10**
|
|
20
|
+
|
|
21
|
+
- **@scalar/openapi-upgrader@0.1.8**
|
|
22
|
+
|
|
23
|
+
## 0.8.36
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
#### Updated Dependencies
|
|
28
|
+
|
|
29
|
+
- **@scalar/oas-utils@0.6.41**
|
|
30
|
+
|
|
3
31
|
## 0.8.35
|
|
4
32
|
|
|
5
33
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"respond-with-authorize-page.d.ts","sourceRoot":"","sources":["../../src/routes/respond-with-authorize-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"respond-with-authorize-page.d.ts","sourceRoot":"","sources":["../../src/routes/respond-with-authorize-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAgCnC;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,SAAK,YA4E9D"}
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
const EXAMPLE_AUTHORIZATION_CODE = "super-secret-token";
|
|
2
|
+
const EXAMPLE_ACCESS_TOKEN = "super-secret-access-token";
|
|
3
|
+
function escapeHtml(s) {
|
|
4
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
5
|
+
}
|
|
6
|
+
function parseScopeParam(scopeQuery) {
|
|
7
|
+
if (!scopeQuery || scopeQuery.trim() === "") {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
return scopeQuery.split(/[\s+]+/).map((s) => s.trim()).filter(Boolean);
|
|
11
|
+
}
|
|
2
12
|
function respondWithAuthorizePage(c, title = "") {
|
|
3
13
|
const redirectUri = c.req.query("redirect_uri");
|
|
14
|
+
const responseType = c.req.query("response_type");
|
|
15
|
+
const scope = c.req.query("scope");
|
|
4
16
|
const state = c.req.query("state");
|
|
5
17
|
if (!redirectUri) {
|
|
6
18
|
return c.html(
|
|
@@ -13,17 +25,43 @@ function respondWithAuthorizePage(c, title = "") {
|
|
|
13
25
|
}
|
|
14
26
|
try {
|
|
15
27
|
const redirectUrl = new URL(redirectUri);
|
|
16
|
-
|
|
17
|
-
if (
|
|
18
|
-
|
|
28
|
+
const isImplicitFlow = responseType === "token";
|
|
29
|
+
if (isImplicitFlow) {
|
|
30
|
+
const fragmentParams = new URLSearchParams();
|
|
31
|
+
fragmentParams.set("access_token", EXAMPLE_ACCESS_TOKEN);
|
|
32
|
+
fragmentParams.set("token_type", "Bearer");
|
|
33
|
+
fragmentParams.set("expires_in", "3600");
|
|
34
|
+
if (scope) {
|
|
35
|
+
fragmentParams.set("scope", scope);
|
|
36
|
+
}
|
|
37
|
+
if (state) {
|
|
38
|
+
fragmentParams.set("state", state);
|
|
39
|
+
}
|
|
40
|
+
redirectUrl.hash = fragmentParams.toString();
|
|
41
|
+
} else {
|
|
42
|
+
redirectUrl.searchParams.set("code", EXAMPLE_AUTHORIZATION_CODE);
|
|
43
|
+
if (state) {
|
|
44
|
+
redirectUrl.searchParams.set("state", state);
|
|
45
|
+
}
|
|
19
46
|
}
|
|
20
47
|
const deniedUrl = new URL(redirectUri);
|
|
21
|
-
if (
|
|
22
|
-
|
|
48
|
+
if (isImplicitFlow) {
|
|
49
|
+
const deniedFragmentParams = new URLSearchParams();
|
|
50
|
+
deniedFragmentParams.set("error", "access_denied");
|
|
51
|
+
deniedFragmentParams.set("error_description", "User has denied the authorization request");
|
|
52
|
+
if (state) {
|
|
53
|
+
deniedFragmentParams.set("state", state);
|
|
54
|
+
}
|
|
55
|
+
deniedUrl.hash = deniedFragmentParams.toString();
|
|
56
|
+
} else {
|
|
57
|
+
if (state) {
|
|
58
|
+
deniedUrl.searchParams.set("state", state);
|
|
59
|
+
}
|
|
60
|
+
deniedUrl.searchParams.set("error", "access_denied");
|
|
61
|
+
deniedUrl.searchParams.set("error_description", "User has denied the authorization request");
|
|
23
62
|
}
|
|
24
|
-
|
|
25
|
-
deniedUrl.
|
|
26
|
-
const htmlContent = generateAuthorizationHtml(redirectUrl.toString(), deniedUrl.toString(), title);
|
|
63
|
+
const scopes = parseScopeParam(c.req.query("scope"));
|
|
64
|
+
const htmlContent = generateAuthorizationHtml(redirectUrl.toString(), deniedUrl.toString(), title, scopes);
|
|
27
65
|
return c.html(htmlContent);
|
|
28
66
|
} catch {
|
|
29
67
|
return c.html(
|
|
@@ -35,7 +73,12 @@ function respondWithAuthorizePage(c, title = "") {
|
|
|
35
73
|
);
|
|
36
74
|
}
|
|
37
75
|
}
|
|
38
|
-
function generateAuthorizationHtml(redirectUrl, deniedUrl, title = "") {
|
|
76
|
+
function generateAuthorizationHtml(redirectUrl, deniedUrl, title = "", scopes = []) {
|
|
77
|
+
const scopesSection = scopes.length > 0 ? `
|
|
78
|
+
<p class="font-medium text-gray-700">Requested Scopes</p>
|
|
79
|
+
<ul class="list-disc list-inside space-y-1">
|
|
80
|
+
${scopes.map((scope) => `<li><code class="bg-gray-100 py-1 px-2 rounded text-sm">${escapeHtml(scope)}</code></li>`).join("\n ")}
|
|
81
|
+
</ul>` : "";
|
|
39
82
|
return `
|
|
40
83
|
<!DOCTYPE html>
|
|
41
84
|
<html lang="en">
|
|
@@ -49,9 +92,9 @@ function generateAuthorizationHtml(redirectUrl, deniedUrl, title = "") {
|
|
|
49
92
|
|
|
50
93
|
<div class="flex flex-col">
|
|
51
94
|
<div class="mb-5 flex justify-center items-center gap-2">
|
|
52
|
-
<img src="https://scalar.com/logo-dark.svg" class="w-6 inline-block" />
|
|
95
|
+
<img src="https://cdn.scalar.com/images/logo-dark.svg" class="w-6 inline-block" />
|
|
53
96
|
<div class="font-medium truncate max-w-[26ch] text-lg">
|
|
54
|
-
${title}
|
|
97
|
+
${escapeHtml(title)}
|
|
55
98
|
</div>
|
|
56
99
|
</div>
|
|
57
100
|
<div class="bg-gray-50 rounded-lg p-1 rounded-lg w-[28rem] shadow">
|
|
@@ -64,6 +107,7 @@ function generateAuthorizationHtml(redirectUrl, deniedUrl, title = "") {
|
|
|
64
107
|
<p>
|
|
65
108
|
This application is requesting access to your account. By granting authorization, you allow the application to perform certain actions on your behalf.
|
|
66
109
|
</p>
|
|
110
|
+
${scopesSection}
|
|
67
111
|
<p>
|
|
68
112
|
If you're comfortable with the access being requested, click the button below to grant authorization:
|
|
69
113
|
</p>
|
|
@@ -81,7 +125,7 @@ function generateAuthorizationHtml(redirectUrl, deniedUrl, title = "") {
|
|
|
81
125
|
</div>
|
|
82
126
|
|
|
83
127
|
<p class="text-xs text-gray-400 mt-5 text-center">
|
|
84
|
-
This authorization page is provided by
|
|
128
|
+
This authorization page is provided by the <a href="https://scalar.com/products/mock-server/getting-started" target="_blank" class="underline text-gray-600 hover:text-gray-800">Scalar Mock Server</a>.
|
|
85
129
|
</p>
|
|
86
130
|
|
|
87
131
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/routes/respond-with-authorize-page.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from 'hono'\n\n/** Always responds with this code */\nconst EXAMPLE_AUTHORIZATION_CODE = 'super-secret-token'\n\n/**\n * Responds with an HTML page that simulates an OAuth 2.0 authorization page.\n */\nexport function respondWithAuthorizePage(c: Context, title = '') {\n const redirectUri = c.req.query('redirect_uri')\n const state = c.req.query('state')\n\n if (!redirectUri) {\n return c.html(\n generateErrorHtml(\n 'Missing redirect_uri parameter',\n 'This parameter is required for the OAuth 2.0 authorization flow to function correctly. Please provide a valid redirect URI in your request.',\n ),\n 400,\n )\n }\n\n try {\n // Validate redirect URI against allowed domains\n const redirectUrl = new URL(redirectUri)\n\n redirectUrl.searchParams.set('code', EXAMPLE_AUTHORIZATION_CODE)\n\n
|
|
5
|
-
"mappings": "AAGA,MAAM,6BAA6B;
|
|
4
|
+
"sourcesContent": ["import type { Context } from 'hono'\n\n/** Always responds with this code */\nconst EXAMPLE_AUTHORIZATION_CODE = 'super-secret-token'\n/** Always responds with this token for implicit flow */\nconst EXAMPLE_ACCESS_TOKEN = 'super-secret-access-token'\n\n/**\n * Escapes HTML special characters to prevent XSS when rendering user-controlled scope values.\n */\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n}\n\n/**\n * Parses the OAuth 2.0 scope query parameter (space- or +-separated) into an array of scope strings.\n */\nfunction parseScopeParam(scopeQuery: string | undefined): string[] {\n if (!scopeQuery || scopeQuery.trim() === '') {\n return []\n }\n return scopeQuery\n .split(/[\\s+]+/)\n .map((s) => s.trim())\n .filter(Boolean)\n}\n\n/**\n * Responds with an HTML page that simulates an OAuth 2.0 authorization page.\n */\nexport function respondWithAuthorizePage(c: Context, title = '') {\n const redirectUri = c.req.query('redirect_uri')\n const responseType = c.req.query('response_type')\n const scope = c.req.query('scope')\n const state = c.req.query('state')\n\n if (!redirectUri) {\n return c.html(\n generateErrorHtml(\n 'Missing redirect_uri parameter',\n 'This parameter is required for the OAuth 2.0 authorization flow to function correctly. Please provide a valid redirect URI in your request.',\n ),\n 400,\n )\n }\n\n try {\n // Validate redirect URI against allowed domains\n const redirectUrl = new URL(redirectUri)\n const isImplicitFlow = responseType === 'token'\n\n if (isImplicitFlow) {\n const fragmentParams = new URLSearchParams()\n fragmentParams.set('access_token', EXAMPLE_ACCESS_TOKEN)\n fragmentParams.set('token_type', 'Bearer')\n fragmentParams.set('expires_in', '3600')\n\n if (scope) {\n fragmentParams.set('scope', scope)\n }\n\n if (state) {\n fragmentParams.set('state', state)\n }\n\n redirectUrl.hash = fragmentParams.toString()\n } else {\n redirectUrl.searchParams.set('code', EXAMPLE_AUTHORIZATION_CODE)\n\n if (state) {\n redirectUrl.searchParams.set('state', state)\n }\n }\n\n const deniedUrl = new URL(redirectUri)\n if (isImplicitFlow) {\n const deniedFragmentParams = new URLSearchParams()\n deniedFragmentParams.set('error', 'access_denied')\n deniedFragmentParams.set('error_description', 'User has denied the authorization request')\n\n if (state) {\n deniedFragmentParams.set('state', state)\n }\n\n deniedUrl.hash = deniedFragmentParams.toString()\n } else {\n if (state) {\n deniedUrl.searchParams.set('state', state)\n }\n deniedUrl.searchParams.set('error', 'access_denied')\n deniedUrl.searchParams.set('error_description', 'User has denied the authorization request')\n }\n\n const scopes = parseScopeParam(c.req.query('scope'))\n const htmlContent = generateAuthorizationHtml(redirectUrl.toString(), deniedUrl.toString(), title, scopes)\n\n return c.html(htmlContent)\n } catch {\n return c.html(\n generateErrorHtml(\n 'Invalid redirect_uri format',\n 'Please provide a valid URL. The redirect_uri parameter must be a properly formatted URL that includes the protocol (e.g., https://) and a valid domain. This is essential for the OAuth 2.0 flow to securely redirect after authorization.',\n ),\n 400,\n )\n }\n}\n\nfunction generateAuthorizationHtml(redirectUrl: string, deniedUrl: string, title = '', scopes: string[] = []) {\n const scopesSection =\n scopes.length > 0\n ? `\n <p class=\"font-medium text-gray-700\">Requested Scopes</p>\n <ul class=\"list-disc list-inside space-y-1\">\n ${scopes.map((scope) => `<li><code class=\"bg-gray-100 py-1 px-2 rounded text-sm\">${escapeHtml(scope)}</code></li>`).join('\\n ')}\n </ul>`\n : ''\n\n return `\n<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>OAuth 2.0 Authorization</title>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n </head>\n <body class=\"flex justify-center items-center h-screen bg-gray-100\">\n\n <div class=\"flex flex-col\">\n <div class=\"mb-5 flex justify-center items-center gap-2\">\n <img src=\"https://cdn.scalar.com/images/logo-dark.svg\" class=\"w-6 inline-block\" />\n <div class=\"font-medium truncate max-w-[26ch] text-lg\">\n ${escapeHtml(title)}\n </div>\n </div>\n <div class=\"bg-gray-50 rounded-lg p-1 rounded-lg w-[28rem] shadow\">\n <div class=\"\">\n <h1 class=\"text font-medium text-gray-800 px-6 pt-2 pb-3 flex gap-3 rounded-t-lg\">\n OAuth 2.0 Authorization\n </h1>\n <div class=\"bg-white rounded\">\n <div class=\"text-gray-600 text-base px-6 py-5 flex flex-col gap-3\">\n <p>\n This application is requesting access to your account. By granting authorization, you allow the application to perform certain actions on your behalf.\n </p>\n ${scopesSection}\n <p>\n If you're comfortable with the access being requested, click the button below to grant authorization:\n </p>\n </div>\n <div class=\"px-6 py-4 pt-0 flex justify-between\">\n <a href=\"${deniedUrl}\" class=\"inline-block px-6 py-2 text-gray-600 rounded border\" aria-label=\"Cancel authorization\">\n Cancel\n </a>\n <a href=\"${redirectUrl}\" class=\"inline-block px-6 py-2 bg-black text-white rounded transition-colors duration-300 hover:bg-gray-800\" aria-label=\"Authorize application\">\n Authorize\n </a>\n </div>\n </div>\n </div>\n </div>\n\n <p class=\"text-xs text-gray-400 mt-5 text-center\">\n This authorization page is provided by the <a href=\"https://scalar.com/products/mock-server/getting-started\" target=\"_blank\" class=\"underline text-gray-600 hover:text-gray-800\">Scalar Mock Server</a>.\n </p>\n\n </div>\n </body>\n</html>\n `\n}\n\nfunction generateErrorHtml(title: string, message: string) {\n return `<html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>OAuth 2.0 Authorization</title>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n </head>\n <body>\n <div class=\"p-4 m-8 flex flex-col gap-4 text-lg\">\n <h1 class=\"font-bold\">\n Error: ${title}\n </h1>\n <p>\n ${message}\n </p>\n <p>\n Example: <code class=\"bg-gray-100 py-1 px-2 rounded text-base\"><a href=\"?redirect_uri=https://example.com/callback\">?redirect_uri=https://example.com/callback</a></code>\n </p>\n </div>\n </body>\n</html>`\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"swagger",
|
|
17
17
|
"cli"
|
|
18
18
|
],
|
|
19
|
-
"version": "0.8.
|
|
19
|
+
"version": "0.8.37",
|
|
20
20
|
"engines": {
|
|
21
21
|
"node": ">=20"
|
|
22
22
|
},
|
|
@@ -53,11 +53,11 @@
|
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@faker-js/faker": "^10.2.0",
|
|
55
55
|
"hono": "4.11.7",
|
|
56
|
-
"@scalar/
|
|
57
|
-
"@scalar/
|
|
58
|
-
"@scalar/openapi-parser": "0.24.
|
|
56
|
+
"@scalar/json-magic": "0.11.1",
|
|
57
|
+
"@scalar/helpers": "0.2.12",
|
|
58
|
+
"@scalar/openapi-parser": "0.24.10",
|
|
59
59
|
"@scalar/openapi-types": "0.5.3",
|
|
60
|
-
"@scalar/oas-utils": "0.6.
|
|
60
|
+
"@scalar/oas-utils": "0.6.42",
|
|
61
61
|
"@scalar/openapi-upgrader": "0.1.8"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|