kroo / reflex-clerk

A reflex custom component library for clerk
14 stars 7 forks source link

Better Pattern for Protected State Vars #8

Open kroo opened 2 months ago

kroo commented 2 months ago

Investigate the following two methods for ensuring state vars are not leaked to unauthenticated users:

  1. Inherit from a "protected state" class, which does not allow any of the fields to be returned unless the user is logged in.
class State(clerk.ClerkProtectedState):
    field1: int
    field2: str
  1. Annotate a state class or var with a decorator, perhaps named auth_required, or protect, which allows you to specify 'permission' or 'role', similar to the react component:
@protect(permission="org:invoices:create")
class State(rx.State):
    field1: int
    field2: str

class State2(rx.State):
    field1: Protected[int, Role("org:billing")]
    field2: Protected[str, Permission("org:invoices:create")]
    field3: Protected[bool]

    @rx.var
    @protect(role="org:billing")
    def field4(self) -> str:
        return self._field2

Approach 1 is simple, encourages the substate behavior described above, and makes accessing the signed in user information straight forward... Approach 2 feels pretty magical, and allows for much finer-grained permissions, but has the dangerous default of allowing information to leak if you don't wrap one of the fields...

(Discord thread here)