Skip to content

Commit b4851d1

Browse files
dgellowclaude
andcommitted
Implement multi-IDP support with provider abstraction
Replaces Google-specific OAuth with a provider abstraction pattern supporting Google, Azure AD, GitHub, and generic OIDC providers. Changes: - Create internal/idp package with Provider interface and implementations - Update config from googleClientId/googleClientSecret to structured idp block - Add provider tracking to browser session cookies for multi-IDP readiness - Delete internal/googleauth package - Add comprehensive tests for idp package (including GitHub UserInfo tests) - Update all example configs and documentation - Refactor parseIDPConfig to use helper function for cleaner code Config format change: "idp": { "provider": "google|azure|github|oidc", "clientId": "...", "clientSecret": {"$env": "..."}, "redirectUri": "...", // Provider-specific: tenantId (azure), allowedOrgs (github), discoveryUrl (oidc) } Co-authored-by: Claude <[email protected]>
1 parent 9839592 commit b4851d1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2187
-641
lines changed

cmd/mcp-front/main.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,20 @@ func generateDefaultConfig(path string) error {
2222
"addr": ":8080",
2323
"name": "mcp-front",
2424
"auth": map[string]any{
25-
"kind": "oauth",
26-
"issuer": "https://mcp.yourcompany.com",
27-
"allowedDomains": []string{"yourcompany.com"},
28-
"allowedOrigins": []string{"https://claude.ai"},
29-
"tokenTtl": "24h",
30-
"storage": "memory",
31-
"googleClientId": map[string]string{"$env": "GOOGLE_CLIENT_ID"},
32-
"googleClientSecret": map[string]string{"$env": "GOOGLE_CLIENT_SECRET"},
33-
"googleRedirectUri": "https://mcp.yourcompany.com/oauth/callback",
34-
"jwtSecret": map[string]string{"$env": "JWT_SECRET"},
35-
"encryptionKey": map[string]string{"$env": "ENCRYPTION_KEY"},
25+
"kind": "oauth",
26+
"issuer": "https://mcp.yourcompany.com",
27+
"allowedDomains": []string{"yourcompany.com"},
28+
"allowedOrigins": []string{"https://claude.ai"},
29+
"tokenTtl": "24h",
30+
"storage": "memory",
31+
"idp": map[string]any{
32+
"provider": "google",
33+
"clientId": map[string]string{"$env": "GOOGLE_CLIENT_ID"},
34+
"clientSecret": map[string]string{"$env": "GOOGLE_CLIENT_SECRET"},
35+
"redirectUri": "https://mcp.yourcompany.com/oauth/callback",
36+
},
37+
"jwtSecret": map[string]string{"$env": "JWT_SECRET"},
38+
"encryptionKey": map[string]string{"$env": "ENCRYPTION_KEY"},
3639
},
3740
},
3841
"mcpServers": map[string]any{

config-admin-example.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
"auth": {
88
"kind": "oauth",
99
"issuer": "https://mcp.example.com",
10+
"idp": {
11+
"provider": "google",
12+
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
13+
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
14+
"redirectUri": "https://mcp.example.com/oauth/callback"
15+
},
1016
"allowedDomains": ["example.com"],
1117
"allowedOrigins": ["https://claude.ai"],
1218
"tokenTtl": "1h",
1319
"storage": "memory",
14-
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
15-
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
16-
"googleRedirectUri": "https://mcp.example.com/oauth/callback",
1720
"jwtSecret": {"$env": "JWT_SECRET"},
1821
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
1922
},

config-inline-example.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
"auth": {
88
"kind": "oauth",
99
"issuer": "https://mcp.example.com",
10+
"idp": {
11+
"provider": "google",
12+
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
13+
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
14+
"redirectUri": "https://mcp.example.com/oauth/callback"
15+
},
1016
"allowedDomains": ["example.com"],
1117
"allowedOrigins": ["https://claude.ai"],
1218
"tokenTtl": "1h",
1319
"storage": "memory",
14-
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
15-
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
16-
"googleRedirectUri": "https://mcp.example.com/oauth/callback",
1720
"jwtSecret": {"$env": "JWT_SECRET"},
1821
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
1922
}

config-inline-test.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
"auth": {
88
"kind": "oauth",
99
"issuer": "http://localhost:8080",
10+
"idp": {
11+
"provider": "google",
12+
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
13+
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
14+
"redirectUri": "http://localhost:8080/oauth/callback"
15+
},
1016
"allowedDomains": ["gmail.com"],
1117
"allowedOrigins": ["https://claude.ai"],
1218
"tokenTtl": "1h",
1319
"storage": "memory",
14-
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
15-
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
16-
"googleRedirectUri": "http://localhost:8080/oauth/callback",
1720
"jwtSecret": {"$env": "JWT_SECRET"},
1821
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
1922
}

config-oauth-firestore.example.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
"kind": "oauth",
99
"issuer": {"$env": "OAUTH_ISSUER"},
1010
"gcpProject": {"$env": "GCP_PROJECT"},
11+
"idp": {
12+
"provider": "google",
13+
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
14+
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
15+
"redirectUri": {"$env": "GOOGLE_REDIRECT_URI"}
16+
},
1117
"allowedDomains": ["yourcompany.com", "contractors.yourcompany.com"],
1218
"allowedOrigins": ["https://claude.ai", "https://yourcompany.com"],
1319
"tokenTtl": "24h",
1420
"storage": "firestore",
15-
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
16-
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
17-
"googleRedirectUri": {"$env": "GOOGLE_REDIRECT_URI"},
1821
"jwtSecret": {"$env": "JWT_SECRET"},
1922
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
2023
}

config-oauth.example.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
"kind": "oauth",
99
"issuer": {"$env": "OAUTH_ISSUER"},
1010
"gcpProject": {"$env": "GCP_PROJECT"},
11+
"idp": {
12+
"provider": "google",
13+
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
14+
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
15+
"redirectUri": {"$env": "GOOGLE_REDIRECT_URI"}
16+
},
1117
"allowedDomains": ["yourcompany.com", "contractors.yourcompany.com"],
1218
"allowedOrigins": ["https://claude.ai", "https://yourcompany.com"],
1319
"tokenTtl": "24h",
1420
"storage": "memory",
15-
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
16-
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
17-
"googleRedirectUri": {"$env": "GOOGLE_REDIRECT_URI"},
1821
"jwtSecret": {"$env": "JWT_SECRET"},
1922
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
2023
}

