Autenticação e Autorização no Hasura

Permissões, Autenticação, e Autorização

O Hasura exige que em cada requisição seja informado duas session variables:

  • X-Hasura-Default-Role
  • X-Hasura-Allowed-Roles

Além disso, é praticamente indispensável enviar as seguintes session variable (via Header ou WebHook):

  • X-Hasura-Role
  • X-Hasura-User-Id

A Role faz a request automaticamente assumir uma das roles cadastradas no sistema.

Com o User-Id é possível fazer regras dentro das permissões ou ajudar o WebHook a identificar e colocar cabeçalhos importantes para a autorização no Hasura.

Quais as limitações de Autorização no Hasura?

Não é possível definir multiple column + row permission rules for the same role.

Só é possível assumir uma role por request.

Como o Hasura sabe que uma request foi enviada de um determinado usuário?

Para realizar autenticação no Hasura pode-se escolher 2 caminhos: JWT puro ou WebHook + JWT.

Estas session variables podem já estar todas prontas dentro do JWT ou Header, ou podem ser inseridas pelo WebHook. No final das contas o resultado das duas é igual.

Estratégias para autenticação multi tenant

Sistemas multi tenant são aqueles em que várias empresas compartilham uma mesma tabela. Em tabelas que compartilham dados de várias empresas, os dados são separados através de alguma coluna tipo id_empresa, ou em casos mais complexos, através de alguma FOREIGN KEY que leve até a coluna id_empresa.

No final das contas é obrigatório que tenhamos detro das session variables o tenant_id e a role usada para operá-lo.

Opção 1 - Enviar tenant_id, role e user_id

Nesta opção o hasura recebe via session variables um tenant_id, uma role e o user_id.

O perigo desta opção é o próprio cliente informa o tenant_id e a role ao Hasura. Se deixarmos isto nas mãos do usuário sem nenhuma verificação, o usuário pode se conceder uma role de administrador e modificar qualquer tenant que desejar.

Para termos segurança com esta abordagem é necessário termos uma tabela de permissões onde estas são verificadas em cada requisição pelas permissões do Hasura.

Esta tabela precisa conter:
user_id, tenant_id, role

(CONTRAS)

Uma request poderá operar apenas um tenant por vez.

O tenant_id precisa estar presente em todas as tabelas que deseja acessar. Se não existir, é preciso criar uma VIEW que traga o tenant_id.

Esta é a abordagem ensinada neste artigo do blog oficial do Hasura:
https://hasura.io/blog/authorization-rules-for-multi-tenant-system-google-cloud/

Opção 2 - Eviar client_id e um json com permissões em forma de árvore:

Seria uma boa saída, entretanto o Hasura não possui operadores de JSON para session variables. Talvez quando existir esta opção seja possível.

Opção 3 - Enviar role que representa a role + tenant

Criar uma role pra cada combinação de tenant + role, tipo:

admin-tenant-1
admin-tenant-2
user-tenant-1
user-tenant-2

(CONTRAS)

É preciso definir MUITAS regras no hasura, várias repetidas. Isso traz muitos problemas. Não é uma boa saída.

Opção 4 - Enviar várias roles, cada uma com um array com tenant_ids dentro

Criar uma session variable para cada role que o usuário desempenha. Dentro de cada role, armazenar os tenants.

Temos 3 roles: manager, reader, administrator

x-hasura-administrator={1,2,3}
x-hasura-manager={4,5,6}
x-hasura-reader={7}

E aí nas permissões, basta usar o operador _in.
https://hasura.io/docs/1.0/graphql/core/queries/query-filters.html#list-based-search-operators-in-nin

(CONTRAS)

Em cada request, o usuário deve informar qual role está usando. Logo o usuário deve saber de antemão o que ele pode pedir ou não para o Hasura. Isso não deve ser problema pois essas infos estão dentro do JWT.

O JWT pode ficar grande dependendo da quantidade de permissões.

Opção 5 - Cada role é um tenant, e os níveis de permissão estão em outra session variable

Não é possível. Se cada role é um tenant não é possível definir diferentes permissões para cada tenant.

Opção 6 - Usar apenas a role "user" e todo o controle ser feito por meio de tabelas de permissões via _exists e do user_id

Funciona! Mas é uma forma muito limitada de permissão porque todas as requisições serão feitas em nome de uma única role do sistema e nela só se pode definir um tipo de permissão.

Conclusão

As opções 1, 4 são as mais viáveis.

Referências

Hasura Roles Example
https://hasura.io/blog/hasura-authorization-system-through-examples/

Hasura Multi Tenancy
https://hasura.io/blog/authorization-rules-for-multi-tenant-system-google-cloud/

Padrões de controle de acesso com Hasura
https://hasura.io/blog/access-control-patterns-with-hasura-graphql-engine/

You should also read:

Hasura, PostgreSQL + GraphQL

Use o docker. Tutorial oficial - Instalando Hasura e PostgreSQL com Docker https://docs.hasura.io/1.0/graphql/manual/getting-started/docker-simple.html Configurando o Hasura pelo painel de administração, criando tabelas e…