Corvia / django-tenant-users

Adds global user authentication and tenant-specific permissions to django-tenants.
https://django-tenant-users.rtfd.io
MIT License
334 stars 65 forks source link

Users are able to login into any tenants. #661

Closed thapabishwa closed 1 week ago

thapabishwa commented 3 weeks ago

Hi all, I'm trying to build a multi-tenant DRF API and I've configured django-tenants. Now I'm attempting to use django-tenant-users as it offers Global Authentication and Tenant-Specific Permissions.

I think I've somewhat configured django-tenant-users. But I have problems because all users can access all tenants(including the public schema).

My project is best described as follows:

Right now, a user created in a tenant is able to login to an unrelated tenant as well as the Public Tenant and view/edit their private data.

I've followed the setup instructions as mentioned in the docs.

I've already attempted remediations mentioned in https://github.com/Corvia/django-tenant-users/issues/593.

Like mentioned in #593, I'm also using tenant.add_user method to add new users to the newly created tenant.

Any help would be appreciated.


# APPS
# ------------------------------------------------------------------------------
DJANGO_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "django.forms",

]
THIRD_PARTY_APPS = [
    "crispy_forms",
    "crispy_bootstrap5",
    "django_tenants",
    "rest_framework",
    "rest_framework.authtoken",
    "tenant_users.tenants",
    "tenant_users.permissions",
    "corsheaders",
    "drf_spectacular",
    "organizations",
    "users",
    "drf_simple_invite",
    "django_rest_passwordreset",
    "corsheaders",
]

SHARED_APPS = DJANGO_APPS + THIRD_PARTY_APPS

TENANT_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "django.forms",
    "tenant_users.permissions",
    # Your stuff: custom apps go here
    "backend.app1"
]

DATABASE_ROUTERS = (
    'django_tenants.routers.TenantSyncRouter',
)

TENANT_MODEL = "organizations.Organization"

TENANT_DOMAIN_MODEL = "organizations.Domain"

AUTHENTICATION_BACKENDS = ("tenant_users.permissions.backend.UserBackend",)

MIDDLEWARE = [
    "django_tenants.middleware.main.TenantMainMiddleware",
    "django.middleware.security.SecurityMiddleware",
    "corsheaders.middleware.CorsMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.locale.LocaleMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.common.CommonMiddleware",
    "tenant_users.tenants.middleware.TenantAccessMiddleware",
]
class Organization(TenantBase):
    id = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4)
    name = models.CharField(max_length=100)
    redacted_field1 =  models.DateField(blank=True, null=True)
    redacted_field2 = models.BooleanField(default=True)

    # default true, schema will be automatically created and synced when it is saved
    auto_create_schema = True

class Domain(DomainMixin):
    pass

PS: Issue https://github.com/Corvia/django-tenant-users/issues/588 was specifically helpful when I had circular dependency errors.

Expected Behavior

A user created in a tenant should not be able to login to an unrelated tenant as well as the Public Tenant and view/edit their private data.

Actual Behavior

A user created in a tenant is able to login to an unrelated tenant as well as the Public Tenant and view/edit their private data.

Dresdn commented 3 weeks ago

Let's make sure we're under the correct impressions here @thapabishwa. The entire point of django-tenant-users is to allow users to log in to any tenant via a centralized User model. I see you have the TenantAccessMiddleware, so my question would be: For a user with this erroneous behavior, what does their UserModel.tenants.all() come back with? The middleware that is part of this package allows the user to access any tenant they've been "added to."

If that's not what you want, then I suggest rolling your own middleware to control tenant access.