Skip to content

Commit 1a7749d

Browse files
committed
refactor(auth): replace AUTH_MODE with ENABLE_AUTH for streamlined authentication logic
1 parent ec1de9c commit 1a7749d

File tree

3 files changed

+54
-74
lines changed

3 files changed

+54
-74
lines changed

src/auth/index.ts

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,45 +4,29 @@ import { getConfig } from "../config.ts";
44
import { logger } from "../logger.ts";
55

66
/**
7-
* Initialize authentication based on AUTH_MODE
7+
* Initialize authentication based on ENABLE_AUTH
88
*/
99
export function initializeAuth() {
1010
const config = getConfig();
1111

12-
if (config.AUTH_MODE === "none") {
12+
if (!config.ENABLE_AUTH) {
1313
logger.info("Authentication is disabled");
1414
return { tokenValidator: null };
1515
}
1616

17-
if (config.AUTH_MODE === "resource_server") {
18-
logger.info("Initializing OAuth resource server mode");
19-
20-
// Resource server mode: only validate tokens from external OAuth provider
21-
const tokenValidator = new OAuthTokenValidator(
22-
config.OAUTH_ISSUER!,
23-
config.OAUTH_AUDIENCE
24-
);
25-
26-
return { tokenValidator };
27-
}
28-
29-
if (config.AUTH_MODE === "full") {
30-
logger.info("Initializing OAuth full mode with external IdP delegation", {
31-
issuer: config.OAUTH_ISSUER,
32-
audience: config.OAUTH_AUDIENCE,
33-
clientId: config.OAUTH_CLIENT_ID
34-
});
35-
36-
// Full mode: OAuth client that delegates to external IdP + resource server capabilities
37-
// For MCP API token validation, we need to validate OUR tokens, not external IdP tokens
38-
// The tokens we issue to MCP clients are from our OAuthProvider, not the external IdP
39-
40-
// We'll create a custom validator that validates our own issued tokens
41-
// This needs to be handled differently - we'll return null and handle it in the middleware
42-
return { tokenValidator: null };
43-
}
44-
45-
throw new Error(`Unknown AUTH_MODE: ${config.AUTH_MODE}`);
17+
logger.info("Initializing OAuth 2.1 authentication with token validation", {
18+
issuer: config.OAUTH_ISSUER,
19+
audience: config.OAUTH_AUDIENCE,
20+
clientId: config.OAUTH_CLIENT_ID
21+
});
22+
23+
// Create token validator for OAuth 2.1 token validation
24+
const tokenValidator = new OAuthTokenValidator(
25+
config.OAUTH_ISSUER!,
26+
config.OAUTH_AUDIENCE
27+
);
28+
29+
return { tokenValidator };
4630
}
4731

4832
/**
@@ -55,6 +39,5 @@ export function createAuthenticationMiddleware() {
5539
return (_req: any, _res: any, next: any) => next();
5640
}
5741

58-
// For full and resource_server modes, use token validator
5942
return createAuthMiddleware(tokenValidator);
6043
}

src/config.ts

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ const configSchema = z.object({
1010
LOG_LEVEL: z.enum(["error", "warn", "info", "debug"]).default("info"),
1111

1212
BASE_URL: z.string().optional(),
13-
AUTH_MODE: z.enum(["none", "full", "resource_server"]).default("none"),
13+
ENABLE_AUTH: z
14+
.string()
15+
.optional()
16+
.default("false")
17+
.transform((val) => val === "true"),
1418

15-
// OAuth configuration for external IdP integration
19+
// OAuth configuration - required when ENABLE_AUTH=true
1620
OAUTH_ISSUER: z.string().optional(),
1721
OAUTH_CLIENT_ID: z.string().optional(),
1822
OAUTH_CLIENT_SECRET: z.string().optional(),
@@ -36,55 +40,43 @@ export function getConfig(): Config {
3640
parsed.BASE_URL = `http://localhost:${parsed.PORT}`;
3741
}
3842

39-
// Full mode validation - OAuth Authorization Server with external IdP
40-
if (parsed.AUTH_MODE === "full") {
43+
// Log authentication status for clarity
44+
console.log(`🔐 Authentication: ${parsed.ENABLE_AUTH ? 'ENABLED' : 'DISABLED'}`);
45+
46+
// OAuth validation when authentication is enabled
47+
if (parsed.ENABLE_AUTH) {
4148
const requiredVars = [];
4249
if (!parsed.OAUTH_ISSUER) requiredVars.push("OAUTH_ISSUER");
4350
if (!parsed.OAUTH_CLIENT_ID) requiredVars.push("OAUTH_CLIENT_ID");
4451
if (!parsed.OAUTH_CLIENT_SECRET)
4552
requiredVars.push("OAUTH_CLIENT_SECRET");
4653

47-
// Provide default for OAUTH_REDIRECT_URI if not set
48-
if (!parsed.OAUTH_REDIRECT_URI) {
49-
const callbackUrl = new URL("/callback", parsed.BASE_URL);
50-
parsed.OAUTH_REDIRECT_URI = callbackUrl.toString();
51-
console.log(
52-
`⚠️ OAUTH_REDIRECT_URI not set, using default: ${parsed.OAUTH_REDIRECT_URI}`,
53-
);
54-
}
55-
5654
if (requiredVars.length > 0) {
5755
throw new Error(
58-
`AUTH_MODE=full requires OAuth configuration. Missing: ${requiredVars.join(", ")}\n` +
56+
`ENABLE_AUTH=true requires OAuth configuration. Missing: ${requiredVars.join(", ")}\n` +
5957
"Example configuration:\n" +
58+
"ENABLE_AUTH=true\n" +
6059
"OAUTH_ISSUER=https://your-domain.auth0.com\n" +
6160
"OAUTH_CLIENT_ID=your-client-id\n" +
6261
"OAUTH_CLIENT_SECRET=your-client-secret\n" +
63-
"OAUTH_REDIRECT_URI=http://localhost:3000/callback # Optional, defaults to BASE_URL/callback or http://localhost:PORT/callback\n" +
64-
"OAUTH_AUDIENCE=your-api-identifier # Optional but recommended",
62+
"OAUTH_AUDIENCE=your-api-identifier # Optional but recommended for production",
6563
);
6664
}
6765

68-
// OAUTH_AUDIENCE is optional but recommended when a resource server is used
69-
if (!parsed.OAUTH_AUDIENCE) {
70-
console.warn(
71-
"⚠️ OAUTH_AUDIENCE not set for full mode. Token validation will not check audience.\n" +
72-
" For production deployments, consider setting OAUTH_AUDIENCE to your API identifier",
66+
// Provide default for OAUTH_REDIRECT_URI if not set
67+
if (!parsed.OAUTH_REDIRECT_URI) {
68+
const callbackUrl = new URL("/callback", parsed.BASE_URL);
69+
parsed.OAUTH_REDIRECT_URI = callbackUrl.toString();
70+
console.log(
71+
`ℹ️ OAUTH_REDIRECT_URI not set, using default: ${parsed.OAUTH_REDIRECT_URI}`,
7372
);
7473
}
75-
}
76-
77-
if (parsed.AUTH_MODE === "resource_server") {
78-
const requiredVars = [];
79-
if (!parsed.OAUTH_ISSUER) requiredVars.push("OAUTH_ISSUER");
80-
if (!parsed.OAUTH_AUDIENCE) requiredVars.push("OAUTH_AUDIENCE");
8174

82-
if (requiredVars.length > 0) {
83-
throw new Error(
84-
`AUTH_MODE=resource_server requires OAuth configuration. Missing: ${requiredVars.join(", ")}\n` +
85-
"Example configuration:\n" +
86-
"OAUTH_ISSUER=https://your-domain.auth0.com\n" +
87-
"OAUTH_AUDIENCE=your-api-identifier",
75+
// OAUTH_AUDIENCE is optional but recommended for production
76+
if (!parsed.OAUTH_AUDIENCE) {
77+
console.warn(
78+
"⚠️ OAUTH_AUDIENCE not set. Token validation will not check audience.\n" +
79+
" For production deployments, consider setting OAUTH_AUDIENCE to your API identifier",
8880
);
8981
}
9082
}

src/index.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ const mcpHandler = async (req: express.Request, res: express.Response) => {
102102
const config = getConfig();
103103
const capabilities = ["tools"];
104104

105-
if (config.AUTH_MODE !== "none") {
105+
if (config.ENABLE_AUTH) {
106106
capabilities.push("oauth");
107107
}
108108

@@ -111,7 +111,7 @@ const mcpHandler = async (req: express.Request, res: express.Response) => {
111111
version: config.SERVER_VERSION,
112112
description: "TypeScript template for building MCP servers",
113113
capabilities,
114-
...(config.AUTH_MODE !== "none" && {
114+
...(config.ENABLE_AUTH && {
115115
oauth: {
116116
authorization_server: new URL("/.well-known/oauth-authorization-server", config.BASE_URL).toString(),
117117
protected_resource: new URL("/.well-known/oauth-protected-resource", config.BASE_URL).toString(),
@@ -132,7 +132,8 @@ const mcpHandler = async (req: express.Request, res: express.Response) => {
132132
const config = getConfig();
133133
let oauthProvider: OAuthProvider | null = null;
134134

135-
if (config.AUTH_MODE === "full") {
135+
// Setup OAuth endpoints and provider when authentication is enabled
136+
if (config.ENABLE_AUTH) {
136137
const baseUrl = config.BASE_URL;
137138
oauthProvider = new OAuthProvider({
138139
clientId: "mcp-client",
@@ -154,24 +155,28 @@ if (config.AUTH_MODE === "full") {
154155
app.get(redirectPath, createCallbackHandler(oauthProvider));
155156
app.post("/oauth/token", express.urlencoded({ extended: true }), createTokenHandler(oauthProvider));
156157

157-
logger.info("OAuth 2.1 client delegation endpoints registered for full auth mode", {
158+
logger.info("OAuth 2.1 endpoints registered", {
158159
discovery: [
159160
"/.well-known/oauth-authorization-server",
160161
"/.well-known/oauth-protected-resource",
161162
"/.well-known/openid_configuration"
162163
],
163164
endpoints: ["/oauth/authorize", redirectPath, "/oauth/token"],
164-
externalIdP: config.OAUTH_ISSUER
165+
issuer: config.OAUTH_ISSUER
165166
});
166167
}
167168

169+
// Setup authentication middleware
168170
let authMiddleware;
169-
if (config.AUTH_MODE === "full" && oauthProvider) {
171+
if (config.ENABLE_AUTH && oauthProvider) {
170172
authMiddleware = createOAuthProviderAuthMiddleware(oauthProvider);
171-
logger.info("Using OAuthProvider authentication for MCP endpoints");
172-
} else {
173+
logger.info("Using OAuth 2.1 authentication for MCP endpoints");
174+
} else if (config.ENABLE_AUTH) {
173175
authMiddleware = createAuthenticationMiddleware();
174-
logger.info("Using standard authentication for MCP endpoints");
176+
logger.info("Using OAuth 2.1 token validation for MCP endpoints");
177+
} else {
178+
authMiddleware = (_req: any, _res: any, next: any) => next();
179+
logger.info("Authentication disabled - MCP endpoints are public");
175180
}
176181

177182
app.get("/mcp", mcpHandler);

0 commit comments

Comments
 (0)