Skip to content

Commit 2d80129

Browse files
committed
docs: add multi-provider OAuth support and flexible storage options
- Add support and documentation for multiple OAuth providers: GitHub, GitLab, and Gitea - Introduce flexible storage options with both in-memory and Redis-backed persistence - Update instructions and examples to use the new oauth-server and oauth-client structure - Expand setup and usage sections with detailed steps for both development (memory store) and production (Redis store) environments - Add command-line flag documentation for server configuration, including new provider and storage options - Provide new curl examples for client registration and resource metadata endpoints - Clarify and generalize references to OAuth tokens instead of GitHub-specific tokens - Add links to additional documentation and relevant external resources Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
1 parent 3baaaa2 commit 2d80129

File tree

1 file changed

+156
-27
lines changed

1 file changed

+156
-27
lines changed

03-oauth-mcp/README.md

Lines changed: 156 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# OAuth MCP Server
22

3-
This project demonstrates an OAuth 2.0 protected [Model Context Protocol (MCP)](https://github.com/mark3labs/mcp-go) server written in Go. It integrates with GitHub as the OAuth provider and showcases authenticated MCP tool execution with token context propagation.
3+
This project demonstrates an OAuth 2.0 protected [Model Context Protocol (MCP)](https://github.com/mark3labs/mcp-go) server written in Go. It supports multiple OAuth providers (GitHub, GitLab, Gitea) and showcases authenticated MCP tool execution with token context propagation.
4+
5+
The implementation includes both an OAuth authorization server (`oauth-server/`) and an example OAuth client (`oauth-client/`), demonstrating the complete OAuth 2.0 flow with PKCE support and flexible storage options.
46

57
---
68

@@ -9,6 +11,7 @@ This project demonstrates an OAuth 2.0 protected [Model Context Protocol (MCP)](
911
The server provides:
1012

1113
- **Multi-Provider OAuth Integration**: Supports GitHub, GitLab, and Gitea as OAuth 2.0 providers for user authentication
14+
- **Flexible Storage Backends**: Choose between in-memory or Redis-backed storage for OAuth data persistence
1215
- **MCP Server with Authentication**: Requires valid OAuth tokens for all MCP endpoint access
1316
- **Context-based Token Propagation**: Injects and propagates authentication tokens through Go's `context.Context`
1417
- **Two Authenticated MCP Tools**:
@@ -169,64 +172,92 @@ flowchart TD
169172
1. Change to the server directory:
170173

171174
```bash
172-
cd 03-oauth-mcp/server
175+
cd 03-oauth-mcp/oauth-server
173176
```
174177

175178
2. Start the server with your OAuth credentials:
176179

177-
**GitHub (default):**
180+
**GitHub (default with memory store):**
181+
182+
```bash
183+
go run . -client_id="your-github-client-id" -client_secret="your-github-client-secret"
184+
```
185+
186+
**GitHub with Redis store:**
178187

179188
```bash
180-
go run server.go -client_id="your-github-client-id" -client_secret="your-github-client-secret"
189+
# Start Redis first
190+
docker run -d -p 6379:6379 redis:alpine
191+
192+
# Run server with Redis
193+
go run . -client_id="your-id" -client_secret="your-secret" -store redis -redis-addr localhost:6379
181194
```
182195

183196
**GitLab.com:**
184197

185198
```bash
186-
go run server.go -provider="gitlab" -client_id="your-gitlab-client-id" -client_secret="your-gitlab-client-secret"
199+
go run . -provider="gitlab" -client_id="your-gitlab-client-id" -client_secret="your-gitlab-client-secret"
187200
```
188201

189202
**Self-hosted GitLab:**
190203

191204
```bash
192-
go run server.go -provider="gitlab" -gitlab-host="https://gitlab.example.com" -client_id="your-client-id" -client_secret="your-client-secret"
205+
go run . -provider="gitlab" -gitlab-host="https://gitlab.example.com" -client_id="your-client-id" -client_secret="your-client-secret"
193206
```
194207

195208
**Gitea:**
196209

197210
```bash
198-
go run server.go -provider="gitea" -gitea-host="https://gitea.example.com" -client_id="your-client-id" -client_secret="your-client-secret"
211+
go run . -provider="gitea" -gitea-host="https://gitea.example.com" -client_id="your-client-id" -client_secret="your-client-secret"
199212
```
200213

201-
3. Optional: Specify a different port:
214+
3. Optional flags:
202215

203216
```bash
204-
go run server.go -provider="gitlab" -client_id="your-id" -client_secret="your-secret" -addr=":8095"
217+
go run . -client_id="your-id" -client_secret="your-secret" \
218+
-addr=":8095" \
219+
-log-level="INFO" \
220+
-store="redis" \
221+
-redis-addr="localhost:6379" \
222+
-redis-password="mypassword" \
223+
-redis-db=1
205224
```
206225

207226
### Server Endpoints
208227

209-
| Endpoint | Method | Description | Auth Required |
210-
|----------|--------|-------------|---------------|
211-
| `/mcp` | POST/GET/DELETE | MCP protocol endpoint | ✅ Bearer token |
212-
| `/.well-known/oauth-protected-resource` | GET | Resource metadata ||
213-
| `/.well-known/oauth-authorization-server` | GET | OAuth server metadata ||
214-
| `/authorize` | GET | OAuth authorization (redirects to provider) ||
215-
| `/token` | POST | Token exchange with OAuth provider ||
216-
| `/register` | POST | Dynamic client registration ||
228+
| Endpoint | Method | Description | Auth Required |
229+
| ----------------------------------------- | --------------- | ------------------------------------------- | --------------- |
230+
| `/mcp` | POST/GET/DELETE | MCP protocol endpoint | ✅ Bearer token |
231+
| `/.well-known/oauth-protected-resource` | GET | Resource metadata | |
232+
| `/.well-known/oauth-authorization-server` | GET | OAuth server metadata | |
233+
| `/authorize` | GET | OAuth authorization (redirects to provider) | |
234+
| `/token` | POST | Token exchange with OAuth provider | |
235+
| `/register` | POST | Dynamic client registration | |
217236

218237
### Testing with curl
219238

220239
```bash
221240
# Get OAuth metadata
222241
curl http://localhost:8095/.well-known/oauth-authorization-server
223242

243+
# Get protected resource metadata
244+
curl http://localhost:8095/.well-known/oauth-protected-resource
245+
246+
# Register a client
247+
curl -X POST http://localhost:8095/register \
248+
-H "Content-Type: application/json" \
249+
-d '{
250+
"redirect_uris": ["http://localhost:8085/oauth/callback"],
251+
"grant_types": ["authorization_code"],
252+
"response_types": ["code"]
253+
}'
254+
224255
# Try MCP without token (should get 401)
225256
curl -X POST http://localhost:8095/mcp
226257

227258
# Test with valid token (after OAuth flow)
228259
curl -X POST http://localhost:8095/mcp \
229-
-H "Authorization: Bearer your-github-token" \
260+
-H "Authorization: Bearer your-oauth-token" \
230261
-H "Content-Type: application/json"
231262
```
232263

@@ -237,19 +268,31 @@ curl -X POST http://localhost:8095/mcp \
237268
### Key Components
238269

239270
- **`MCPServer`**: Wraps the mark3labs/mcp-go server with OAuth authentication
240-
- **`GitHubProvider`**: Implements GitHub OAuth 2.0 integration with proper error handling
271+
- **OAuth Providers**:
272+
- `GitHubProvider`: GitHub OAuth 2.0 integration
273+
- `GitLabProvider`: GitLab OAuth 2.0 integration with self-hosted support
274+
- `GiteaProvider`: Gitea OAuth 2.0 integration with self-hosted support
275+
- **Storage Layer**:
276+
- `store.MemoryStore`: In-memory storage for development
277+
- `store.RedisStore`: Redis-backed persistent storage for production
278+
- Factory pattern for easy store creation
241279
- **`authMiddleware`**: Gin middleware that enforces Authorization header requirements
242280
- **Context Injection**: Uses `core.AuthFromRequest` to propagate tokens through request context
243281

244282
### File Structure
245283

246284
```txt
247285
03-oauth-mcp/
248-
├── server/
286+
├── oauth-server/
249287
│ ├── server.go # Main server with MCP and OAuth endpoints
250288
│ ├── oauth_provider.go # OAuth provider interface definition
251-
│ └── provider_github.go # GitHub OAuth implementation
252-
├── client/
289+
│ ├── provider_github.go # GitHub OAuth implementation
290+
│ ├── provider_gitlab.go # GitLab OAuth implementation
291+
│ ├── provider_gitea.go # Gitea OAuth implementation
292+
│ ├── middleware.go # Authentication middleware
293+
│ ├── auth_meta.go # Client registration metadata
294+
│ └── README.md # Server documentation
295+
├── oauth-client/
253296
│ ├── client.go # OAuth MCP client example
254297
│ └── README.md # Client documentation
255298
└── README.md # This file
@@ -262,29 +305,115 @@ curl -X POST http://localhost:8095/mcp \
262305
- **Token Masking**: Sensitive tokens are masked in logs and responses
263306
- **CORS Configuration**: Proper CORS headers for cross-origin requests
264307
- **Request Timeouts**: 30-second timeouts on all external HTTP requests
308+
- **Client Secret Validation**: Validates client credentials before token exchange
309+
- **Redirect URI Validation**: Ensures redirect URIs match registered URIs
310+
311+
### Storage Options
312+
313+
#### Memory Store
314+
315+
- **Pros**: No external dependencies, fast, simple setup
316+
- **Cons**: Data lost on restart, not suitable for production with multiple instances
317+
- **Use case**: Development and testing
318+
319+
#### Redis Store
320+
321+
- **Pros**: Persistent storage, production-ready, supports multiple server instances
322+
- **Cons**: Requires Redis server
323+
- **Use case**: Production deployments
324+
325+
See [oauth-server/README.md](oauth-server/README.md) for detailed storage configuration.
265326

266327
---
267328

268329
## Testing the Complete Flow
269330

270-
1. **Start the server** with your GitHub OAuth credentials
271-
2. **Run the client** - it will open your browser to GitHub
272-
3. **Authorize the application** in GitHub
331+
1. **Start the server** with your OAuth credentials:
332+
333+
```bash
334+
cd 03-oauth-mcp/oauth-server
335+
go run . -client_id="your-id" -client_secret="your-secret"
336+
```
337+
338+
2. **Run the client** in a separate terminal:
339+
340+
```bash
341+
cd 03-oauth-mcp/oauth-client
342+
go run .
343+
```
344+
345+
3. **Authorize the application** - the client will open your browser to the OAuth provider
273346
4. **Observe the logs** showing successful token exchange and user info fetch
274-
5. **See MCP tools execute** with the authenticated GitHub token
347+
5. **See MCP tools execute** with the authenticated token
348+
349+
### Testing with Different Configurations
350+
351+
**Development setup (memory store):**
352+
353+
```bash
354+
# Terminal 1: Server
355+
cd 03-oauth-mcp/oauth-server
356+
go run . -client_id=<id> -client_secret=<secret>
357+
358+
# Terminal 2: Client
359+
cd 03-oauth-mcp/oauth-client
360+
go run .
361+
```
362+
363+
**Production setup (Redis store):**
364+
365+
```bash
366+
# Terminal 1: Redis
367+
docker run -d -p 6379:6379 redis:alpine
368+
369+
# Terminal 2: Server
370+
cd 03-oauth-mcp/oauth-server
371+
go run . -client_id=<id> -client_secret=<secret> -store redis -log-level INFO
372+
373+
# Terminal 3: Client
374+
cd 03-oauth-mcp/oauth-client
375+
go run .
376+
```
275377

276378
---
277379

278380
## See Also
279381

280-
For detailed OAuth MCP Client implementation, features, and usage examples, see [`client/README.md`](client/README.md).
382+
- [OAuth Server Documentation](oauth-server/README.md) - Detailed server configuration and storage options
383+
- [OAuth Client Documentation](oauth-client/README.md) - Complete client implementation guide
384+
- [Store Package](../pkg/store/README.md) - Storage layer implementation details
385+
386+
---
387+
388+
## Command-Line Flags
389+
390+
### Required Flags
391+
392+
- `-client_id`: OAuth 2.0 Client ID from your provider
393+
- `-client_secret`: OAuth 2.0 Client Secret from your provider
394+
395+
### Optional Flags
396+
397+
- `-addr`: Server address (default: `:8095`)
398+
- `-provider`: OAuth provider - `github`, `gitlab`, or `gitea` (default: `github`)
399+
- `-gitea-host`: Gitea host URL (default: `https://gitea.com`)
400+
- `-gitlab-host`: GitLab host URL (default: `https://gitlab.com`)
401+
- `-log-level`: Log level - `DEBUG`, `INFO`, `WARN`, `ERROR` (default: `DEBUG`)
402+
- `-store`: Storage type - `memory` or `redis` (default: `memory`)
403+
- `-redis-addr`: Redis address (default: `localhost:6379`)
404+
- `-redis-password`: Redis password (optional)
405+
- `-redis-db`: Redis database number (default: `0`)
281406

282407
---
283408

284409
## References
285410

286411
- [MCP Documentation](https://mark3.ai/docs/mcp/)
287412
- [OAuth 2.0 RFC6749](https://datatracker.ietf.org/doc/html/rfc6749)
413+
- [PKCE RFC7636](https://datatracker.ietf.org/doc/html/rfc7636)
288414
- [GitHub OAuth Apps](https://docs.github.com/en/apps/oauth-apps)
415+
- [GitLab OAuth Documentation](https://docs.gitlab.com/ee/api/oauth2.html)
416+
- [Gitea OAuth Documentation](https://docs.gitea.io/en-us/oauth2-provider/)
289417
- [mark3labs/mcp-go](https://github.com/mark3labs/mcp-go)
290418
- [Gin Web Framework](https://gin-gonic.com/)
419+
- [Redis](https://redis.io/)

0 commit comments

Comments
 (0)