Executando verificação de segurança...
3

O que eu faço com o Laravel:

1 - Minha rota está protegida pelo middleware de autenticação.

2 - Verifico direto no usuário autenticado qual é o tenant dele, para que não seja possível uma modificação maliciosa.

3 - Busco todos os usuários, filtrando pelo tenant, e envio a resposta;

Fica assim


// Rota index
Route::get('usuarios', [UsuarioController::class, 'index'])->middleware(['auth']);

// Método
public function index(){
    // usuarios do tenant
    $usuarios = auth()->user()->tenant->usuarios()->get();
    
    // response
    return response()->json($usuarios);
    
}
Carregando publicação patrocinada...
1
3

Sim, utilizo o id do model, mas faço validações no método para garantir a segurança.

// Rota de usuários - (index, show, create, store, edit, update e destroy)
Route::resource('usuarios', UsuarioController::class)->middleware(['auth']);

// método edit
public function edit(Usuario $usuario){
    // usuário não pertence ao mesmo tenant -> retorno erro e passo uma mensagem diferente de forbidden pra não chamar atenção
    abort_if($usuario->tenant_id !== auth()->user()->tenant_id, 403, 'Página não encontrada');
    
    // carrega a view com os dados do usuário
    return view('view-edit', compact('usuario'));
}

// método update
public function update(Request $request, Usuario $usuario){
    // $request -> tenho acesso a tudo do request
    // $usuario -> tenho acesso ao model do usuario que foi passado por parâmetro
    // posso validar diversas coisas aqui sobre esse usuário para garantir a segurança
    
    // exemplo: acesso negado se o usuário acessado pertence a um tenant diferente
    abort_if($usuario->tenant_id !== auth()->user()->tenant_id, 403);
}

Normalmente no lugar do Request eu crio uma classe Form Request separada para cuidar só do request e o código ficar mais limpo e organizado, mas coloquei dessa forma para facilitar o entendimento.

A rota gerada fica assim: https://dominio.com.br/usuarios/id

Dentro do método update você pode realizar validações como o exemplo fornecido, aí vai da sua regra de negócio, o quê deseja fazer.

O exemplo acima poderia se tratar de um usuário administrador que tem acesso ao gerenciamento de usuários do sistema, mas ele tenta acessar um id na url que não pertence ao tenant dele. Dessa forma o sistema irá abortar a requisição e gerar um acesso negado.

1
0

O problema dessa abordagem é que você expõe o ID de outros tenants, então caso o middleware falhe, o usuário pode conseguir acessar algo indevido. Além disso alguem consegue extrair a quantidade de registros por exemplo só pelo numeral do ID.

1

Na verdade não, acredito que houve um equívoco da sua parte, olhe o código postado abaixo em outra resposta minha e entenderá. Inclusive dá pra fazer esse filtro de tenant por global scope de forma automática.

A validação do tenant não se dá no middleware e sim no método que está sendo acessado. O middleware só me garante que quem acessa aquela rota está logado.

Quando usuário autenticado acessar o registro de um usuário (exemplo: /usuarios/3), o método recebe essa requisição, e eu valido se o usuário 3 pertence ao mesmo tenant de quem está solicitando as informações. Se sim, continuo com minha regra de negócio. Caso contrário, aborto a requisição e vira um acesso negado.

Sendo assim, não há problemas de segurança. Um usuário do tenant 2 não consegue acessar usuários do tenants 5.

Em relação à quantidade de usuários pelo id, não é uma informação sensível para o meu caso, ainda mais que será retornado uma página de erro por não ser do mesmo tenant que o usuário autenticado. O usuário comum que pode fuçar nem sabe diferenciar se é acesso negado ou página não encontrada.