Site

Integrações Social (OAuth) v4

A MuCRM não embute um provider OAuth completo no Core. O padrão recomendado na v2 é: OAuth no seu plugin → vincular identidade → emitir Bearer MuCRM (ou usar sessão web).


Arquitetura sugerida

Usuário clica "Entrar com Discord"
        │
        ▼
Plugin SocialAuth  ->  redirect OAuth (Discord/Twitch)
        │
        ▼
Callback (withoutCsrf)  ->  troca code por access_token do provedor
        │
        ▼
Busca/cria vínculo (discord_id ↔ id)
        │
        ▼
Sessão web  OU  create_login_token() / create_token('discord', [...])

Callback sem CSRF

use MUCRM\engine\support\facades\uri;
use MUCRM\modules\social_auth\handlers\discord_handler;

uri::get('/oauth/discord/callback', [discord_handler::class, 'callback'])
    ->without_csrf()
    ->name('oauth.discord.callback');
🚨Valide o state
Sempre use state CSRF-like no fluxo OAuth e rejeite callbacks sem state válido — withoutCsrf só remove o token de formulário MuCRM.

Após o OAuth: emitir token MuCRM

$customer = customer::where('id', $account_id)->first_or_fail();

auth::login($customer, 'user');

$token = $customer->create_token('discord', ['profile:read'])->plainTextToken;

return json(['success' => true, 'token' => $token]);

HTTP Client do Core

Use o cliente embutido para falar com as APIs Discord/Twitch:

use MUCRM\engine\http\http;
use MUCRM\engine\support\log;

$response = http::as_form()->post('https://discord.com/api/oauth2/token', [
    'client_id' => config('social.discord.client_id'),
    'client_secret' => config('social.discord.client_secret'),
    'grant_type' => 'authorization_code',
    'code' => $code,
    'redirect_uri' => config('social.discord.redirect'),
]);

if ($response->failed()) {
    log::channel('api')->error('OAuth Discord falhou', ['body' => $response->body()]);
    return json(['error' => 'oauth_failed'], 502);
}

$oauth = $response->json();

Detalhes do client: Cliente HTTP.


Checklist

  • Credenciais em bootstrap/config/ (nunca no repositório público)
  • Callback com withoutCsrf + validação de state
  • Vínculo estável no banco (discord_id, twitch_id)
  • Abilities mínimas no token emitido
  • IP/domínio do callback em auth.allowed se a API estiver fechada