Fix jwt-token
This commit is contained in:
@@ -14,11 +14,20 @@ class MultiTenantAuth {
|
||||
constructor() {
|
||||
this.authConfig = new AuthConfig();
|
||||
this.providers = new Map();
|
||||
this.models = null; // For dependency injection in tests
|
||||
|
||||
// Initialize authentication providers
|
||||
this.initializeProviders();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set models for dependency injection (used in tests)
|
||||
* @param {Object} models - Models object
|
||||
*/
|
||||
setModels(models) {
|
||||
this.models = models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all authentication providers
|
||||
*/
|
||||
@@ -33,43 +42,74 @@ class MultiTenantAuth {
|
||||
* Can be from subdomain, header, or JWT
|
||||
*/
|
||||
async determineTenant(req) {
|
||||
// Method 1: Subdomain (tenant.yourapp.com)
|
||||
const subdomain = req.hostname.split('.')[0];
|
||||
if (subdomain && subdomain !== 'www' && subdomain !== 'api') {
|
||||
return subdomain;
|
||||
// Method 1: From authenticated user (highest priority)
|
||||
if (req.user && req.user.tenantId) {
|
||||
return req.user.tenantId;
|
||||
}
|
||||
|
||||
// Method 2: Custom header
|
||||
const tenantHeader = req.headers['x-tenant-id'];
|
||||
if (tenantHeader) {
|
||||
return tenantHeader;
|
||||
}
|
||||
|
||||
// Method 3: From JWT token (for existing sessions)
|
||||
// Method 2: From JWT token (for existing sessions)
|
||||
const token = req.headers.authorization?.split(' ')[1];
|
||||
if (token) {
|
||||
try {
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
||||
return decoded.tenantId;
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'test-secret');
|
||||
if (decoded.tenantId) {
|
||||
return decoded.tenantId;
|
||||
}
|
||||
} catch (error) {
|
||||
// Token invalid, continue with other methods
|
||||
}
|
||||
}
|
||||
|
||||
// Method 4: Query parameter (for redirects)
|
||||
if (req.query.tenant) {
|
||||
// Method 3: Custom header
|
||||
const tenantHeader = req.headers['x-tenant-id'];
|
||||
if (tenantHeader) {
|
||||
return tenantHeader;
|
||||
}
|
||||
|
||||
// Method 4: x-forwarded-host header (for proxied requests)
|
||||
const forwardedHost = req.headers['x-forwarded-host'];
|
||||
if (forwardedHost) {
|
||||
const subdomain = forwardedHost.split('.')[0];
|
||||
if (subdomain && subdomain !== 'www' && subdomain !== 'api' && !subdomain.includes(':')) {
|
||||
return subdomain;
|
||||
}
|
||||
}
|
||||
|
||||
// Method 5: Subdomain (tenant.yourapp.com)
|
||||
const hostname = req.hostname || req.headers.host || '';
|
||||
if (hostname && !hostname.startsWith('localhost')) {
|
||||
const subdomain = hostname.split('.')[0];
|
||||
if (subdomain && subdomain !== 'www' && subdomain !== 'api' && !subdomain.includes(':')) {
|
||||
return subdomain;
|
||||
}
|
||||
}
|
||||
|
||||
// Method 6: URL path (/tenant2/api/...)
|
||||
const pathSegments = (req.path || req.url || '').split('/').filter(segment => segment);
|
||||
if (pathSegments.length > 0 && pathSegments[0] !== 'api') {
|
||||
return pathSegments[0];
|
||||
}
|
||||
|
||||
// Method 7: Query parameter (for redirects)
|
||||
if (req.query && req.query.tenant) {
|
||||
return req.query.tenant;
|
||||
}
|
||||
|
||||
// Default to 'default' tenant for backward compatibility
|
||||
return 'default';
|
||||
// Return null for localhost without tenant info
|
||||
if (hostname && hostname.startsWith('localhost')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Default to null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authentication configuration for tenant
|
||||
*/
|
||||
async getTenantAuthConfig(tenantId) {
|
||||
const tenant = await Tenant.findOne({ where: { slug: tenantId } });
|
||||
const TenantModel = this.models ? this.models.Tenant : Tenant;
|
||||
const tenant = await TenantModel.findOne({ where: { slug: tenantId } });
|
||||
if (!tenant) {
|
||||
// Return default local auth for unknown tenants
|
||||
return {
|
||||
@@ -137,7 +177,8 @@ class MultiTenantAuth {
|
||||
|
||||
try {
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
||||
const user = await User.findByPk(decoded.userId, {
|
||||
const UserModel = this.models ? this.models.User : User;
|
||||
const user = await UserModel.findByPk(decoded.userId, {
|
||||
attributes: ['id', 'username', 'email', 'role', 'is_active', 'tenant_id']
|
||||
});
|
||||
|
||||
@@ -315,7 +356,7 @@ class MultiTenantAuth {
|
||||
*/
|
||||
async validateTenantAccess(userId, tenantSlug) {
|
||||
try {
|
||||
const { User, Tenant } = require('../models');
|
||||
const { User, Tenant } = this.models || require('../models');
|
||||
|
||||
// Find the user
|
||||
const user = await User.findByPk(userId, {
|
||||
|
||||
Reference in New Issue
Block a user