AuthSec SDK Documentation
Welcome to the AuthSec SDK documentation. This guide will help you secure your MCP servers with enterprise-grade authentication and authorization.
Table of Contents
- Overview - Introduction to AuthSec SDK and its key features
- Getting Started - Quick start guide to integrate AuthSec SDK
- How It Works - Detailed explanation of the authentication flow and architecture
- RBAC Patterns - Advanced Role-Based Access Control patterns and examples
- Service Integration - Guide to integrating external services securely
- FAQs - Frequently asked questions about AuthSec SDK
Quick Links
Need Help?
If you have any questions or need assistance:
- Check our FAQs
- Read through the detailed documentation
- Contact our support team at support@authsec.dev
Built with ❤️ by the AuthSec team
If you're building MCP servers for AI assistants like Claude, you've probably encountered this critical issue:
All your tools are exposed to everyone by default.
Without proper security, anyone who connects to your MCP server can:
- Call
delete_user_account - Access
view_financial_reports - Trigger
deploy_to_production - Read sensitive company data
That's a security nightmare waiting to happen.
The Solution: AuthSec SDK
AuthSec SDK gives you enterprise-grade security in just 3 lines of code:
from authsec_sdk import protected_by_AuthSec, run_mcp_server_with_oauth
@protected_by_AuthSec("admin_tool", roles=["admin"])
async def admin_tool(arguments: dict) -> list:
return [{"type": "text", "text": "Welcome to admin panel!"}]
run_mcp_server_with_oauth(client_id="your-client-id", app_name="My Server")
That's it. Your tool is now protected by OAuth 2.0 and RBAC.
How It Works: The Complete Flow
Step 1: Before Authentication - Tools Are Hidden
When your MCP server starts, users only see 5 OAuth tools:
oauth_start- Start authenticationoauth_authenticate- Complete authenticationoauth_status- Check auth statusoauth_logout- Logoutoauth_user_info- Get user info
All your protected business logic tools are completely hidden. Users can't even see they exist.
Step 2: User Starts Authentication
User: Call oauth_start
Server: Here's your session_id and authorization URL
The user opens the URL in their browser and authenticates with your OAuth provider (Google, GitHub, Custom Logon, etc.).
Step 3: Complete Authentication with JWT
After authentication, the user receives a JWT token containing:
{
"email": "john@company.com",
"tenant_id": "acme-corp",
"roles": ["admin", "developer"],
"groups": ["engineering"],
"scopes": ["read", "write"],
"resources": ["projects", "analytics"]
}
They call oauth_authenticate with this token.
Step 4: RBAC Magic - Validating Permissions
Here's where AuthSec SDK does the heavy lifting. For each tool in your server, it:
- Connects to your tenant database (
tenant_acme-corp) - Validates JWT claims against database:
- Does
adminrole exist inrolestable? ✓ - Does
writescope exist inscopestable? ✓ - Does
analyticsresource exist inresourcestable? ✓
- Does
- Checks if user satisfies tool requirements
- Returns list of accessible tools
Example validation:
# Tool 1: No RBAC - accessible to all authenticated users
@protected_by_AuthSec("calculator")
async def calculator(...) -> list:
...
# Tool 2: Requires admin role
@protected_by_AuthSec("admin_dashboard", roles=["admin"])
async def admin_dashboard(...) -> list:
...
# Tool 3: Requires write scope AND analytics resource
@protected_by_AuthSec(
"view_analytics",
scopes=["read"],
resources=["analytics"],
require_all=True
)
async def view_analytics(...) -> list:
...
For our user (roles=["admin"], scopes=["read", "write"], resources=["analytics"]):
- ✅
calculator- Accessible (all authenticated users) - ✅
admin_dashboard- Accessible (has admin role) - ✅
view_analytics- Accessible (has read scope + analytics resource)
Step 5: Tools Are Now Visible
After authentication, users see only what they can access:
Available tools:
├── oauth_start
├── oauth_authenticate
├── oauth_status
├── calculator # ← Now visible
├── admin_dashboard # ← Now visible (has admin role)
└── view_analytics # ← Now visible (has permissions)
Step 6: Tool Execution with User Context
When a user calls a protected tool, user information is automatically injected:
@protected_by_AuthSec("admin_dashboard", roles=["admin"])
async def admin_dashboard(arguments: dict) -> list:
# User info automatically available
email = arguments['_user_info']['email'] # "john@company.com"
roles = arguments['_user_info']['roles'] # ["admin", "developer"]
tenant = arguments['_user_info']['tenant_id'] # "acme-corp"
return [{
"type": "text",
"text": f"Welcome to admin dashboard, {email}!"
}]
Real-World Use Case: GitHub Integration (External-Service Integration)
Let's build a tool that lists GitHub repositories using credentials stored securely in HashiCorp Vault.
Setup: Store Credentials in Dashboard
- Log in to AuthSec Dashboard
- Navigate to Services section
- Add service: "GitHub API Integration"
- Store credential:
access_token=ghp_YOUR_TOKEN - Credentials are encrypted and stored in Vault
Code: Use Credentials Securely
import aiohttp
from authsec_sdk import protected_by_AuthSec, ServiceAccessSDK
@protected_by_AuthSec("list_my_repos", scopes=["read"])
async def list_my_repos(arguments: dict, session) -> list:
"""List user's GitHub repositories."""
# Create services SDK
services_sdk = ServiceAccessSDK(session)
# Fetch GitHub token from Vault (secure!)
github_token = await services_sdk.get_service_token("GitHub API Integration")
# Call GitHub API
async with aiohttp.ClientSession() as http:
async with http.get(
'https://api.github.com/user/repos',
headers={'Authorization': f'Bearer {github_token}'}
) as response:
repos = await response.json()
# Format response
repo_list = "\n".join([
f"- {repo['full_name']} ({repo['stargazers_count']} ⭐)"
for repo in repos[:10]
])
return [{
"type": "text",
"text": f"Your GitHub Repositories:\n{repo_list}"
}]
Security benefits:
- ✅ Token stored in Vault, not in code
- ✅ Only users with
readscope can access - ✅ Token never exposed to end users
- ✅ All access logged and auditable
- ✅ Credentials can be rotated from dashboard
Advanced RBAC Patterns
OR Logic - Any Permission Grants Access
@protected_by_AuthSec(
"view_reports",
roles=["admin", "manager", "analyst"],
require_all=False # Default: OR logic
)
async def view_reports(arguments: dict) -> list:
return [{"type": "text", "text": "Business reports"}]
Accessible to: Users with admin OR manager OR analyst role
AND Logic - All Permissions Required
@protected_by_AuthSec(
"deploy_production",
roles=["admin", "deployer"], # User needs admin OR deployer
scopes=["write"], # AND user needs write scope
resources=["production"], # AND user needs production resource
require_all=True # All conditions must pass
)
async def deploy_production(arguments: dict) -> list:
return [{"type": "text", "text": "Deployment initiated"}]
Accessible to: Users with (admin OR deployer) AND write AND production resource
Group-Based Access
@protected_by_AuthSec(
"engineering_tools",
groups=["engineering", "devops"]
)
async def engineering_tools(arguments: dict) -> list:
return [{"type": "text", "text": "Engineering dashboard"}]
Accessible to: Users in engineering OR devops group
Complex Multi-Requirement Tool
@protected_by_AuthSec(
"sensitive_operations",
roles=["admin", "superuser"],
groups=["security-team"],
scopes=["write", "admin"],
resources=["production", "sensitive-data"],
require_all=True
)
async def sensitive_operations(arguments: dict) -> list:
# Only accessible if ALL conditions are met:
# - Has admin OR superuser role
# - In security-team group
# - Has write OR admin scope
# - Has access to production AND sensitive-data resources
return [{"type": "text", "text": "Sensitive operation completed"}]
Getting Started in 5 Minutes
1. Install the SDK
pip install git+https://github.com/authsec-ai/sdk-authsec.git
2. Get Your Client Credentials
- Sign up at AuthSec Dashboard
- Create a new application (MCP)
- Copy your
client_id - Configure your authentication methods for users
- Configure RBAC rules (roles, scopes, resources)
3. Create Your Secure MCP Server
# server.py
from authsec_sdk import protected_by_AuthSec, run_mcp_server_with_oauth
# Tool 1: Accessible to all authenticated users
@protected_by_AuthSec("hello")
async def hello(arguments: dict) -> list:
return [{
"type": "text",
"text": f"Hello, {arguments['_user_info']['email']}!"
}]
# Tool 2: Admin only
@protected_by_AuthSec("admin_panel", roles=["admin"])
async def admin_panel(arguments: dict) -> list:
return [{"type": "text", "text": "Admin panel accessed"}]
# Tool 3: Requires write permission
@protected_by_AuthSec("create_resource", scopes=["write"])
async def create_resource(arguments: dict) -> list:
name = arguments.get("name", "Unnamed")
return [{
"type": "text",
"text": f"Resource '{name}' created successfully!"
}]
# Start the server
if __name__ == "__main__":
run_mcp_server_with_oauth(
client_id="your-client-id-here",
app_name="My Secure MCP Server"
)
4. Run Your Server
python server.py
5. Test It Out
From your MCP Clients (MCP Inspector, VS Code, Claude, Windows, etc.):
User: Show me available tools
> Only OAuth tools are visible
User: Call oauth_start
> Returns session_id and authorization URL
User: [Opens URL and authenticates]
> Receives JWT token
User: Call oauth_authenticate with token
> Authentication successful!
> Protected tools now visible
User: Call hello
> "Hello, john@company.com!"
User: Call admin_panel
> "Admin panel accessed" (only if admin role)
User: Call create_resource with name="Project Alpha"
> "Resource 'Project Alpha' created!" (only if write scope)
Architecture Overview
┌─────────────────────────────────┐
│ AI Assistant (Claude, etc.) │
│ MCP Client │
└────────────┬────────────────────┘
│ JSON-RPC 2.0
▼
┌─────────────────────────────────┐
│ Your MCP Server (server.py) │
│ with AuthSec SDK │
│ │
│ OAuth Tools (always visible): │
│ ├── oauth_start │
│ ├── oauth_authenticate │
│ └── oauth_status │
│ │
│ Protected Tools (after auth): │
│ ├── @protected_by_AuthSec │
│ │ ("hello") │
│ ├── @protected_by_AuthSec │
│ │ ("admin_panel", │
│ │ roles=["admin"]) │
│ └── ... │
└────────────┬────────────────────┘
│ HTTPS
▼
┌─────────────────────────────────┐
│ AuthSec SDK Manager Service │
│ (Managed by AuthSec) │
│ │
│ ├── OAuth flow management │
│ ├── JWT validation │
│ ├── RBAC checking │
│ ├── Session management │
│ └── Vault integration │
└────────────┬────────────────────┘
│
▼
┌─────────────────────────────────┐
│ External Services │
│ ├── OAuth Provider │
│ ├── HashiCorp Vault │
│ └── Tenant Database │
└─────────────────────────────────┘
Multi-Tenant Architecture
- Master Database: Tenant mappings
- Tenant Databases: Each tenant has isolated database (
tenant_{tenant_id})- RBAC tables (roles, scopes, resources, permissions)
- Authenticated sessions
- Service configurations
- User data
Before vs After AuthSec SDK
Before: Insecure and Messy
# server.py
async def admin_dashboard(arguments: dict) -> list:
# ❌ No authentication - anyone can call this!
# ❌ No authorization - can't restrict by role!
# ❌ Credentials hardcoded - major security risk!
github_token = "ghp_hardcoded_token_in_my_code"
# Call GitHub API...
return [{"type": "text", "text": "Dashboard"}]
Problems:
- ❌ No authentication
- ❌ No authorization/RBAC
- ❌ Credentials in source code
- ❌ All tools always visible to everyone
- ❌ No audit trail
- ❌ No multi-tenancy
After: Secure and Clean
# server.py
from authsec_sdk import protected_by_AuthSec, ServiceAccessSDK
@protected_by_AuthSec("admin_dashboard", roles=["admin"])
async def admin_dashboard(arguments: dict, session) -> list:
# ✅ Authenticated - only valid users
# ✅ Authorized - only admins can access
# ✅ Credentials from Vault - secure!
services_sdk = ServiceAccessSDK(session)
github_token = await services_sdk.get_service_token("GitHub API")
# Call GitHub API...
return [{"type": "text", "text": "Dashboard"}]
Benefits:
- ✅ OAuth 2.0 authentication
- ✅ RBAC authorization
- ✅ Link any External-Service PROVIDER
- ✅ Credentials in Vault
- ✅ Tools hidden until authenticated
- ✅ Full audit trail
- ✅ Multi-tenant ready
Key Features
🔐 Authentication (AuthN)
- OAuth 2.0 flow with PKCE security
- JWT token validation and management
- Persistent session handling
- Multi-tenant support out of the box
🛡️ Authorization (AuthZ)
- Role-Based Access Control (RBAC)
- Dynamic tool filtering (users only see permitted tools)
- Flexible permissions: roles, groups, scopes, resources
- Database-backed validation (not just JWT claims)
- AND/OR logic support
🔑 External Service Integration
- HashiCorp Vault integration
- Secure credential storage via UI
- Support for any API (GitHub, AWS, databases, Slack, etc.)
- Automatic credential rotation
- No credentials in code
✨ Developer Experience
- Single decorator to protect tools
- Minimal code changes
- Automatic tool hiding/showing
- User context auto-injected
- Zero security expertise required
Frequently Asked Questions
Q: Do I need to modify my existing tools significantly?
A: No! Just add the @protected_by_AuthSec decorator. Minimal changes required.
Q: What happens if a user loses their JWT token?
A: They simply re-authenticate by calling oauth_start again. The entire process takes less than 30 seconds.
Q: Can I use my own OAuth provider? A: Absolutely! AuthSec SDK works with any OAuth 2.0 provider (Google, GitHub, Custom Logon, etc.).
Q: How does RBAC validation actually work? A: User roles/scopes from JWT are validated against your tenant database. Access is granted only if they exist in both places.
Q: Are credentials really secure? A: Yes. Credentials are stored in HashiCorp Vault, never in your code. They're fetched on-demand and never exposed to end users.
Q: What's the performance impact? A: Minimal. AuthSec SDK uses connection pooling and caching. Typical validation overhead is <5ms per request.
Q: Can I test this locally? A: Yes! You can run your MCP server locally using AuthSec SDK locally for testing as well.
Q: What about compliance and audit logs? A: All authentication and tool access is logged. Audit logging features are available on the AuthSec Dashboard
Get Started Today
Secure your MCP server in just 5 minutes:
- Sign up: app.authsec.dev
- Install SDK:
pip install authsec-sdk - Add decorator:
@protected_by_AuthSec("tool_name", roles=["admin"]) - Run server:
python my_server.py
That's it. Your tools are now protected by enterprise-grade security.
Resources
- Blogs: docs.authsec.dev
- Dashboard: app.authsec.dev
- GitHub: github.com/authsec-ai/sdk-authsec
- Support: support@authsec.dev
Conclusion
Building secure AI tools shouldn't be complicated. With AuthSec SDK, you get:
- ✅ OAuth 2.0 authentication in 3 lines of code
- ✅ Flexible RBAC with database validation
- ✅ Secure credential management with Vault
- ✅ Dynamic tool filtering based on permissions
- ✅ Multi-tenant architecture out of the box
- ✅ Zero security expertise required
Stop building security infrastructure from scratch. Start building secure AI tools that your users can trust.
Try AuthSec SDK today: app.authsec.dev
Built with ❤️ by the AuthSec team
*Have questions? Reach out at support@authsec.dev