You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is your feature request related to a problem? Please describe.
openwisp-radius currently does not enforce Organization.is_active.
As a result, disabling an organization has little practical effect on RADIUS operations. A disabled organization can continue to:
authenticate users through FreeRADIUS;
create and update accounting sessions;
register users and memberships;
issue and validate tokens;
send SMS verification messages;
perform social and SAML registration flows;
emit CoA/Disconnect requests;
execute asynchronous tasks that were queued before the organization was disabled.
This behavior is inconsistent with the disabled-organization policy being introduced in openwisp/openwisp-users#522, whose goal is to make disabled organizations effectively read-only while still allowing auditing, cleanup, and deletion of existing records.
Describe the solution you'd like
flowchart TD
A["Disabled Organization"]
A --> B["BLOCK access-producing operations"]
B --> B1["Authentication"]
B1 --> B2["Authorization"]
B2 --> B3["Registration"]
B3 --> B4["Tokens"]
B4 --> B5["SMS / Social / SAML"]
B5 --> B6["CoA / Disconnect"]
A --> C["ACCOUNTING exception"]
C --> C1["Start → BLOCK"]
C1 --> C2["Stop → ALLOW"]
C2 --> C3["Interim-Update → ALLOW"]
C3 --> C4["Session cleanup → ALLOW"]
A --> D["CRUD policy"]
D --> D1["Create / Update → BLOCK"]
D1 --> D2["Read / Delete → ALLOW"]
A --> E["Defense in depth"]
E --> E1["Invalidate auth cache"]
E1 --> E2["Invalidate organization RadiusTokens only"]
E2 --> E3["Revalidate queued Celery tasks"]
Loading
Adopt the disabled-organization policy defined in openwisp/openwisp-users#522 and extend it to cover RADIUS-specific operations.
Write protection
Reuse the admin, DRF, model-validation, and active-organization helpers introduced by openwisp/openwisp-users#522 so that objects belonging to disabled organizations cannot be created or modified.
Read and delete operations must remain available.
Authentication and credential issuance
Authentication and credential-related operations must be denied when the organization is disabled, including:
FreeRADIUS API authentication;
user authorization;
token issuance and validation;
registration flows;
SMS verification flows;
social authentication;
SAML authentication;
CoA generation.
Cache invalidation
The current FreeRADIUS authentication flow relies on cached organization credentials that remain valid after an organization is disabled.
Disabling an organization must immediately invalidate all authentication-related cache entries and credentials so that authentication stops taking effect without waiting for cache expiration.
Authentication code should also explicitly verify Organization.is_active as a defense-in-depth measure.
Asynchronous operations
Operations executed through Celery must revalidate organization state when they start executing.
This prevents work that was queued while an organization was active from continuing after the organization has been disabled.
Accounting exceptions
Some accounting operations represent cleanup of already established sessions rather than creation of new activity.
To preserve network correctness:
accounting Start requests should be blocked;
accounting Stop and Interim-Update requests should remain allowed;
session cleanup and maintenance tasks should continue to operate normally.
Scope of the block: per-organization context, not per-user
The guard is scoped to the organization context of each request, not to the user.
A user who belongs to two organizations — organization A (active) and organization B (disabled) — is not locked out globally. Requests resolved to organization A continue to succeed, while requests resolved to organization B are rejected.
FreeRADIUS uuid/token authentication path
In api/freeradius_views.py, the organization is determined from the token or NAS that issued the request. Each request is evaluated independently, therefore blocking organization B must not affect authentication requests that belong to organization A.
REST API path
For endpoints such as /api/v1/radius/<org_slug>/..., the organization is explicitly determined from the URL. The guard therefore applies naturally on a per-organization basis.
RADIUS token authentication path
The radius-token authentication flow behaves differently.
RadiusToken is currently a one-per-user resource and the cache["rt-{username}"] entry maps a username to the organization associated with that token.
As a consequence, radius-token authentication is effectively bound to the user's current organization. If that token currently belongs to a disabled organization, authentication is rejected until a new token is obtained through an active organization, which updates both the token and the cache entry.
This is therefore a current-organization authentication model rather than a simultaneous multi-organization authentication model.
For this reason, cache invalidation performed during organization disablement must be scoped to the affected organization only:
invalidate that organization's OrganizationRadiusSettings cache entries;
invalidate only RadiusToken objects belonging to the disabled organization.
Disabling organization B must never invalidate authentication state belonging to organization A.
Goals
Make Organization.is_active a first-class enforcement mechanism throughout openwisp-radius.
Blockers
Is your feature request related to a problem? Please describe.
openwisp-radiuscurrently does not enforceOrganization.is_active.As a result, disabling an organization has little practical effect on RADIUS operations. A disabled organization can continue to:
This behavior is inconsistent with the disabled-organization policy being introduced in openwisp/openwisp-users#522, whose goal is to make disabled organizations effectively read-only while still allowing auditing, cleanup, and deletion of existing records.
Describe the solution you'd like
flowchart TD A["Disabled Organization"] A --> B["BLOCK access-producing operations"] B --> B1["Authentication"] B1 --> B2["Authorization"] B2 --> B3["Registration"] B3 --> B4["Tokens"] B4 --> B5["SMS / Social / SAML"] B5 --> B6["CoA / Disconnect"] A --> C["ACCOUNTING exception"] C --> C1["Start → BLOCK"] C1 --> C2["Stop → ALLOW"] C2 --> C3["Interim-Update → ALLOW"] C3 --> C4["Session cleanup → ALLOW"] A --> D["CRUD policy"] D --> D1["Create / Update → BLOCK"] D1 --> D2["Read / Delete → ALLOW"] A --> E["Defense in depth"] E --> E1["Invalidate auth cache"] E1 --> E2["Invalidate organization RadiusTokens only"] E2 --> E3["Revalidate queued Celery tasks"]Adopt the disabled-organization policy defined in openwisp/openwisp-users#522 and extend it to cover RADIUS-specific operations.
Write protection
Reuse the admin, DRF, model-validation, and active-organization helpers introduced by openwisp/openwisp-users#522 so that objects belonging to disabled organizations cannot be created or modified.
Read and delete operations must remain available.
Authentication and credential issuance
Authentication and credential-related operations must be denied when the organization is disabled, including:
Cache invalidation
The current FreeRADIUS authentication flow relies on cached organization credentials that remain valid after an organization is disabled.
Disabling an organization must immediately invalidate all authentication-related cache entries and credentials so that authentication stops taking effect without waiting for cache expiration.
Authentication code should also explicitly verify
Organization.is_activeas a defense-in-depth measure.Asynchronous operations
Operations executed through Celery must revalidate organization state when they start executing.
This prevents work that was queued while an organization was active from continuing after the organization has been disabled.
Accounting exceptions
Some accounting operations represent cleanup of already established sessions rather than creation of new activity.
To preserve network correctness:
Startrequests should be blocked;StopandInterim-Updaterequests should remain allowed;Scope of the block: per-organization context, not per-user
The guard is scoped to the organization context of each request, not to the user.
A user who belongs to two organizations — organization A (active) and organization B (disabled) — is not locked out globally. Requests resolved to organization A continue to succeed, while requests resolved to organization B are rejected.
FreeRADIUS uuid/token authentication path
In
api/freeradius_views.py, the organization is determined from the token or NAS that issued the request. Each request is evaluated independently, therefore blocking organization B must not affect authentication requests that belong to organization A.REST API path
For endpoints such as
/api/v1/radius/<org_slug>/..., the organization is explicitly determined from the URL. The guard therefore applies naturally on a per-organization basis.RADIUS token authentication path
The radius-token authentication flow behaves differently.
RadiusTokenis currently a one-per-user resource and thecache["rt-{username}"]entry maps a username to the organization associated with that token.As a consequence, radius-token authentication is effectively bound to the user's current organization. If that token currently belongs to a disabled organization, authentication is rejected until a new token is obtained through an active organization, which updates both the token and the cache entry.
This is therefore a current-organization authentication model rather than a simultaneous multi-organization authentication model.
For this reason, cache invalidation performed during organization disablement must be scoped to the affected organization only:
OrganizationRadiusSettingscache entries;RadiusTokenobjects belonging to the disabled organization.Disabling organization B must never invalidate authentication state belonging to organization A.
Goals
Organization.is_activea first-class enforcement mechanism throughoutopenwisp-radius.Deliverables / Work items
A. Authentication & credentials — BLOCK
Organization.is_activeguard to FreeRADIUS authentication.Organization.is_activeguard to authorization flows.RadiusTokenstate when an organization is disabled.B. Accounting
Startrequests for disabled organizations.Stoprequests.Interim-Updaterequests.C. Registration, token and SMS flows
D. CoA and asynchronous tasks
E. Admin and CRUD protections
Reference: OpenWISP Device Operation Analysis