authorize! w kontrolerze to dobry początek. W wielotenantowym SaaS nie jest jednak ostateczną granicą bezpieczeństwa.
Ta sama operacja może zostać uruchomiona przez żądanie HTTP, zadanie w tle, import, konsolę administracyjną albo inną komendę biznesową. Jeżeli reguła istnieje tylko w kontrolerze, bezpośrednie wywołanie serwisu może ją ominąć.
Pełny kontekst dostępu
Krytyczna komenda powinna otrzymać jawny kontekst wykonania:
- aktora,
- organizację,
- członkostwo i rolę organizacyjną,
- rolę lub uprawnienie modułowe,
- informację o impersonacji,
- źródło wywołania.
Nie chodzi o przekazywanie luźnego hasha przez całą aplikację. Warto użyć małego obiektu wartości, który opisuje zweryfikowany dostęp i ma jednoznaczny kontrakt.
Controller / Job / Import
↓
Verified Access Context
↓
Business Command
↓
Domain Decision
Trzy warstwy, trzy odpowiedzialności
UI pokazuje tylko działania dostępne dla użytkownika. To redukuje frustrację i prowadzi przez proces, ale nie stanowi zabezpieczenia.
Policy chroni endpoint oraz zakres zapytania. Powinna szybko odrzucić niedozwolone żądanie i nie dopuścić, aby rekord z innej organizacji został w ogóle załadowany.
Komenda biznesowa ponownie weryfikuje warunki istotne dla operacji. Nie ufa temu, że wywołujący wcześniej zrobił wszystko poprawnie. Dzięki temu zasada działa również poza HTTP.
To nie musi oznaczać potrójnego kopiowania logiki. Wspólny obiekt dostępu może odpowiadać na pytania o członkostwo i uprawnienia, a policy i komenda używają tego samego kontraktu w różnych rolach.
Tenant scope przed identyfikatorem
Organizacja nie powinna być wywnioskowana z dowolnego parametru przesłanego przez użytkownika. Najpierw wyznaczamy organizacje dostępne dla aktora. Dopiero w tym zakresie szukamy rekordu wskazanego w URL.
current_organization.records.find(params[:id])
Taki porządek ma znaczenie. Poprawny identyfikator obiektu należącego do innego tenantu nadal kończy się bezpiecznym not found, zamiast ujawniać istnienie rekordu albo polegać na późniejszym sprawdzeniu.
W jobach sytuacja jest podobna. Nie wystarczy zapisać samo record_id. Job powinien dostać stabilny kontekst organizacji oraz aktora lub jawnie działać jako system. Po deserializacji ponownie ładuje dane w prawidłowym zakresie.
Impersonacja wymaga dwóch tożsamości
Gdy operator wspiera użytkownika przez impersonację, zdarzenie ma co najmniej dwie osoby: aktora biznesowego oraz rzeczywistego operatora. Autoryzacja musi uwzględniać ograniczenia sesji impersonowanej, a audyt zachować obie tożsamości.
Nie każda operacja dozwolona administratorowi powinna być dostępna podczas impersonacji. Eksporty, zmiany zabezpieczeń lub działania między organizacjami często wymagają bezpośredniej sesji operatora.
Ostateczna zasada
Nie ufaj miejscu, z którego przyszło wywołanie. Ufaj jawnie zweryfikowanemu kontekstowi operacji.
Kontroler, policy i komenda nie konkurują ze sobą. Razem tworzą warstwową ochronę, w której UX jest czytelny, zapytania są ograniczone do tenantu, a domeny nie można ominąć alternatywną ścieżką wykonania.
To podejście jest częścią szerszych standardów technologicznych Thinqcraft. Jeśli porządkujesz autoryzację w istniejącym systemie Rails, zacznij rozmowę.

