mcp-oauth-provider 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.
Files changed (44) hide show
  1. package/README.md +668 -0
  2. package/dist/__tests__/config.test.js +56 -0
  3. package/dist/__tests__/config.test.js.map +1 -0
  4. package/dist/__tests__/integration.test.js +341 -0
  5. package/dist/__tests__/integration.test.js.map +1 -0
  6. package/dist/__tests__/oauth-flow.test.js +201 -0
  7. package/dist/__tests__/oauth-flow.test.js.map +1 -0
  8. package/dist/__tests__/server.test.js +271 -0
  9. package/dist/__tests__/server.test.js.map +1 -0
  10. package/dist/__tests__/storage.test.js +256 -0
  11. package/dist/__tests__/storage.test.js.map +1 -0
  12. package/dist/client/config.js +30 -0
  13. package/dist/client/config.js.map +1 -0
  14. package/dist/client/factory.js +16 -0
  15. package/dist/client/factory.js.map +1 -0
  16. package/dist/client/index.js +237 -0
  17. package/dist/client/index.js.map +1 -0
  18. package/dist/client/oauth-flow.js +73 -0
  19. package/dist/client/oauth-flow.js.map +1 -0
  20. package/dist/client/storage.js +237 -0
  21. package/dist/client/storage.js.map +1 -0
  22. package/dist/index.js +12 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/server/callback.js +164 -0
  25. package/dist/server/callback.js.map +1 -0
  26. package/dist/server/index.js +8 -0
  27. package/dist/server/index.js.map +1 -0
  28. package/dist/server/templates.js +245 -0
  29. package/dist/server/templates.js.map +1 -0
  30. package/package.json +66 -0
  31. package/src/__tests__/config.test.ts +78 -0
  32. package/src/__tests__/integration.test.ts +398 -0
  33. package/src/__tests__/oauth-flow.test.ts +276 -0
  34. package/src/__tests__/server.test.ts +391 -0
  35. package/src/__tests__/storage.test.ts +329 -0
  36. package/src/client/config.ts +134 -0
  37. package/src/client/factory.ts +19 -0
  38. package/src/client/index.ts +361 -0
  39. package/src/client/oauth-flow.ts +115 -0
  40. package/src/client/storage.ts +335 -0
  41. package/src/index.ts +31 -0
  42. package/src/server/callback.ts +257 -0
  43. package/src/server/index.ts +21 -0
  44. package/src/server/templates.ts +271 -0
