@@ -72,22 +72,196 @@ export class EverythingAuthProvider implements OAuthServerProvider {
72
72
// You can redirect to another page, or you can send an html response directly
73
73
// res.redirect(new URL(`fakeupstreamauth/authorize?metadata=${authorizationCode}`, BASE_URI).href);
74
74
75
+ // Set permissive CSP for styling
76
+ res . setHeader ( 'Content-Security-Policy' , [
77
+ "default-src 'self'" ,
78
+ "style-src 'self' 'unsafe-inline'" ,
79
+ "script-src 'self' 'unsafe-inline'" ,
80
+ "img-src 'self' data:" ,
81
+ "object-src 'none'" ,
82
+ "frame-ancestors 'none'" ,
83
+ "form-action 'self'" ,
84
+ "base-uri 'self'"
85
+ ] . join ( '; ' ) ) ;
86
+
75
87
res . send ( `
76
- <html>
88
+ <!DOCTYPE html>
89
+ <html lang="en">
77
90
<head>
78
- <title>MCP Auth Page</title>
91
+ <meta charset="UTF-8">
92
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
93
+ <title>MCP Server Authorization</title>
94
+ <style>
95
+ * {
96
+ margin: 0;
97
+ padding: 0;
98
+ box-sizing: border-box;
99
+ }
100
+
101
+ body {
102
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
103
+ background: #000000;
104
+ color: #ffffff;
105
+ min-height: 100vh;
106
+ display: flex;
107
+ align-items: center;
108
+ justify-content: center;
109
+ padding: 20px;
110
+ }
111
+
112
+ .auth-container {
113
+ background: #ffffff;
114
+ color: #000000;
115
+ border-radius: 16px;
116
+ box-shadow: 0 20px 40px rgba(255, 255, 255, 0.1);
117
+ padding: 40px;
118
+ max-width: 500px;
119
+ width: 100%;
120
+ text-align: center;
121
+ border: 1px solid #e2e8f0;
122
+ }
123
+
124
+ .logo-container {
125
+ margin-bottom: 32px;
126
+ }
127
+
128
+ .logo {
129
+ width: 80px;
130
+ height: 80px;
131
+ margin: 0 auto 16px;
132
+ filter: invert(1);
133
+ }
134
+
135
+ .mcp-title {
136
+ font-size: 24px;
137
+ font-weight: 700;
138
+ color: #000000;
139
+ margin-bottom: 8px;
140
+ letter-spacing: 2px;
141
+ }
142
+
143
+ h1 {
144
+ color: #000000;
145
+ font-size: 32px;
146
+ font-weight: 800;
147
+ margin-bottom: 12px;
148
+ line-height: 1.2;
149
+ }
150
+
151
+ .subtitle {
152
+ color: #4a5568;
153
+ font-size: 18px;
154
+ margin-bottom: 32px;
155
+ line-height: 1.5;
156
+ }
157
+
158
+ .client-info {
159
+ background: #f8f9fa;
160
+ border-radius: 12px;
161
+ padding: 24px;
162
+ margin-bottom: 32px;
163
+ border: 2px solid #e2e8f0;
164
+ }
165
+
166
+ .client-info h3 {
167
+ color: #2d3748;
168
+ font-size: 18px;
169
+ font-weight: 600;
170
+ margin-bottom: 16px;
171
+ }
172
+
173
+ .client-id {
174
+ background: white;
175
+ border: 2px solid #e2e8f0;
176
+ border-radius: 8px;
177
+ padding: 12px;
178
+ font-family: 'Courier New', monospace;
179
+ font-size: 14px;
180
+ color: #4a5568;
181
+ word-break: break-all;
182
+ }
183
+
184
+ .auth-flow-info {
185
+ background: #f8f9fa;
186
+ border-radius: 12px;
187
+ padding: 24px;
188
+ margin-bottom: 32px;
189
+ border-left: 4px solid #000000;
190
+ }
191
+
192
+ .auth-flow-info h3 {
193
+ color: #2d3748;
194
+ font-size: 18px;
195
+ font-weight: 600;
196
+ margin-bottom: 12px;
197
+ }
198
+
199
+ .auth-flow-info p {
200
+ color: #4a5568;
201
+ font-size: 14px;
202
+ line-height: 1.5;
203
+ }
204
+
205
+ .btn-primary {
206
+ background: #000000;
207
+ color: #ffffff;
208
+ font-size: 18px;
209
+ font-weight: 700;
210
+ padding: 18px 36px;
211
+ border: none;
212
+ border-radius: 8px;
213
+ cursor: pointer;
214
+ transition: all 0.2s ease;
215
+ width: 100%;
216
+ text-decoration: none;
217
+ display: inline-block;
218
+ text-align: center;
219
+ letter-spacing: 1px;
220
+ }
221
+
222
+ .btn-primary:hover {
223
+ background: #333333;
224
+ transform: translateY(-2px);
225
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
226
+ }
227
+
228
+ .branding {
229
+ margin-top: 24px;
230
+ padding-top: 24px;
231
+ border-top: 1px solid #e2e8f0;
232
+ color: #718096;
233
+ font-size: 12px;
234
+ }
235
+ </style>
79
236
</head>
80
237
<body>
81
- <h1>MCP Server Auth Page</h1>
82
- <p>
83
- This page is the authorization page presented by the MCP server, routing the user upstream. This is only
84
- needed on 2025-03-26 Auth spec, where the MCP server acts as it's own authoriztion server. This page should
85
- be present to avoid confused deputy attacks.
86
- </p>
87
- <p>
88
- Click <a href="/fakeupstreamauth/authorize?redirect_uri=/fakeupstreamauth/callback&state=${ authorizationCode } ">here</a>
89
- to continue to the upstream auth
90
- </p>
238
+ <div class="auth-container">
239
+ <div class="logo-container">
240
+ <img src="/mcp-logo.png" alt="MCP Logo" class="logo">
241
+ <div class="mcp-title">MCP</div>
242
+ </div>
243
+
244
+ <h1>Authorization Required</h1>
245
+ <p class="subtitle">This client wants to connect to your MCP server</p>
246
+
247
+ <div class="client-info">
248
+ <h3>Client Application</h3>
249
+ <div class="client-id">${ client . client_id } </div>
250
+ </div>
251
+
252
+ <div class="auth-flow-info">
253
+ <h3>What happens next?</h3>
254
+ <p>You'll be redirected to authenticate with the upstream provider. Once verified, you'll be granted access to this MCP server's resources.</p>
255
+ </div>
256
+
257
+ <a href="/fakeupstreamauth/authorize?redirect_uri=/fakeupstreamauth/callback&state=${ authorizationCode } " class="btn-primary">
258
+ Continue to Authentication
259
+ </a>
260
+
261
+ <div class="branding">
262
+ Model Context Protocol (MCP) Server
263
+ </div>
264
+ </div>
91
265
</body>
92
266
</html>
93
267
` ) ;
@@ -156,6 +330,7 @@ export class EverythingAuthProvider implements OAuthServerProvider {
156
330
...mcpInstallation ,
157
331
mcpTokens : newTokens ,
158
332
issuedAt : Date . now ( ) / 1000 ,
333
+ userId : mcpInstallation . userId , // Preserve the user ID
159
334
} ) ;
160
335
161
336
return newTokens ;
@@ -183,7 +358,10 @@ export class EverythingAuthProvider implements OAuthServerProvider {
183
358
token,
184
359
clientId : installation . clientId ,
185
360
scopes : [ 'mcp' ] ,
186
- expiresAt
361
+ expiresAt,
362
+ extra : {
363
+ userId : installation . userId
364
+ }
187
365
} ;
188
366
}
189
367
0 commit comments