-
-
-
+ {/* Local/LDAP Authentication Form */}
+ {(tenantConfig?.auth_provider === 'local' || tenantConfig?.auth_provider === 'ldap') && (
+
+ )}
-
+ {/* SAML Authentication */}
+ {tenantConfig?.auth_provider === 'saml' && (
+
+ )}
+ {/* OAuth Authentication */}
+ {tenantConfig?.auth_provider === 'oauth' && (
+
+
+
+ )}
+
+ {/* Registration link for local auth if enabled */}
+ {tenantConfig?.auth_provider === 'local' && tenantConfig?.local?.allow_registration && (
+
+ )}
+
+ {/* Demo credentials for local/ldap auth */}
+ {(tenantConfig?.auth_provider === 'local' || tenantConfig?.auth_provider === 'ldap') && (
Demo credentials:
@@ -125,7 +225,16 @@ const Login = () => {
Password: admin123
-
+ )}
+
+ {/* Error message if auth provider not configured */}
+ {!tenantConfig?.auth_provider && (
+
+
+ Authentication not configured for this tenant. Please contact your administrator.
+
+
+ )}
);
diff --git a/server/routes/auth.js b/server/routes/auth.js
index 973256c..cb26cbb 100644
--- a/server/routes/auth.js
+++ b/server/routes/auth.js
@@ -84,6 +84,73 @@ router.get('/config/:tenantId', async (req, res) => {
}
});
+/**
+ * GET /auth/config
+ * Get authentication configuration for current tenant (auto-detected)
+ */
+router.get('/config', async (req, res) => {
+ try {
+ // Auto-determine tenant from request
+ const tenantId = await multiAuth.determineTenant(req);
+ if (!tenantId) {
+ return res.status(400).json({
+ success: false,
+ message: 'Unable to determine tenant from request'
+ });
+ }
+
+ const tenant = await Tenant.findOne({ where: { slug: tenantId } });
+ if (!tenant) {
+ return res.status(404).json({
+ success: false,
+ message: 'Tenant not found'
+ });
+ }
+
+ // Return public auth configuration (no secrets)
+ const publicConfig = {
+ tenant_id: tenant.slug,
+ tenant_name: tenant.name,
+ auth_provider: tenant.auth_provider,
+ branding: tenant.branding
+ };
+
+ // Add provider-specific configuration
+ if (tenant.auth_provider === 'local') {
+ const authConfig = JSON.parse(tenant.auth_config || '{}');
+ publicConfig.local = {
+ allow_registration: authConfig.allow_registration || false,
+ require_email_verification: authConfig.require_email_verification || false
+ };
+ } else if (tenant.auth_provider === 'saml') {
+ publicConfig.saml = {
+ login_url: `/auth/saml/${tenantId}/login`,
+ metadata_url: `/auth/saml/${tenantId}/metadata`
+ };
+ } else if (tenant.auth_provider === 'oauth') {
+ publicConfig.oauth = {
+ login_url: `/auth/oauth/${tenantId}/login`
+ };
+ } else if (tenant.auth_provider === 'ldap') {
+ publicConfig.ldap = {
+ // LDAP uses same form as local but with different backend
+ };
+ }
+
+ res.json({
+ success: true,
+ data: publicConfig
+ });
+
+ } catch (error) {
+ console.error('Error fetching auth config:', error);
+ res.status(500).json({
+ success: false,
+ message: 'Failed to fetch authentication configuration'
+ });
+ }
+});
+
/**
* POST /auth/login
* Universal login endpoint that routes to appropriate provider
@@ -129,6 +196,39 @@ router.post('/login', async (req, res, next) => {
}
});
+/**
+ * POST /auth/local
+ * Local authentication endpoint with tenant isolation
+ */
+router.post('/local', async (req, res, next) => {
+ try {
+ // Determine tenant
+ const tenantId = await multiAuth.determineTenant(req);
+ const authConfig = await multiAuth.getTenantAuthConfig(tenantId);
+
+ // Verify tenant supports local authentication
+ if (authConfig.type !== 'local') {
+ return res.status(400).json({
+ success: false,
+ message: `This tenant uses ${authConfig.type} authentication. Please use the appropriate login method.`,
+ auth_provider: authConfig.type
+ });
+ }
+
+ req.tenant = { id: tenantId, authConfig };
+
+ // Call tenant-aware local login
+ return require('../routes/user').loginLocal(req, res, next);
+
+ } catch (error) {
+ console.error('Local login error:', error);
+ res.status(500).json({
+ success: false,
+ message: 'Local login failed'
+ });
+ }
+});
+
/**
* SAML Authentication Routes
*/