config-oauth.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
"kind": "oauth",
99
"issuer": "https://mcp-internal.yourcompany.org",
1010
"gcpProject": {"$env": "GCP_PROJECT"},
11+
"idp": {
12+
"provider": "google",
13+
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
14+
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
15+
"redirectUri": "https://mcp-internal.yourcompany.org/oauth/callback"
16+
},
1117
"allowedDomains": ["yourcompany.com"],
1218
"allowedOrigins": ["https://claude.ai"],
1319
"tokenTtl": "24h",
1420
"storage": "memory",
15-
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
16-
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
17-
"googleRedirectUri": "https://mcp-internal.yourcompany.org/oauth/callback",
1821
"jwtSecret": {"$env": "JWT_SECRET"},
1922
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
2023
}

config-user-tokens-example.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
"kind": "oauth",
99
"issuer": {"$env": "OAUTH_ISSUER"},
1010
"gcpProject": {"$env": "GCP_PROJECT"},
11+
"idp": {
12+
"provider": "google",
13+
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
14+
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
15+
"redirectUri": {"$env": "GOOGLE_REDIRECT_URI"}
16+
},
1117
"allowedDomains": ["yourcompany.com"],
1218
"allowedOrigins": ["https://claude.ai"],
1319
"tokenTtl": "24h",
1420
"storage": "memory",
15-
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
16-
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
17-
"googleRedirectUri": {"$env": "GOOGLE_REDIRECT_URI"},
1821
"jwtSecret": {"$env": "JWT_SECRET"},
1922
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
2023
}

docs-site/src/content/docs/configuration.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,16 @@ For production, use OAuth with Google. Claude redirects users to Google for auth
4949
"auth": {
5050
"kind": "oauth",
5151
"issuer": "https://mcp.company.com",
52+
"idp": {
53+
"provider": "google",
54+
"clientId": { "$env": "GOOGLE_CLIENT_ID" },
55+
"clientSecret": { "$env": "GOOGLE_CLIENT_SECRET" },
56+
"redirectUri": "https://mcp.company.com/oauth/callback"
57+
},
5258
"allowedDomains": ["company.com"],
5359
"allowedOrigins": ["https://claude.ai"],
5460
"tokenTtl": "24h",
5561
"storage": "memory",
56-
"googleClientId": { "$env": "GOOGLE_CLIENT_ID" },
57-
"googleClientSecret": { "$env": "GOOGLE_CLIENT_SECRET" },
58-
"googleRedirectUri": "https://mcp.company.com/oauth/callback",
5962
"jwtSecret": { "$env": "JWT_SECRET" },
6063
"encryptionKey": { "$env": "ENCRYPTION_KEY" }
6164
}
@@ -66,7 +69,7 @@ The `issuer` should match your `baseURL`. `allowedDomains` restricts access to s
6669