@@ -0,0 +1,271 @@
1
+ /**
2
+ * Default success HTML template for OAuth authorization
3
+ */
4
+ export const SUCCESS_TEMPLATE = `<!DOCTYPE html>
5
+ <html lang="en">
6
+ <head>
7
+ <meta charset="UTF-8">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
9
+ <title>Authorization Successful</title>
10
+ <style>
11
+ body {
12
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
13
+ margin: 0;
14
+ padding: 0;
15
+ background: hsl(0deg, 0%, 7%);
16
+ min-height: 100vh;
17
+ display: flex;
18
+ align-items: center;
19
+ justify-content: center;
20
+ }
21
+ .container {
22
+ background: hsl(0deg, 0%, 13%);
23
+ padding: 2rem;
24
+ border-radius: 8px;
25
+ box-shadow: 0 10px 30px rgba(0,0,0,0.5);
26
+ text-align: center;
27
+ max-width: 400px;
28
+ width: 90%;
29
+ border: 1px solid hsl(0deg, 0%, 19%);
30
+ }
31
+ .success-icon {
32
+ width: 64px;
33
+ height: 64px;
34
+ background: #0d1f06;
35
+ border-radius: 50%;
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ margin: 0 auto 1rem;
40
+ border: 2px solid #16a34a;
41
+ }
42
+ .checkmark {
43
+ color: #16a34a;
44
+ font-size: 2rem;
45
+ font-weight: bold;
46
+ }
47
+ h1 {
48
+ color: #ebebec;
49
+ margin: 0 0 1rem;
50
+ font-size: 1.5rem;
51
+ }
52
+ p {
53
+ color: #c4c4c5;
54
+ margin: 0 0 1.5rem;
55
+ line-height: 1.5;
56
+ }
57
+ .close-button {
58
+ background: #114eac;
59
+ color: #ebebec;
60
+ border: none;
61
+ padding: 0.75rem 1.5rem;
62
+ border-radius: 6px;
63
+ font-size: 1rem;
64
+ cursor: pointer;
65
+ transition: background-color 0.2s;
66
+ }
67
+ .close-button:hover {
68
+ background: #186ff6;
69
+ }
70
+ </style>
71
+ </head>
72
+ <body>
73
+ <div class="container">
74
+ <div class="success-icon">
75
+ <span class="checkmark">✓</span>
76
+ </div>
77
+ <h1>Authorization Successful!</h1>
78
+ <p>You have successfully authorized the application. You can close this window and return to the application.</p>
79
+ <button class="close-button" onclick="window.close()">Close Window</button>
80
+ </div>
81
+ </body>
82
+ </html>`;
83
+
84
+ /**
85
+ * Default error HTML template for OAuth authorization
86
+ * Supports placeholder replacement: {{error}}, {{error_description}}, {{error_uri}}
87
+ */
88
+ export const ERROR_TEMPLATE = `<!DOCTYPE html>
89
+ <html lang="en">
90
+ <head>
91
+ <meta charset="UTF-8">
92
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
93
+ <title>Authorization Error</title>
94
+ <style>
95
+ body {
96
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
97
+ margin: 0;
98
+ padding: 0;
99
+ background: hsl(0deg, 0%, 7%);
100
+ color: #c4c4c5;
101
+ min-height: 100vh;
102
+ display: flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ }
106
+ .container {
107
+ background: hsl(0deg, 0%, 13%);
108
+ padding: 2rem;
109
+ border-radius: 8px;
110
+ box-shadow: 0 10px 30px rgba(0,0,0,0.5);
111
+ text-align: center;
112
+ max-width: 400px;
113
+ width: 90%;
114
+ border: 1px solid hsl(0deg, 0%, 19%);
115
+ }
116
+ .error-icon {
117
+ width: 64px;
118
+ height: 64px;
119
+ background: rgba(240, 77, 107, 15%);
120
+ border-radius: 50%;
121
+ display: flex;
122
+ align-items: center;
123
+ justify-content: center;
124
+ margin: 0 auto 1rem;
125
+ border: 2px solid #f87171;
126
+ }
127
+ .x-mark {
128
+ color: #f87171;
129
+ font-size: 2rem;
130
+ font-weight: bold;
131
+ }
132
+ h1 {
133
+ color: #ebebec;
134
+ margin: 0 0 1rem;
135
+ font-size: 1.5rem;
136
+ }
137
+ .error-code {
138
+ background: rgba(240, 77, 107, 15%);
139
+ color: #f87171;
140
+ padding: 0.5rem 1rem;
141
+ border-radius: 6px;
142
+ margin: 0 0 1rem;
143
+ font-family: monospace;
144
+ font-size: 0.9rem;
145
+ border: 1px solid #4f4f51;
146
+ }
147
+ p {
148
+ color: #c4c4c5;
149
+ margin: 0 0 1.5rem;
150
+ line-height: 1.5;
151
+ }
152
+ .error-details {
153
+ text-align: left;
154
+ background: hsl(0deg, 0%, 19%);
155
+ padding: 1rem;
156
+ border-radius: 6px;
157
+ margin: 1rem 0;
158
+ border-left: 4px solid #f87171;
159
+ }
160
+ .error-details strong {
161
+ display: block;
162
+ color: #ebebec;
163
+ margin-bottom: 0.5rem;
164
+ }
165
+ .close-button {
166
+ background: #636365;
167
+ color: #ebebec;
168
+ border: none;
169
+ padding: 0.75rem 1.5rem;
170
+ border-radius: 6px;
171
+ font-size: 1rem;
172
+ cursor: pointer;
173
+ transition: background-color 0.2s;
174
+ }
175
+ .close-button:hover {
176
+ background: #767678;
177
+ }
178
+ .retry-link {
179
+ color: #60a5fa;
180
+ text-decoration: none;
181
+ margin-left: 1rem;
182
+ }
183
+ .retry-link:hover {
184
+ text-decoration: underline;
185
+ }
186
+ </style>
187
+ </head>
188
+ <body>
189
+ <div class="container">
190
+ <div class="error-icon">
191
+ <span class="x-mark">✕</span>
192
+ </div>
193
+ <h1>Authorization Failed</h1>
194
+ <div class="error-code">{{error}}</div>
195
+ <p>The authorization request could not be completed.</p>
196
+
197
+ {{#if error_description}}
198
+ <div class="error-details">
199
+ <strong>Error Details:</strong>
200
+ {{error_description}}
201
+ </div>
202
+ {{/if}}
203
+
204
+ {{#if error_uri}}
205
+ <p>
206
+ <a href="{{error_uri}}" target="_blank" class="retry-link">
207
+ More information about this error
208
+ </a>
209
+ </p>
210
+ {{/if}}
211
+
212
+ <button class="close-button" onclick="window.close()">Close Window</button>
213
+ <a href="javascript:history.back()" class="retry-link">Try Again</a>
214
+ </div>
215
+ </body>
216
+ </html>`;
217
+
218
+ /**
219
+ * Render HTML template with parameter substitution
220
+ */
221
+ export function renderTemplate(
222
+ template: string,
223
+ params: Record<string, string | undefined>
224
+ ): string {
225
+ let rendered = template;
226
+
227
+ // Simple placeholder replacement
228
+ for (const [key, value] of Object.entries(params)) {
229
+ const placeholder = `{{${key}}}`;
230
+
231
+ rendered = rendered.replace(
232
+ new RegExp(placeholder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'),
233
+ value || ''
234
+ );
235
+ }
236
+
237
+ // Handle conditional blocks
238
+ rendered = rendered.replace(
239
+ /{{#if (\w+)}}(.*?){{\/if}}/gs,
240
+ (match, condition, content) => {
241
+ return params[condition] ? content : '';
242
+ }
243
+ );
244
+
245
+ return rendered;
246
+ }
247
+
248
+ /**
249
+ * Generate success page HTML
250
+ */
251
+ export function renderSuccessPage(customTemplate?: string): string {
252
+ return customTemplate || SUCCESS_TEMPLATE;
253
+ }
254
+
255
+ /**
256
+ * Generate error page HTML with error details
257
+ */
258
+ export function renderErrorPage(
259
+ error?: string,
260
+ errorDescription?: string,
261
+ errorUri?: string,
262
+ customTemplate?: string
263
+ ): string {
264
+ const template = customTemplate || ERROR_TEMPLATE;
265
+
266
+ return renderTemplate(template, {
267
+ error: error || 'unknown_error',
268
+ error_description: errorDescription,
269
+ error_uri: errorUri,
270
+ });
271
+ }