Setting up a task-based passwordless auth structure

[X-Posting from Discord]

Looking for some feedback on a design I just got done implementing.

Let’s say I’m making something like a DocuSign clone. My app has two types of users: Lawyers and Clients. They Lawyers upload the Documents and then generate a secure link that the Clients click on, and get access to a document to then sign.

I’ve implemented the Lawyers as normal Users, with their own roles (owners, admins, readers, writers etc).
For the Clients, I’ve implemented the following:

  • A DocumentAccess table that links to a Document and has a UUID token. An entry in this gets generated when a Lawyer wants to give access to a Client
  • A custom function that gets called when the Client clicks on the access link. This adds a signed cookie to their session referring the DocumentAccess token
  • A graphQL ContextFunction that verifies the cookie and adds the DocumentAccess token to the context (actually keeps a list of tokens)
  • A graphQL directive that checks that one of the tokens in the context links to the Document that the Client is trying to sign

Does this make sense? Is there a better way to do all of this? I DON’T want to just add Clients as Users and give them a client role, because that leads to other sorts of security issues (e.g.: a passwordless login will enable a user-agent to see all other Documents a client has access to, and can be misused by a bad lawyer)