6770
`tokenTtl` controls how long JWT tokens are valid. Shorter times are more secure but require more frequent logins.
6871

69-
Security requirements: `googleClientSecret`, `jwtSecret`, and `encryptionKey` must be environment variables. The JWT secret must be at least 32 bytes. The encryption key must be exactly 32 bytes.
72+
Security requirements: `idp.clientSecret`, `jwtSecret`, and `encryptionKey` must be environment variables. The JWT secret must be at least 32 bytes. The encryption key must be exactly 32 bytes.
7073

7174
For production, set `storage` to "firestore" and add `gcpProject`, `firestoreDatabase`, and `firestoreCollection` fields.
7275

@@ -345,13 +348,16 @@ Set `MCP_FRONT_ENV=development` when testing OAuth locally. It allows http:// UR
345348
"auth": {
346349
"kind": "oauth",
347350
"issuer": "https://mcp.company.com",
351+
"idp": {
352+
"provider": "google",
353+
"clientId": { "$env": "GOOGLE_CLIENT_ID" },
354+
"clientSecret": { "$env": "GOOGLE_CLIENT_SECRET" },
355+
"redirectUri": "https://mcp.company.com/oauth/callback"
356+
},
348357
"allowedDomains": ["company.com"],
349358
"allowedOrigins": ["https://claude.ai"],
350359
"tokenTtl": "4h",
351360
"storage": "firestore",
352-
"googleClientId": { "$env": "GOOGLE_CLIENT_ID" },
353-
"googleClientSecret": { "$env": "GOOGLE_CLIENT_SECRET" },
354-
"googleRedirectUri": "https://mcp.company.com/oauth/callback",
355361
"jwtSecret": { "$env": "JWT_SECRET" },
356362
"encryptionKey": { "$env": "ENCRYPTION_KEY" },
357363
"gcpProject": { "$env": "GOOGLE_CLOUD_PROJECT" },

docs-site/src/content/docs/examples/oauth-google.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,26 @@ Create `config.json`:
3939

4040
```json
4141
{
42-
"version": "1.0",
42+
"version": "v0.0.1-DEV_EDITION_EXPECT_CHANGES",
4343
"proxy": {
4444
"name": "Company MCP Proxy",
45-
"baseUrl": "https://mcp.company.com",
45+
"baseURL": "https://mcp.company.com",
4646
"addr": ":8080",
4747
"auth": {
4848
"kind": "oauth",
4949
"issuer": "https://mcp.company.com",
50-
"allowedDomains": ["company.com"]
50+
"idp": {
51+
"provider": "google",
52+
"clientId": { "$env": "GOOGLE_CLIENT_ID" },
53+
"clientSecret": { "$env": "GOOGLE_CLIENT_SECRET" },
54+
"redirectUri": "https://mcp.company.com/oauth/callback"
55+
},
56+
"allowedDomains": ["company.com"],
57+
"allowedOrigins": ["https://claude.ai"],
58+
"tokenTtl": "24h",
59+
"storage": "memory",
60+
"jwtSecret": { "$env": "JWT_SECRET" },
61+
"encryptionKey": { "$env": "ENCRYPTION_KEY" }
5162
}
5263
},
5364
"mcpServers": {
@@ -80,6 +91,7 @@ Create `config.json`:
8091
export GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"
8192
export GOOGLE_CLIENT_SECRET="your-client-secret"
8293
export JWT_SECRET=$(openssl rand -base64 32)
94+
export ENCRYPTION_KEY=$(openssl rand -base64 32)
8395
```
8496

8597
## 4. Run with Docker
@@ -89,6 +101,7 @@ docker run -p 8080:8080 \
89101
-e GOOGLE_CLIENT_ID \
90102
-e GOOGLE_CLIENT_SECRET \
91103
-e JWT_SECRET \
104+
-e ENCRYPTION_KEY \
92105
-v $(pwd)/config.json:/config.json \
93106
ghcr.io/dgellow/mcp-front:latest
94107
```

0 commit comments

Comments
 (0)