15 de August de 2026
Como Criar Autenticação de API via Bearer Token e Estruturar Respostas com HttpData na MuCRM
Aprenda o fluxo completo de autenticação via API na MuCRM: rotas com rate limit, validação, criação de Bearer Tokens e formatação limpa com HttpData e relacionamentos aninhados.
Como Criar Autenticação de API via Bearer Token e Estruturar Respostas com HttpData
Criar APIs seguras e padronizadas é essencial para conectar launchers de jogos, bots do Discord, painéis administrativos, aplicações web e outros sistemas externos.
Prefere em vídeo? Este tutorial também está disponível no nosso canal oficial no YouTube.
Neste tutorial, você vai aprender a implementar o ciclo completo de autenticação via Bearer Token, incluindo:
- Proteção contra tentativas excessivas com
RateLimiter. - Controle de acesso às rotas através de Middleware.
- Autenticação utilizando Bearer Token.
- Criação e revogação de tokens.
- Padronização das respostas utilizando
HttpData. - Transformação de relacionamentos em estruturas JSON.
- Consumo da API por aplicações externas.
1. Definindo as Rotas da API
As rotas de API devem desativar a verificação de CSRF, já que não são baseadas em formulários web tradicionais.
Também podemos separar as rotas públicas das rotas que exigem autenticação.
No arquivo de rotas da aplicação:
<?php
/**
* Rotas de API.
*/
use MUCRM\Engine\Support\Facades\Router;
use MUCRM\Http\Controllers\Api\AuthController;
Router::group([
'prefix' => 'api',
'withoutCsrf' => true
], function () {
/**
* Rota pública de autenticação.
*/
Router::post('/login', [
AuthController::class,
'login'
]);
/**
* Rotas protegidas por autenticação.
*/
Router::group([
'middleware' => ['auth:api']
], function () {
Router::post('/me', [
AuthController::class,
'me'
]);
Router::post('/logout', [
AuthController::class,
'logout'
]);
});
});
Rotas disponíveis
| Método | Endpoint | Autenticação |
|---|---|---|
POST |
/api/login |
Não |
POST |
/api/me |
Bearer Token |
POST |
/api/logout |
Bearer Token |
O fluxo de autenticação funciona da seguinte maneira:
Cliente
│
│ POST /api/login
▼
AuthController
│
├── Valida credenciais
├── Verifica RateLimiter
├── Localiza usuário
└── Gera Bearer Token
│
▼
Cliente recebe token
│
│ Authorization: Bearer TOKEN
▼
Middleware auth:api
│
▼
Endpoint protegido
2. Estruturando os Dados com HttpData
A classe HttpData é responsável por controlar quais informações serão expostas pela API.
Em vez de enviar diretamente todos os atributos de um Model para o cliente, criamos classes específicas para transformar os dados em uma estrutura apropriada para respostas HTTP.
Isso permite:
- Controlar os campos expostos.
- Renomear propriedades.
- Esconder informações internas.
- Serializar relacionamentos.
- Criar estruturas JSON consistentes.
- Reutilizar os mesmos Data Layers em diferentes endpoints.
A estrutura poderá ficar assim:
app/
└── Http/
└── Data/
├── GuildData.php
├── CharacterData.php
└── UserData.php
2.1. GuildData
Crie o arquivo:
app/Http/Data/GuildData.php
<?php
namespace MUCRM\Http\Data;
use MUCRM\Engine\Http\Data as HttpData;
class GuildData extends HttpData
{
public function toArray(): array
{
return [
'name' => $this->G_Name,
'mark' => $this->G_Mark,
'score' => $this->G_Score,
];
}
}
A classe transforma os dados da Guild em uma estrutura mais limpa para a API.
Por exemplo:
{
"name": "DarkKnights",
"mark": "ABC123",
"score": 12500
}
2.2. CharacterData
Agora podemos criar o Data responsável pelos personagens.
Crie:
app/Http/Data/CharacterData.php
<?php
namespace MUCRM\Http\Data;
use MUCRM\Engine\Http\Data as HttpData;
class CharacterData extends HttpData
{
public function toArray(): array
{
return array_merge([
'name' => $this->Name,
'level' => $this->cLevel,
'class' => $this->Class,
], $this->mergeRelation(
'guild',
GuildData::class
));
}
}
Aqui utilizamos:
$this->mergeRelation(
'guild',
GuildData::class
)
Isso permite que o relacionamento guild seja transformado utilizando GuildData.
Assim, o personagem pode ser retornado juntamente com os dados da Guild.
2.3. UserData
Por último, vamos criar o Data responsável pelo usuário.
Crie:
app/Http/Data/UserData.php
<?php
namespace MUCRM\Http\Data;
use MUCRM\Engine\Http\Data as HttpData;
class UserData extends HttpData
{
public function toArray(): array
{
return array_merge([
'login' => $this->memb___id,
], $this->mergeRelation(
'characters',
CharacterData::class
));
}
}
Agora temos uma cadeia de transformação:
UserData
│
└── characters
│
└── CharacterData
│
└── guild
│
└── GuildData
Isso permite construir respostas complexas sem precisar montar manualmente todo o JSON dentro do Controller.
3. Criando o AuthController
Agora vamos criar o Controller responsável pela autenticação da API.
Crie:
app/Http/Controllers/Api/AuthController.php
<?php
namespace MUCRM\Http\Controllers\Api;
use MUCRM\Engine\Support\RateLimiter;
use MUCRM\Engine\Support\Request;
use MUCRM\Http\Controllers\Controller;
use MUCRM\Http\Data\UserData;
use MUCRM\Models\User;
/**
* Autenticação da API utilizando Bearer Token.
*/
class AuthController extends Controller
{
/**
* Login da API.
*
* POST /api/login
*
* Body:
* username
* password
*/
public function login(Request $request)
{
$rateLimiter = new RateLimiter();
$key = 'api_login_attempts:' . $request->ip();
/**
* Limita a quantidade de tentativas
* de login por IP.
*/
if ($rateLimiter->tooManyAttempts($key, 5)) {
$seconds = $rateLimiter->availableIn($key);
return $request->json([
'success' => false,
'code' => 429,
'error' => 'Muitas tentativas. Tente novamente em ' . $seconds . ' segundos.',
], 429);
}
/**
* Validação dos dados enviados.
*/
$credentials = $request->validate([
'username' => 'required|string|min:4|max:10',
'password' => 'required|string|max:10',
], [
'username.required' => 'Informe seu login.',
'password.required' => 'A senha é obrigatória.',
]);
/**
* Busca o usuário.
*/
$user = User::where(
'memb___id',
$credentials['username']
)
->where(
'memb__pwd',
$credentials['password']
)
->first();
/**
* Credenciais inválidas.
*/
if (!$user) {
$rateLimiter->hit($key, 2);
return $request->json([
'success' => false,
'code' => 401,
'error' => 'Usuário ou senha incorretos.',
], 401);
}
/**
* Verifica se a conta está bloqueada.
*/
if (((int) ($user->bloc_code ?? 0)) === 1) {
$rateLimiter->hit($key, 2);
return $request->json([
'success' => false,
'code' => 403,
'error' => 'Conta bloqueada.',
], 403);
}
/**
* Login realizado com sucesso.
*
* Limpa as tentativas anteriores.
*/
$rateLimiter->clear($key);
/**
* Gera o Bearer Token.
*/
$token = $user->createLoginToken()->plainTextToken;
return $request->json([
'success' => true,
'token' => $token,
]);
}
/**
* Retorna o usuário autenticado.
*
* POST /api/me
*
* Middleware:
* auth:api
*/
public function me(Request $request)
{
$user = $request->user();
$user->load('characters');
return $request->json([
'success' => true,
'user' => UserData::make($user),
]);
}
/**
* Logout da API.
*
* POST /api/logout
*
* Middleware:
* auth:api
*/
public function logout(Request $request)
{
$request->user()->logout();
return $request->json([
'success' => true,
]);
}
}
4. Entendendo o RateLimiter
O RateLimiter protege o endpoint de login contra tentativas excessivas.
Primeiro criamos uma chave baseada no IP:
$key = 'api_login_attempts:' . $request->ip();
Depois verificamos se o limite foi atingido:
if ($rateLimiter->tooManyAttempts($key, 5)) {
// ...
}
Neste exemplo, o limite é de 5 tentativas.
Quando o limite é atingido, podemos descobrir quanto tempo falta para que novas tentativas sejam permitidas:
$seconds = $rateLimiter->availableIn($key);
Quando o usuário informa credenciais incorretas, registramos uma nova tentativa:
$rateLimiter->hit($key, 2);
Após um login bem-sucedido, removemos o controle daquele IP:
$rateLimiter->clear($key);
5. Gerando o Bearer Token
Depois que as credenciais são validadas, o token é criado através do usuário:
$token = $user->createLoginToken()->plainTextToken;
Esse token deve ser enviado ao cliente.
A resposta será:
{
"success": true,
"token": "1|a8f9c2e4b7...plainTextToken"
}
O cliente deve armazenar o token de maneira segura.
6. Consumindo a API na Prática
6.1. Realizando o Login
Faça uma requisição:
POST /api/login
Envie os dados em JSON:
{
"username": "meuusuario",
"password": "minhasenha"
}
Em caso de sucesso:
{
"success": true,
"token": "1|a8f9c2e4b7...plainTextToken"
}
Guarde o token retornado para realizar as próximas requisições autenticadas.
7. Consultando o Usuário Autenticado
Agora podemos utilizar:
POST /api/me
Como essa rota está dentro do grupo:
'middleware' => ['auth:api']
ela exige um Bearer Token válido.
O Header HTTP deve conter:
Authorization: Bearer 1|a8f9c2e4b7...plainTextToken
A requisição será processada pelo Middleware de autenticação antes de chegar ao Controller.
7.1. Resposta
O UserData será responsável pela transformação do usuário.
Exemplo:
{
"success": true,
"user": {
"login": "meuusuario",
"characters": [
{
"name": "DragonKnight",
"level": 400,
"class": 1
}
]
}
}
Caso o relacionamento de Guild também esteja carregado, o CharacterData poderá incluir os dados transformados pelo GuildData.
8. Fazendo Logout
Para revogar o token utilizado atualmente, envie:
POST /api/logout
Com o Header:
Authorization: Bearer 1|a8f9c2e4b7...plainTextToken
O Controller executará:
$request->user()->logout();
E retornará:
{
"success": true
}
9. Estrutura Final
Ao finalizar o tutorial, a estrutura relacionada à API ficará semelhante a:
app/
├── Http/
│ ├── Controllers/
│ │ ├── Api/
│ │ │ └── AuthController.php
│ │ │
│ │ └── Controller.php
│ │
│ └── Data/
│ ├── GuildData.php
│ ├── CharacterData.php
│ └── UserData.php
│
└── Models/
└── User.php
E as rotas:
/api/login
/api/me
/api/logout
10. Fluxo Completo da Autenticação
A arquitetura completa pode ser visualizada assim:
CLIENTE
│
│
▼
POST /api/login
│
▼
AuthController
│
┌────────┴────────┐
│ │
▼ ▼
RateLimiter Validação
│ │
└────────┬────────┘
│
▼
User Model
│
▼
Credenciais OK?
│ │
NÃO SIM
│ │
▼ ▼
401/403 Bearer Token
│
▼
CLIENTE
│
│ Authorization:
│ Bearer TOKEN
▼
Middleware
auth:api
│
▼
Endpoint protegido
│
▼
Controller
│
▼
HttpData
│
▼
JSON Response
Conclusão
Com o sistema de autenticação via Bearer Token, o RateLimiter, o Middleware auth:api e a camada HttpData, a API da MuCRM possui uma estrutura organizada para atender diferentes aplicações.
Essa arquitetura permite que a mesma API seja consumida por:
- Launchers.
- Bots do Discord.
- Sites externos.
- Dashboards.
- Aplicações desktop.
- Aplicações mobile.
- Outros serviços integrados.
O ponto principal é manter cada responsabilidade separada:
Router
↓
Middleware
↓
Controller
↓
Model
↓
HttpData
↓
JSON
Dessa forma, a API permanece organizada, segura e fácil de expandir conforme novos endpoints forem adicionados à framework.