@decocms/runtime 1.0.0-alpha.28 → 1.0.0-alpha.30
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/package.json +2 -2
- package/src/oauth.ts +18 -9
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decocms/runtime",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.30",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@cloudflare/workers-types": "^4.20250617.0",
|
|
7
7
|
"@deco/mcp": "npm:@jsr/deco__mcp@0.5.5",
|
|
8
|
-
"@decocms/bindings": "1.0.1-alpha.
|
|
8
|
+
"@decocms/bindings": "1.0.1-alpha.17",
|
|
9
9
|
"@modelcontextprotocol/sdk": "1.20.2",
|
|
10
10
|
"@ai-sdk/provider": "^2.0.0",
|
|
11
11
|
"hono": "^4.10.7",
|
package/src/oauth.ts
CHANGED
|
@@ -65,6 +65,15 @@ interface CodePayload {
|
|
|
65
65
|
codeChallengeMethod?: string;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
const forceHttps = (url: URL) => {
|
|
69
|
+
const isLocal = url.hostname === "localhost" || url.hostname === "127.0.0.1";
|
|
70
|
+
if (!isLocal) {
|
|
71
|
+
// force http if not local
|
|
72
|
+
url.protocol = "https:";
|
|
73
|
+
}
|
|
74
|
+
return url;
|
|
75
|
+
};
|
|
76
|
+
|
|
68
77
|
/**
|
|
69
78
|
* Create OAuth endpoint handlers for MCP servers
|
|
70
79
|
* The MCP server acts as an OAuth Authorization Server proxy
|
|
@@ -77,7 +86,7 @@ export function createOAuthHandlers(oauth: OAuthConfig) {
|
|
|
77
86
|
* Points to THIS server as the authorization server
|
|
78
87
|
*/
|
|
79
88
|
const handleProtectedResourceMetadata = (req: Request): Response => {
|
|
80
|
-
const url = new URL(req.url);
|
|
89
|
+
const url = forceHttps(new URL(req.url));
|
|
81
90
|
const resourceUrl = `${url.origin}/mcp`;
|
|
82
91
|
|
|
83
92
|
return Response.json({
|
|
@@ -95,7 +104,7 @@ export function createOAuthHandlers(oauth: OAuthConfig) {
|
|
|
95
104
|
* Exposes our endpoints for authorization, token exchange, and registration
|
|
96
105
|
*/
|
|
97
106
|
const handleAuthorizationServerMetadata = (req: Request): Response => {
|
|
98
|
-
const url = new URL(req.url);
|
|
107
|
+
const url = forceHttps(new URL(req.url));
|
|
99
108
|
const baseUrl = url.origin;
|
|
100
109
|
|
|
101
110
|
return Response.json({
|
|
@@ -117,7 +126,7 @@ export function createOAuthHandlers(oauth: OAuthConfig) {
|
|
|
117
126
|
* Stateless: encodes all needed info in the state parameter
|
|
118
127
|
*/
|
|
119
128
|
const handleAuthorize = (req: Request): Response => {
|
|
120
|
-
const url = new URL(req.url);
|
|
129
|
+
const url = forceHttps(new URL(req.url));
|
|
121
130
|
const redirectUri = url.searchParams.get("redirect_uri");
|
|
122
131
|
const responseType = url.searchParams.get("response_type");
|
|
123
132
|
const clientState = url.searchParams.get("state");
|
|
@@ -155,7 +164,7 @@ export function createOAuthHandlers(oauth: OAuthConfig) {
|
|
|
155
164
|
const encodedState = encodeState(pendingState);
|
|
156
165
|
|
|
157
166
|
// Build callback URL pointing to our internal callback
|
|
158
|
-
const callbackUrl = new URL(`${url.origin}/oauth/callback`);
|
|
167
|
+
const callbackUrl = forceHttps(new URL(`${url.origin}/oauth/callback`));
|
|
159
168
|
callbackUrl.searchParams.set("state", encodedState);
|
|
160
169
|
|
|
161
170
|
// Get the external authorization URL from the config
|
|
@@ -170,7 +179,7 @@ export function createOAuthHandlers(oauth: OAuthConfig) {
|
|
|
170
179
|
* Stateless: decodes state to get redirect info, encodes token in code
|
|
171
180
|
*/
|
|
172
181
|
const handleOAuthCallback = async (req: Request): Promise<Response> => {
|
|
173
|
-
const url = new URL(req.url);
|
|
182
|
+
const url = forceHttps(new URL(req.url));
|
|
174
183
|
const code = url.searchParams.get("code");
|
|
175
184
|
const encodedState = url.searchParams.get("state");
|
|
176
185
|
const error = url.searchParams.get("error");
|
|
@@ -184,7 +193,7 @@ export function createOAuthHandlers(oauth: OAuthConfig) {
|
|
|
184
193
|
const errorDescription =
|
|
185
194
|
url.searchParams.get("error_description") ?? "Authorization failed";
|
|
186
195
|
if (pending?.redirectUri) {
|
|
187
|
-
const redirectUrl = new URL(pending.redirectUri);
|
|
196
|
+
const redirectUrl = forceHttps(new URL(pending.redirectUri));
|
|
188
197
|
redirectUrl.searchParams.set("error", error);
|
|
189
198
|
redirectUrl.searchParams.set("error_description", errorDescription);
|
|
190
199
|
if (pending.clientState)
|
|
@@ -222,7 +231,7 @@ export function createOAuthHandlers(oauth: OAuthConfig) {
|
|
|
222
231
|
const ourCode = encodeState(codePayload);
|
|
223
232
|
|
|
224
233
|
// Redirect back to client with our code
|
|
225
|
-
const redirectUrl = new URL(pending.redirectUri);
|
|
234
|
+
const redirectUrl = forceHttps(new URL(pending.redirectUri));
|
|
226
235
|
redirectUrl.searchParams.set("code", ourCode);
|
|
227
236
|
if (pending.clientState) {
|
|
228
237
|
redirectUrl.searchParams.set("state", pending.clientState);
|
|
@@ -233,7 +242,7 @@ export function createOAuthHandlers(oauth: OAuthConfig) {
|
|
|
233
242
|
console.error("OAuth callback error:", err);
|
|
234
243
|
|
|
235
244
|
// Redirect back to client with error
|
|
236
|
-
const redirectUrl = new URL(pending.redirectUri);
|
|
245
|
+
const redirectUrl = forceHttps(new URL(pending.redirectUri));
|
|
237
246
|
redirectUrl.searchParams.set("error", "server_error");
|
|
238
247
|
redirectUrl.searchParams.set(
|
|
239
248
|
"error_description",
|
|
@@ -445,7 +454,7 @@ export function createOAuthHandlers(oauth: OAuthConfig) {
|
|
|
445
454
|
* Per MCP spec: MUST include resource_metadata URL
|
|
446
455
|
*/
|
|
447
456
|
const createUnauthorizedResponse = (req: Request): Response => {
|
|
448
|
-
const url = new URL(req.url);
|
|
457
|
+
const url = forceHttps(new URL(req.url));
|
|
449
458
|
const resourceMetadataUrl = `${url.origin}/.well-known/oauth-protected-resource`;
|
|
450
459
|
const wwwAuthenticateValue = `Bearer resource_metadata="${resourceMetadataUrl}", scope="*"`;
|
|
451
460
|
|