@mayademcom/directus-extension-hasura-sso-bridge
v1.1.2
Published
Seamless SSO bridge between Hasura and Directus admin panel.
Readme
Directus Hasura SSO Bridge
Seamless single sign-on integration between Hasura and Directus admin panel
🚀 Features
✅ One-Click Admin Access - Hasura users can access Directus admin without re-authentication
✅ Automatic User Provisioning - Creates Directus users automatically from Hasura JWT
✅ Role Mapping - Maps Hasura roles to appropriate Directus permissions
✅ Secure Session Management - Full session handling with HTTP-only cookies
✅ TypeScript Support - Fully typed for better developer experience
✅ Production Ready - Comprehensive error handling and logging
📋 Requirements
- Directus v10+ (TypeScript extension support)
- Hasura with JWT authentication configured
🔧 Installation
Method 1: NPM Installation (Recommended)
# Navigate to your Directus project root
cd your-directus-project
# Install the extension via npm
npm install @mayademcom/directus-extension-hasura-sso-bridge
# Restart Directus
npm startMethod 2: Manual Installation
# Clone or download the extension
git clone https://github.com/mayademcom/directus-extension-hasura-sso-bridge.git
# Navigate to your Directus project
cd your-directus-project
# Copy extension to Directus extensions directory
cp -r directus-extension-hasura-sso-bridge extensions/endpoints/
# Install dependencies
cd extensions/endpoints/directus-extension-hasura-sso-bridge
npm install
# Build the extension
npm run build
# Return to project root and restart Directus
cd ../../../
npm startMethod 3: Direct Download
Download the latest release from GitHub Releases
Extract to
extensions/endpoints/directus-extension-hasura-sso-bridge/Run
npm install && npm run buildin the extension directoryRestart Directus
⚙️ Configuration
1. Environment Variables
Add these to your Directus .env file:
# Your existing Directus configuration...
# Hasura JWT Secret (same as your Hasura instance)
HASURA_ADMIN_JWT_SECRET=your-hasura-jwt-secret-key
# Directus JWT Secret
SECRET=your-directus-secret-key2. Directus Roles Setup
Create these roles in Directus admin panel:
- Administrator - Full system access
- Editor - Content management access
Or customize role mapping in the extension configuration.
3. Verification
After installation, verify the extension is loaded:
# Check health endpoint
curl http://localhost:8055/hasura-sso-bridge/health
# Expected response:
{
"status": "healthy",
"service": "hasura-sso-bridge",
"timestamp": "2024-01-15T10:30:00.000Z"
}🎯 Usage
Basic Usage
- Set Hasura JWT Token as Cookie in your application
// Set the Authorization cookie with your Hasura token
document.cookie = `Authorization=${hasuraToken}; path=/; SameSite=Lax; Secure`;- Navigate to SSO endpoint (no token parameter needed):
GET https://your-directus.com/hasura-sso-bridge- Automatic redirect to Directus admin panel with authenticated session
Frontend Integration
// Example: Auto-redirect button with cookie
function openDirectusAdmin() {
const hasuraToken = getHasuraToken(); // Your token retrieval logic
// Set token as cookie
document.cookie = `Authorization=${hasuraToken}; path=/; SameSite=Lax; Secure`;
// Redirect to SSO endpoint
const ssoUrl = "https://your-directus.com/hasura-sso-bridge";
window.open(ssoUrl, "_blank");
}
// Example: Using fetch with credentials
async function openDirectusAdminWithFetch() {
const hasuraToken = getHasuraToken();
// Set cookie
document.cookie = `Authorization=${hasuraToken}; path=/; SameSite=Lax; Secure`;
// Open in new window
window.open("https://your-directus.com/hasura-sso-bridge", "_blank");
}Open Content ManagementReact Integration
import { useAuthToken } from "./hooks/useAuth";
function CMSAccessButton() {
const { hasuraToken } = useAuthToken();
const openCMS = () => {
// Set Hasura token as cookie
document.cookie = `Authorization=${hasuraToken}; path=/; SameSite=Lax; Secure`;
// Open SSO endpoint
const ssoUrl = `${process.env.REACT_APP_DIRECTUS_URL}/hasura-sso-bridge`;
window.open(ssoUrl, '_blank');
};
return (
Open Content Management
);
}Advanced: Using Fetch API
// If you need more control, use fetch with credentials
async function authenticateWithDirectus() {
const hasuraToken = getHasuraToken();
// Set cookie first
document.cookie = `Authorization=${hasuraToken}; path=/; SameSite=Lax; Secure`;
try {
// Call SSO endpoint with credentials
const response = await fetch(
`${process.env.REACT_APP_DIRECTUS_URL}/hasura-sso-bridge`,
{
method: "GET",
credentials: "include", // Important: Include cookies
headers: {
Accept: "application/json",
},
}
);
if (response.redirected) {
// Successfully authenticated, redirect to admin
window.location.href = response.url;
}
} catch (error) {
console.error("Authentication failed:", error);
}
}API Integration
# Direct API call with cookie
curl "https://your-directus.com/hasura-sso-bridge" \
-H "Cookie: Authorization=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \
-L # Follow redirects
# Response: 302 Redirect to /admin/content with authenticated session
# Test without authentication (should return 401)
curl "https://your-directus.com/hasura-sso-bridge" -v
# Response: 401 UnauthorizedSecurity Notes
- Cookie Security: The extension reads the Hasura JWT token from the
Authorizationcookie, not from URL parameters - Credentials Required: Frontend requests must include
credentials: 'include'to send cookies - HTTPS Recommended: Use
Secureflag in production to ensure cookies are only sent over HTTPS - SameSite Protection: Set
SameSite=LaxorSameSite=Strictto prevent CSRF attacks - No Token in URL: Tokens are never exposed in URLs, browser history, or server logs
Cookie Configuration
// Development (HTTP)
document.cookie = `Authorization=${token}; path=/; SameSite=Lax`;
// Production (HTTPS)
document.cookie = `Authorization=${token}; path=/; SameSite=Lax; Secure`;
// With expiration (optional)
const expires = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24 hours
document.cookie = `Authorization=${token}; path=/; SameSite=Lax; Secure; expires=${expires.toUTCString()}`;🔐 Security & Authentication
JWT Token Format
Your Hasura JWT must include these claims:
{
"sub": "user-id-123",
"email": "[email protected]",
"first_name": "John",
"last_name": "Doe",
"https://hasura.io/jwt/claims": {
"x-hasura-user-id": "user-id-123",
"x-hasura-default-role": "editor",
"x-hasura-allowed-roles": ["editor"]
}
}Role Mapping
| Hasura Role | Directus Role | Permissions |
| ------------- | ------------- | ----------------------- |
| super_admin | Administrator | Full system access |
| editor | Editor | Content management only |
Security Features
- HTTP-Only Cookies - Prevents XSS attacks
- Secure Session Management - Proper session lifecycle
- Role Validation - Only authorized roles can access
- Automatic User Provisioning - JIT (Just-In-Time) user creation
- Token Validation - Strict JWT verification
🛠️ Advanced Configuration
Custom Role Mapping
Create a custom configuration file:
// extensions/endpoints/directus-extensio-hasura-sso-bridge/config/roles.js
export const ROLE_MAPPING: RoleMapping = {
super_admin: "Administrator",
editor: "Editor",
content_manager: "Editor",
api_user: "User",
// Add your custom roles here
};Session Duration
Modify session duration:
# Add to your .env file
SESSION_DURATION_HOURS=86400000 # 24 hours in milliseconds📚 API Reference
Endpoints
GET /hasura-sso-bridge
Main SSO authentication endpoint.
Parameters:
token(query, required) - Hasura JWT token
Response:
302- Redirect to/admin/contentwith authenticated session403- Access denied (invalid token/role)
Example:
curl -L "https://your-directus.com/hasura-sso-bridge?token=eyJ0eXAiOiJKV1Q..."GET /hasura-sso-bridge/health
Health check endpoint for monitoring.
Response:
{
"status": "healthy",
"service": "hasura-sso-bridge",
"timestamp": "2024-01-15T10:30:00.000Z"
}GET /hasura-sso-bridge/config
Configuration information endpoint.
Response:
{
"supportedRoles": ["super_admin", "editor"],
"environment": "production",
"features": ["jwt-auth", "role-mapping", "auto-provisioning"]
}🧪 Development
Local Development
# Clone the repository
git clone https://github.com/yourusername/directus-extension-hasura-sso-bridge.git
cd directus-extension-hasura-sso-bridge
# Install dependencies
npm install
# Development build with watch mode
npm run dev
# Type checking
npm run type-check
# Linting
npm run lint
# Build for production
npm run buildTesting
# Test the health endpoint
curl http://localhost:8055/hasura-sso-bridge/health
# Test configuration endpoint
curl http://localhost:8055/hasura-sso-bridge/config
# Test with a valid token
curl "http://localhost:8055/hasura-sso-bridge?token=YOUR_TEST_TOKEN"Release Process
# Release in both NPM and Github
npm run release
🚨 Troubleshooting
Common Issues
"Access denied" Error
- Cause: Invalid JWT token or unsupported role
- Solution: Verify token format and role mapping
- Debug: Check
/hasura-sso-bridge/configfor supported roles
"Directus SECRET not configured" Error
- Cause: Missing environment variable
- Solution: Add
SECRETto your.envfile - Verify: Restart Directus after adding environment variables
"Role 'X' not found" Error
- Cause: Directus role doesn't exist in database
- Solution: Create the role in Directus admin or update role mapping
- Check: Visit Settings > Access Control > Roles in Directus admin
Extension not loading
- Cause: Build errors or incorrect file structure
- Solution: Check extension logs and rebuild with
npm run build - Verify: Check Directus logs for extension loading errors
"Invalid or expired Hasura token"
- Cause: Token verification failed
- Solution: Verify
HASURA_ADMIN_JWT_SECRETmatches your Hasura configuration - Debug: Use jwt.io to inspect token claims
Logs Format
All logs include the [Hasura-SSO-Bridge] prefix:
[Hasura-SSO-Bridge] ✅ SSO authentication completed, redirecting to admin
[Hasura-SSO-Bridge] ❌ SSO authentication failed: Invalid token
[Hasura-SSO-Bridge] ⚠️ Role mapping failed for role: invalid_role
Health Monitoring
Monitor the extension with the health endpoint:
# Check extension health
curl -f http://localhost:8055/hasura-sso-bridge/health || echo "Extension unhealthy"
# Monitor in production
watch -n 30 'curl -s http://your-directus.com/hasura-sso-bridge/health | jq .status'🔄 Migration & Updates
Updating the Extension
# Update via npm
npm update directus-extension-hasura-sso-bridge
# Restart Directus
npm startBreaking Changes
Check CHANGELOG.md for breaking changes between versions.
Database Migration
No database migrations required - the extension uses existing Directus tables.
📊 Performance & Monitoring
Performance Considerations
- Session Cleanup: Extension automatically cleans expired sessions
- Memory Usage: Minimal memory footprint with efficient JWT processing
- Database Impact: Lightweight database operations
Monitoring Endpoints
# Health check for load balancers
GET /hasura-sso-bridge/health
# Configuration validation
GET /hasura-sso-bridge/config🤝 Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes with tests
- Commit with conventional commits (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Guidelines
- Follow existing TypeScript patterns
- Add tests for new features
- Update documentation
- Follow conventional commit format
- Ensure all tests pass
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🔗 Links
- NPM Package
- GitHub Repository
- Directus Documentation
- Hasura Documentation
- JWT.io - JWT token debugging
- Extension Development Guide
💬 Support
🌟 Star History
If this extension helped you, please consider giving it a ⭐ on GitHub!
Made with ❤️ for seamless SSO integration between Hasura and Directus
