@samanhappy/mcphub 0.10.3 → 0.10.5
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 +39 -1
- package/dist/config/index.js +24 -0
- package/dist/config/index.js.map +1 -1
- package/dist/constants/oauthServerDefaults.js +36 -0
- package/dist/constants/oauthServerDefaults.js.map +1 -0
- package/dist/controllers/oauthClientController.js +252 -0
- package/dist/controllers/oauthClientController.js.map +1 -0
- package/dist/controllers/oauthDynamicRegistrationController.js +479 -0
- package/dist/controllers/oauthDynamicRegistrationController.js.map +1 -0
- package/dist/controllers/oauthServerController.js +449 -0
- package/dist/controllers/oauthServerController.js.map +1 -0
- package/dist/controllers/openApiController.js +6 -3
- package/dist/controllers/openApiController.js.map +1 -1
- package/dist/controllers/serverController.js +116 -23
- package/dist/controllers/serverController.js.map +1 -1
- package/dist/middlewares/auth.js +23 -2
- package/dist/middlewares/auth.js.map +1 -1
- package/dist/middlewares/userContext.js +27 -11
- package/dist/middlewares/userContext.js.map +1 -1
- package/dist/models/OAuth.js +291 -0
- package/dist/models/OAuth.js.map +1 -0
- package/dist/routes/index.js +25 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/server.js +4 -1
- package/dist/server.js.map +1 -1
- package/dist/services/dataServicex.js +3 -0
- package/dist/services/dataServicex.js.map +1 -1
- package/dist/services/oauthServerService.js +339 -0
- package/dist/services/oauthServerService.js.map +1 -0
- package/dist/services/sseService.js +413 -45
- package/dist/services/sseService.js.map +1 -1
- package/dist/utils/oauthBearer.js +35 -0
- package/dist/utils/oauthBearer.js.map +1 -0
- package/frontend/dist/assets/index-qg3ysGil.js +251 -0
- package/frontend/dist/assets/index-qg3ysGil.js.map +1 -0
- package/frontend/dist/index.html +1 -1
- package/mcp_settings.json +23 -1
- package/package.json +2 -1
- package/frontend/dist/assets/index-BpPaTvxv.js +0 -251
- package/frontend/dist/assets/index-BpPaTvxv.js.map +0 -1
package/README.md
CHANGED
|
@@ -19,7 +19,9 @@ MCPHub makes it easy to manage and scale multiple MCP (Model Context Protocol) s
|
|
|
19
19
|
- **Hot-Swappable Configuration**: Add, remove, or update MCP servers on the fly — no downtime required.
|
|
20
20
|
- **Group-Based Access Control**: Organize servers into customizable groups for streamlined permissions management.
|
|
21
21
|
- **Secure Authentication**: Built-in user management with role-based access powered by JWT and bcrypt.
|
|
22
|
-
- **OAuth 2.0 Support**:
|
|
22
|
+
- **OAuth 2.0 Support**:
|
|
23
|
+
- Full OAuth support for upstream MCP servers with proxy authorization capabilities
|
|
24
|
+
- **NEW**: Act as OAuth 2.0 authorization server for external clients (ChatGPT Web, custom apps)
|
|
23
25
|
- **Environment Variable Expansion**: Use environment variables anywhere in your configuration for secure credential management. See [Environment Variables Guide](docs/environment-variables.md).
|
|
24
26
|
- **Docker-Ready**: Deploy instantly with our containerized setup.
|
|
25
27
|
|
|
@@ -98,6 +100,42 @@ Manual registration example:
|
|
|
98
100
|
|
|
99
101
|
For manual providers, create the OAuth App in the upstream console, set the redirect URI to `http://localhost:3000/oauth/callback` (or your deployed domain), and then plug the credentials into the dashboard or config file.
|
|
100
102
|
|
|
103
|
+
#### OAuth Authorization Server (NEW)
|
|
104
|
+
|
|
105
|
+
MCPHub can now act as an OAuth 2.0 authorization server, allowing external applications to securely access your MCP servers using standard OAuth flows. This is particularly useful for integrating with ChatGPT Web and other services that require OAuth authentication.
|
|
106
|
+
|
|
107
|
+
**Enable OAuth Server:**
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"systemConfig": {
|
|
112
|
+
"oauthServer": {
|
|
113
|
+
"enabled": true,
|
|
114
|
+
"accessTokenLifetime": 3600,
|
|
115
|
+
"refreshTokenLifetime": 1209600,
|
|
116
|
+
"allowedScopes": ["read", "write"]
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"oauthClients": [
|
|
120
|
+
{
|
|
121
|
+
"clientId": "your-client-id",
|
|
122
|
+
"name": "ChatGPT Web",
|
|
123
|
+
"redirectUris": ["https://chatgpt.com/oauth/callback"],
|
|
124
|
+
"grants": ["authorization_code", "refresh_token"],
|
|
125
|
+
"scopes": ["read", "write"]
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Key Features:**
|
|
132
|
+
- Standard OAuth 2.0 authorization code flow
|
|
133
|
+
- PKCE support for enhanced security
|
|
134
|
+
- Token refresh capabilities
|
|
135
|
+
- Compatible with ChatGPT Web and other OAuth clients
|
|
136
|
+
|
|
137
|
+
For detailed setup instructions, see the [OAuth Server Documentation](docs/oauth-server.md).
|
|
138
|
+
|
|
101
139
|
### Docker Deployment
|
|
102
140
|
|
|
103
141
|
**Recommended**: Mount your custom config:
|
package/dist/config/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import fs from 'fs';
|
|
|
3
3
|
import { getConfigFilePath } from '../utils/path.js';
|
|
4
4
|
import { getPackageVersion } from '../utils/version.js';
|
|
5
5
|
import { getDataService } from '../services/services.js';
|
|
6
|
+
import { cloneDefaultOAuthServerConfig } from '../constants/oauthServerDefaults.js';
|
|
6
7
|
dotenv.config();
|
|
7
8
|
const defaultConfig = {
|
|
8
9
|
port: process.env.PORT || 3000,
|
|
@@ -13,6 +14,19 @@ const defaultConfig = {
|
|
|
13
14
|
mcpHubVersion: getPackageVersion(),
|
|
14
15
|
};
|
|
15
16
|
const dataService = getDataService();
|
|
17
|
+
const ensureOAuthServerDefaults = (settings) => {
|
|
18
|
+
if (!settings.systemConfig) {
|
|
19
|
+
settings.systemConfig = {
|
|
20
|
+
oauthServer: cloneDefaultOAuthServerConfig(),
|
|
21
|
+
};
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
if (!settings.systemConfig.oauthServer) {
|
|
25
|
+
settings.systemConfig.oauthServer = cloneDefaultOAuthServerConfig();
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
};
|
|
16
30
|
// Settings cache
|
|
17
31
|
let settingsCache = null;
|
|
18
32
|
export const getSettingsPath = () => {
|
|
@@ -28,6 +42,7 @@ export const loadOriginalSettings = () => {
|
|
|
28
42
|
if (!fs.existsSync(settingsPath)) {
|
|
29
43
|
console.warn(`Settings file not found at ${settingsPath}, using default settings.`);
|
|
30
44
|
const defaultSettings = { mcpServers: {}, users: [] };
|
|
45
|
+
ensureOAuthServerDefaults(defaultSettings);
|
|
31
46
|
// Cache default settings
|
|
32
47
|
settingsCache = defaultSettings;
|
|
33
48
|
return defaultSettings;
|
|
@@ -36,6 +51,15 @@ export const loadOriginalSettings = () => {
|
|
|
36
51
|
// Read and parse settings file
|
|
37
52
|
const settingsData = fs.readFileSync(settingsPath, 'utf8');
|
|
38
53
|
const settings = JSON.parse(settingsData);
|
|
54
|
+
const initialized = ensureOAuthServerDefaults(settings);
|
|
55
|
+
if (initialized) {
|
|
56
|
+
try {
|
|
57
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
58
|
+
}
|
|
59
|
+
catch (writeError) {
|
|
60
|
+
console.error('Failed to persist default OAuth server configuration:', writeError);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
39
63
|
// Update cache
|
|
40
64
|
settingsCache = settings;
|
|
41
65
|
console.log(`Loaded settings from ${settingsPath}`);
|
package/dist/config/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const DEFAULT_OAUTH_SERVER_CONFIG = {
|
|
2
|
+
enabled: true,
|
|
3
|
+
accessTokenLifetime: 3600,
|
|
4
|
+
refreshTokenLifetime: 1209600,
|
|
5
|
+
authorizationCodeLifetime: 300,
|
|
6
|
+
requireClientSecret: false,
|
|
7
|
+
allowedScopes: ['read', 'write'],
|
|
8
|
+
requireState: false,
|
|
9
|
+
dynamicRegistration: {
|
|
10
|
+
enabled: true,
|
|
11
|
+
allowedGrantTypes: ['authorization_code', 'refresh_token'],
|
|
12
|
+
requiresAuthentication: false,
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
export const cloneDefaultOAuthServerConfig = () => {
|
|
16
|
+
const allowedScopes = DEFAULT_OAUTH_SERVER_CONFIG.allowedScopes
|
|
17
|
+
? [...DEFAULT_OAUTH_SERVER_CONFIG.allowedScopes]
|
|
18
|
+
: [];
|
|
19
|
+
const baseDynamicRegistration = DEFAULT_OAUTH_SERVER_CONFIG.dynamicRegistration ?? {
|
|
20
|
+
enabled: false,
|
|
21
|
+
allowedGrantTypes: [],
|
|
22
|
+
requiresAuthentication: false,
|
|
23
|
+
};
|
|
24
|
+
const dynamicRegistration = {
|
|
25
|
+
...baseDynamicRegistration,
|
|
26
|
+
allowedGrantTypes: baseDynamicRegistration.allowedGrantTypes
|
|
27
|
+
? [...baseDynamicRegistration.allowedGrantTypes]
|
|
28
|
+
: [],
|
|
29
|
+
};
|
|
30
|
+
return {
|
|
31
|
+
...DEFAULT_OAUTH_SERVER_CONFIG,
|
|
32
|
+
allowedScopes,
|
|
33
|
+
dynamicRegistration,
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=oauthServerDefaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauthServerDefaults.js","sourceRoot":"","sources":["../../src/constants/oauthServerDefaults.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,2BAA2B,GAAsB;IAC5D,OAAO,EAAE,IAAI;IACb,mBAAmB,EAAE,IAAI;IACzB,oBAAoB,EAAE,OAAO;IAC7B,yBAAyB,EAAE,GAAG;IAC9B,mBAAmB,EAAE,KAAK;IAC1B,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;IAChC,YAAY,EAAE,KAAK;IACnB,mBAAmB,EAAE;QACnB,OAAO,EAAE,IAAI;QACb,iBAAiB,EAAE,CAAC,oBAAoB,EAAE,eAAe,CAAC;QAC1D,sBAAsB,EAAE,KAAK;KAC9B;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAsB,EAAE;IACnE,MAAM,aAAa,GAAG,2BAA2B,CAAC,aAAa;QAC7D,CAAC,CAAC,CAAC,GAAG,2BAA2B,CAAC,aAAa,CAAC;QAChD,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,uBAAuB,GAC3B,2BAA2B,CAAC,mBAAmB,IAAI;QACjD,OAAO,EAAE,KAAK;QACd,iBAAiB,EAAE,EAAE;QACrB,sBAAsB,EAAE,KAAK;KAC9B,CAAC;IAEJ,MAAM,mBAAmB,GAAG;QAC1B,GAAG,uBAAuB;QAC1B,iBAAiB,EAAE,uBAAuB,CAAC,iBAAiB;YAC1D,CAAC,CAAC,CAAC,GAAG,uBAAuB,CAAC,iBAAiB,CAAC;YAChD,CAAC,CAAC,EAAE;KACP,CAAC;IAEF,OAAO;QACL,GAAG,2BAA2B;QAC9B,aAAa;QACb,mBAAmB;KACpB,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { validationResult } from 'express-validator';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { getOAuthClients, findOAuthClientById, createOAuthClient, updateOAuthClient, deleteOAuthClient, } from '../models/OAuth.js';
|
|
4
|
+
/**
|
|
5
|
+
* GET /api/oauth/clients
|
|
6
|
+
* Get all OAuth clients
|
|
7
|
+
*/
|
|
8
|
+
export const getAllClients = (req, res) => {
|
|
9
|
+
try {
|
|
10
|
+
const clients = getOAuthClients();
|
|
11
|
+
// Don't expose client secrets in the list
|
|
12
|
+
const sanitizedClients = clients.map((client) => ({
|
|
13
|
+
clientId: client.clientId,
|
|
14
|
+
name: client.name,
|
|
15
|
+
redirectUris: client.redirectUris,
|
|
16
|
+
grants: client.grants,
|
|
17
|
+
scopes: client.scopes,
|
|
18
|
+
owner: client.owner,
|
|
19
|
+
}));
|
|
20
|
+
res.json({
|
|
21
|
+
success: true,
|
|
22
|
+
clients: sanitizedClients,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
console.error('Get OAuth clients error:', error);
|
|
27
|
+
res.status(500).json({
|
|
28
|
+
success: false,
|
|
29
|
+
message: 'Failed to retrieve OAuth clients',
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* GET /api/oauth/clients/:clientId
|
|
35
|
+
* Get a specific OAuth client
|
|
36
|
+
*/
|
|
37
|
+
export const getClient = (req, res) => {
|
|
38
|
+
try {
|
|
39
|
+
const { clientId } = req.params;
|
|
40
|
+
const client = findOAuthClientById(clientId);
|
|
41
|
+
if (!client) {
|
|
42
|
+
res.status(404).json({
|
|
43
|
+
success: false,
|
|
44
|
+
message: 'OAuth client not found',
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// Don't expose client secret
|
|
49
|
+
const sanitizedClient = {
|
|
50
|
+
clientId: client.clientId,
|
|
51
|
+
name: client.name,
|
|
52
|
+
redirectUris: client.redirectUris,
|
|
53
|
+
grants: client.grants,
|
|
54
|
+
scopes: client.scopes,
|
|
55
|
+
owner: client.owner,
|
|
56
|
+
};
|
|
57
|
+
res.json({
|
|
58
|
+
success: true,
|
|
59
|
+
client: sanitizedClient,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error('Get OAuth client error:', error);
|
|
64
|
+
res.status(500).json({
|
|
65
|
+
success: false,
|
|
66
|
+
message: 'Failed to retrieve OAuth client',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* POST /api/oauth/clients
|
|
72
|
+
* Create a new OAuth client
|
|
73
|
+
*/
|
|
74
|
+
export const createClient = (req, res) => {
|
|
75
|
+
try {
|
|
76
|
+
// Validate request
|
|
77
|
+
const errors = validationResult(req);
|
|
78
|
+
if (!errors.isEmpty()) {
|
|
79
|
+
res.status(400).json({
|
|
80
|
+
success: false,
|
|
81
|
+
message: 'Validation failed',
|
|
82
|
+
errors: errors.array(),
|
|
83
|
+
});
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const { name, redirectUris, grants, scopes, requireSecret } = req.body;
|
|
87
|
+
const user = req.user;
|
|
88
|
+
// Generate client ID
|
|
89
|
+
const clientId = crypto.randomBytes(16).toString('hex');
|
|
90
|
+
// Generate client secret if required
|
|
91
|
+
const clientSecret = requireSecret !== false ? crypto.randomBytes(32).toString('hex') : undefined;
|
|
92
|
+
// Create client
|
|
93
|
+
const client = {
|
|
94
|
+
clientId,
|
|
95
|
+
clientSecret,
|
|
96
|
+
name,
|
|
97
|
+
redirectUris: Array.isArray(redirectUris) ? redirectUris : [redirectUris],
|
|
98
|
+
grants: grants || ['authorization_code', 'refresh_token'],
|
|
99
|
+
scopes: scopes || ['read', 'write'],
|
|
100
|
+
owner: user?.username || 'admin',
|
|
101
|
+
};
|
|
102
|
+
const createdClient = createOAuthClient(client);
|
|
103
|
+
// Return client with secret (only shown once)
|
|
104
|
+
res.status(201).json({
|
|
105
|
+
success: true,
|
|
106
|
+
message: 'OAuth client created successfully',
|
|
107
|
+
client: {
|
|
108
|
+
clientId: createdClient.clientId,
|
|
109
|
+
clientSecret: createdClient.clientSecret,
|
|
110
|
+
name: createdClient.name,
|
|
111
|
+
redirectUris: createdClient.redirectUris,
|
|
112
|
+
grants: createdClient.grants,
|
|
113
|
+
scopes: createdClient.scopes,
|
|
114
|
+
owner: createdClient.owner,
|
|
115
|
+
},
|
|
116
|
+
warning: clientSecret
|
|
117
|
+
? 'Client secret is only shown once. Please save it securely.'
|
|
118
|
+
: undefined,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
console.error('Create OAuth client error:', error);
|
|
123
|
+
if (error instanceof Error && error.message.includes('already exists')) {
|
|
124
|
+
res.status(409).json({
|
|
125
|
+
success: false,
|
|
126
|
+
message: error.message,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
res.status(500).json({
|
|
131
|
+
success: false,
|
|
132
|
+
message: 'Failed to create OAuth client',
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* PUT /api/oauth/clients/:clientId
|
|
139
|
+
* Update an OAuth client
|
|
140
|
+
*/
|
|
141
|
+
export const updateClient = (req, res) => {
|
|
142
|
+
try {
|
|
143
|
+
const { clientId } = req.params;
|
|
144
|
+
const { name, redirectUris, grants, scopes } = req.body;
|
|
145
|
+
const updates = {};
|
|
146
|
+
if (name)
|
|
147
|
+
updates.name = name;
|
|
148
|
+
if (redirectUris)
|
|
149
|
+
updates.redirectUris = Array.isArray(redirectUris) ? redirectUris : [redirectUris];
|
|
150
|
+
if (grants)
|
|
151
|
+
updates.grants = grants;
|
|
152
|
+
if (scopes)
|
|
153
|
+
updates.scopes = scopes;
|
|
154
|
+
const updatedClient = updateOAuthClient(clientId, updates);
|
|
155
|
+
if (!updatedClient) {
|
|
156
|
+
res.status(404).json({
|
|
157
|
+
success: false,
|
|
158
|
+
message: 'OAuth client not found',
|
|
159
|
+
});
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
// Don't expose client secret
|
|
163
|
+
res.json({
|
|
164
|
+
success: true,
|
|
165
|
+
message: 'OAuth client updated successfully',
|
|
166
|
+
client: {
|
|
167
|
+
clientId: updatedClient.clientId,
|
|
168
|
+
name: updatedClient.name,
|
|
169
|
+
redirectUris: updatedClient.redirectUris,
|
|
170
|
+
grants: updatedClient.grants,
|
|
171
|
+
scopes: updatedClient.scopes,
|
|
172
|
+
owner: updatedClient.owner,
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
console.error('Update OAuth client error:', error);
|
|
178
|
+
res.status(500).json({
|
|
179
|
+
success: false,
|
|
180
|
+
message: 'Failed to update OAuth client',
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* DELETE /api/oauth/clients/:clientId
|
|
186
|
+
* Delete an OAuth client
|
|
187
|
+
*/
|
|
188
|
+
export const deleteClient = (req, res) => {
|
|
189
|
+
try {
|
|
190
|
+
const { clientId } = req.params;
|
|
191
|
+
const deleted = deleteOAuthClient(clientId);
|
|
192
|
+
if (!deleted) {
|
|
193
|
+
res.status(404).json({
|
|
194
|
+
success: false,
|
|
195
|
+
message: 'OAuth client not found',
|
|
196
|
+
});
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
res.json({
|
|
200
|
+
success: true,
|
|
201
|
+
message: 'OAuth client deleted successfully',
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
console.error('Delete OAuth client error:', error);
|
|
206
|
+
res.status(500).json({
|
|
207
|
+
success: false,
|
|
208
|
+
message: 'Failed to delete OAuth client',
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* POST /api/oauth/clients/:clientId/regenerate-secret
|
|
214
|
+
* Regenerate client secret
|
|
215
|
+
*/
|
|
216
|
+
export const regenerateSecret = (req, res) => {
|
|
217
|
+
try {
|
|
218
|
+
const { clientId } = req.params;
|
|
219
|
+
const client = findOAuthClientById(clientId);
|
|
220
|
+
if (!client) {
|
|
221
|
+
res.status(404).json({
|
|
222
|
+
success: false,
|
|
223
|
+
message: 'OAuth client not found',
|
|
224
|
+
});
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// Generate new secret
|
|
228
|
+
const newSecret = crypto.randomBytes(32).toString('hex');
|
|
229
|
+
const updatedClient = updateOAuthClient(clientId, { clientSecret: newSecret });
|
|
230
|
+
if (!updatedClient) {
|
|
231
|
+
res.status(500).json({
|
|
232
|
+
success: false,
|
|
233
|
+
message: 'Failed to regenerate client secret',
|
|
234
|
+
});
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
res.json({
|
|
238
|
+
success: true,
|
|
239
|
+
message: 'Client secret regenerated successfully',
|
|
240
|
+
clientSecret: newSecret,
|
|
241
|
+
warning: 'Client secret is only shown once. Please save it securely.',
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
console.error('Regenerate secret error:', error);
|
|
246
|
+
res.status(500).json({
|
|
247
|
+
success: false,
|
|
248
|
+
message: 'Failed to regenerate client secret',
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
//# sourceMappingURL=oauthClientController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauthClientController.js","sourceRoot":"","sources":["../../src/controllers/oauthClientController.ts"],"names":[],"mappings":"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"}
|