mirror of
https://github.com/Eugeny/tabby-web.git
synced 2026-08-17 06:46:05 +01:00
feat: dynamic auth providers + Auth0 support
- Add /api/1/auth/providers endpoint that returns only configured providers - Frontend fetches available providers dynamically instead of hardcoding - Only providers with credentials set (KEY + SECRET) appear as login options - Add Auth0 as a supported authentication provider - Add python-jose[cryptography] dependency for Auth0 JWT verification - Show helpful message when no providers are configured This makes the login page modular - administrators only see buttons for providers they've actually configured, avoiding confusion from dead buttons. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ router.register(
|
||||
|
||||
urlpatterns = [
|
||||
path("api/1/auth/logout", auth.LogoutView.as_view()),
|
||||
path("api/1/auth/providers", auth.ProvidersView.as_view()),
|
||||
path("api/1/user", user.UserViewSet.as_view({"get": "retrieve", "put": "update"})),
|
||||
path(
|
||||
"api/1/gateways/choose",
|
||||
|
||||
@@ -1,9 +1,73 @@
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import logout
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
|
||||
# Provider configuration: maps backend names to their display info
|
||||
# and the environment variable prefix used to detect if they're configured
|
||||
PROVIDER_CONFIG = {
|
||||
'github': {
|
||||
'name': 'GitHub',
|
||||
'icon': 'github',
|
||||
'cls': 'btn-primary',
|
||||
'env_prefix': 'SOCIAL_AUTH_GITHUB',
|
||||
},
|
||||
'gitlab': {
|
||||
'name': 'GitLab',
|
||||
'icon': 'gitlab',
|
||||
'cls': 'btn-warning',
|
||||
'env_prefix': 'SOCIAL_AUTH_GITLAB',
|
||||
},
|
||||
'google-oauth2': {
|
||||
'name': 'Google',
|
||||
'icon': 'google',
|
||||
'cls': 'btn-secondary',
|
||||
'env_prefix': 'SOCIAL_AUTH_GOOGLE_OAUTH2',
|
||||
},
|
||||
'microsoft-graph': {
|
||||
'name': 'Microsoft',
|
||||
'icon': 'microsoft',
|
||||
'cls': 'btn-light',
|
||||
'env_prefix': 'SOCIAL_AUTH_MICROSOFT_GRAPH',
|
||||
},
|
||||
'auth0': {
|
||||
'name': 'Auth0',
|
||||
'icon': 'key', # Using key icon as Auth0 doesn't have a FA brand icon
|
||||
'cls': 'btn-dark',
|
||||
'env_prefix': 'SOCIAL_AUTH_AUTH0',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def is_provider_configured(env_prefix: str) -> bool:
|
||||
"""Check if a provider has both KEY and SECRET configured."""
|
||||
key = getattr(settings, f'{env_prefix}_KEY', None)
|
||||
secret = getattr(settings, f'{env_prefix}_SECRET', None)
|
||||
# For Auth0, also need DOMAIN
|
||||
if env_prefix == 'SOCIAL_AUTH_AUTH0':
|
||||
domain = getattr(settings, f'{env_prefix}_DOMAIN', None)
|
||||
return bool(key and secret and domain)
|
||||
return bool(key and secret)
|
||||
|
||||
|
||||
class LogoutView(APIView):
|
||||
def post(self, request, format=None):
|
||||
logout(request)
|
||||
return Response(None)
|
||||
|
||||
|
||||
class ProvidersView(APIView):
|
||||
"""Returns list of configured authentication providers."""
|
||||
|
||||
def get(self, request, format=None):
|
||||
providers = []
|
||||
for provider_id, config in PROVIDER_CONFIG.items():
|
||||
if is_provider_configured(config['env_prefix']):
|
||||
providers.append({
|
||||
'id': provider_id,
|
||||
'name': config['name'],
|
||||
'icon': config['icon'],
|
||||
'cls': config['cls'],
|
||||
})
|
||||
return Response(providers)
|
||||
|
||||
Reference in New Issue
Block a user