Skip to Content
Autenticação

Autenticação

Este guia fornece uma visão geral do sistema de autenticação OAuth2 do Meaple e ajuda desenvolvedores a entender como utilizá-lo de forma eficaz.

Visão Geral

O Meaple utiliza OAuth 2.0 com PKCE (Proof Key for Code Exchange) para autenticação segura de usuários. O PKCE é obrigatório para todas as integrações, garantindo segurança mesmo sem client secret.

⚠️ Importante: Atualmente não oferecemos suporte para OpenID Connect (OIDC). A autenticação é feita exclusivamente via OAuth 2.0.


Pré-requisitos

Antes de começar, você precisa:

1. Obter o Client ID
O client_id é o ID do seu canal, obtido no painel em https://meaple.com.br 

2. Registrar a Redirect URI
Registre a(s) URL(s) de callback que sua aplicação utilizará

⚠️ Importante: A redirect_uri usada na requisição de autorização deve corresponder exatamente a uma das URIs registradas.

💡 Suporte: Atualmente, o registro de redirect URIs e domínios é feito diretamente no banco de dados. Entre em contato com o suporte para configurar sua aplicação.


Endpoints

EndpointURLDescrição
Authorizationhttps://whitelabel.meaple.app/api/oauth/authorizePágina de login OAuth
Tokenhttps://whitelabel.meaple.app/api/oauth/tokenObter/renovar tokens
User Infohttps://api.meaple.com.br/v1/users/meDados do usuário autenticado

1. Authorization Request

Para redirecionar um usuário para a página de login, construa a URL de autorização com os parâmetros necessários.

Parâmetros Obrigatórios

ParâmetroTipoDescrição
response_typecodeIndica que o fluxo Authorization Code será utilizado
client_idstringID único do seu canal/aplicação
redirect_uristringURL para redirecionamento após autenticação (deve estar registrada)
statestringString aleatória para prevenir ataques CSRF
scopestringEscopos separados por espaço (ex: profile email)
code_challengestringChallenge derivado do code_verifier (PKCE)
code_challenge_methodS256Método de hash utilizado

Parâmetros Opcionais (Customização)

ParâmetroTipoDescrição
themedark | lightTema da página de login
preferred_colorstringCor primária em hex (ex: #fb923c)

Exemplo de URL

https://whitelabel.meaple.app/oauth/sign-in ?response_type=code &client_id=cmkeg9fpq001cmm0mu61qa6ks &redirect_uri=https://seu-app.com/api/auth/callback &state=OaQi-xy2CBAvzrNv_ed7gMuglH5NaoYp &scope=profile+email &code_challenge_method=S256 &code_challenge=1CZBq_T9lnVeGFc44Ph6voMwJj_gLlwp3ECFWjeaGLc &theme=dark &preferred_color=%23fb923c

Verificando se a URL está correta

Ao acessar a URL de autorização, você deve verificar se todos os parâmetros foram configurados corretamente:

❌ Erro - Parâmetros faltando

Se você ver uma mensagem de erro em vermelho “missing required parameters”, verifique se todos os parâmetros obrigatórios estão presentes.

✅ Sucesso - Tela de login

Quando correto, você verá a tela de login com logo do canal, login social, campos de e-mail/senha e links de recuperação.

Tela de login do Meaple

Implementação

const clientId = process.env.MEAPLE_CLIENT_ID; const redirectUri = 'https://seu-app.com/api/auth/callback'; // Gerar PKCE const verifier = await generateCodeVerifier(); const challenge = await generateCodeChallenge(verifier); // Armazenar verifier para usar na próxima etapa sessionStorage.setItem('code_verifier', verifier); // Gerar state para proteção CSRF const state = generateState(); sessionStorage.setItem('oauth_state', state); // Construir URL de autorização const authorizationUrl = new URL('https://whitelabel.meaple.app/oauth/sign-in'); authorizationUrl.searchParams.append('response_type', 'code'); authorizationUrl.searchParams.append('client_id', clientId); authorizationUrl.searchParams.append('redirect_uri', redirectUri); authorizationUrl.searchParams.append('state', state); authorizationUrl.searchParams.append('scope', 'profile email'); authorizationUrl.searchParams.append('code_challenge_method', 'S256'); authorizationUrl.searchParams.append('code_challenge', challenge); // Parâmetros opcionais de customização authorizationUrl.searchParams.append('theme', 'dark'); authorizationUrl.searchParams.append('preferred_color', '#fb923c'); // Redirecionar usuário window.location.href = authorizationUrl.toString();

2. Retrieve Authorization Code

Quando o usuário completa o login com sucesso, ele é redirecionado para a redirect_uri especificada com os seguintes parâmetros:

https://seu-app.com/api/auth/callback?code=AUTH_CODE&state=OaQi-xy2CBAvzrNv_ed7gMuglH5NaoYp

Validação do State

Importante: Sempre valide o parâmetro state para prevenir ataques CSRF.

const urlParams = new URLSearchParams(window.location.search); const code = urlParams.get('code'); const returnedState = urlParams.get('state'); const savedState = sessionStorage.getItem('oauth_state'); if (returnedState !== savedState) { throw new Error('State mismatch - possível ataque CSRF'); } // State válido, prosseguir com a troca do código

3. Obtain Access Token

Para trocar o authorization code por tokens, faça uma requisição POST para o endpoint de token.

Request

const tokenUrl = 'https://whitelabel.meaple.app/api/oauth/token'; const codeVerifier = sessionStorage.getItem('code_verifier'); const body = new URLSearchParams(); body.append('grant_type', 'authorization_code'); body.append('client_id', clientId); body.append('redirect_uri', redirectUri); body.append('code', code); body.append('code_verifier', codeVerifier); // PKCE const response = await fetch(tokenUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body, }); const tokens = await response.json();

Parâmetros

ParâmetroTipoDescrição
grant_typeauthorization_codeTipo de concessão
client_idstringMesmo client_id usado na autorização
redirect_uristringMesmo redirect_uri usado na autorização
codestringCódigo recebido na etapa anterior
code_verifierstringO verifier original usado para gerar o challenge

Response

{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4..." }
CampoTipoDescrição
access_tokenstringToken para acessar a API
token_typeBearerTipo do token
expires_innumberTempo de expiração em segundos
refresh_tokenstringToken para renovar o access_token

4. Refresh Token

Quando o access_token expira, use o refresh_token para obter um novo.

const body = new URLSearchParams(); body.append('grant_type', 'refresh_token'); body.append('client_id', clientId); body.append('refresh_token', refreshToken); const response = await fetch('https://whitelabel.meaple.app/api/oauth/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body, }); const { access_token, expires_in, refresh_token } = await response.json();

5. Get User Info

Com o access_token, você pode obter os dados completos do usuário autenticado.

const response = await fetch('https://api.meaple.com.br/v1/users/me', { headers: { Authorization: `Bearer ${accessToken}`, 'X-Channel-Id': clientId, }, }); const { user } = await response.json();

Response

{ "user": { "id": "cml5kizep000b0vr1uxdq1tte", "name": "John Doe", "email": "johndoe@meaple.com.br", "document": "11111111111", "phoneNumber": "+5511999999999", "birthdate": "2001-01-01T00:00:00.000Z", "role": "ADMIN", "avatar": { "url": "http://localhost:3333/a58de3cb-89b7-423e-bfbd-b95f45de2c5b.png" } } }

Campos do Usuário

CampoTipoDescrição
idstringID único do usuário
namestringNome completo do usuário
emailstringE-mail do usuário
documentstringCPF do usuário (apenas números)
phoneNumberstringTelefone no formato internacional (+55…)
birthdatestringData de nascimento (ISO 8601)
rolestringPapel do usuário (ADMIN, USER, etc.)
avatarobjectObjeto contendo a URL do avatar do usuário
avatar.urlstringURL da imagem de avatar

Code Challenge e Verifier (PKCE)

O PKCE (Proof Key for Code Exchange) é necessário para clientes públicos para verificar que o cliente que iniciou a requisição de autorização é o mesmo que está trocando o código.

Implementação

export async function generateCodeVerifier(): Promise<string> { const randomBytes = crypto.getRandomValues(new Uint8Array(32)); return base64UrlEncode(String.fromCharCode(...randomBytes)); } export async function generateCodeChallenge( codeVerifier: string ): Promise<string> { const encoder = new TextEncoder(); const data = encoder.encode(codeVerifier); const digest = await crypto.subtle.digest('SHA-256', data); return base64UrlEncode(String.fromCharCode(...new Uint8Array(digest))); } function base64UrlEncode(str: string): string { const base64 = btoa(str); return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); }

Generating State

O parâmetro state é usado para manter o estado da aplicação durante a autorização e prevenir ataques CSRF.

export function generateState(): string { const timestamp = Date.now().toString(); const randomString = Math.random().toString(36).substring(2); return timestamp + randomString; }

Usando com o SDK

Após obter o access_token, configure-o no SDK para usar rotas autenticadas.

import { MeapleSDK } from '@meaple-com/core'; const sdk = new MeapleSDK({ publicKey: 'pk_seu_channel_id', baseURL: 'https://api.meaple.com.br', }); // Configurar token global sdk.setGlobalToken(accessToken); // Agora você pode usar rotas autenticadas const user = await sdk.users.getMe(); const orders = await sdk.users.getOrders(); const events = await sdk.users.getEvents();

Rotas Públicas vs Autenticadas

Rotas Públicas (não requerem token)

// Buscar eventos const { events } = await sdk.events.find(); // Buscar evento por slug const event = await sdk.events.getBySlug('event-slug'); // Buscar categorias const { categories } = await sdk.categories.find(); // Buscar ingressos de um evento const { tickets } = await sdk.events.getTickets(eventId);

Rotas Autenticadas (requerem token)

// Configurar token primeiro sdk.setGlobalToken('seu_access_token'); // Perfil do usuário const user = await sdk.users.getMe(); // Pedidos do usuário const orders = await sdk.users.getOrders(); // Eventos com ingressos do usuário const events = await sdk.users.getEvents();

6. Logout OAuth

Use o logout OAuth para encerrar a sessão do usuário e invalidar o refresh_token.

Endpoint de Logout

  • URL (whitelabel/site): https://whitelabel.meaple.app/api/oauth/logout
  • Métodos suportados: GET e POST

💡 Importante: A post_logout_redirect_uri que você usar precisa estar registrada para o seu canal.
Atualmente o registro de redirect URLs é feito via suporte — entre em contato com o suporte Meaple para cadastrar/alterar essas URLs.

Parâmetros

Envie os parâmetros abaixo na query string (tanto para GET quanto POST):

ParâmetroTipoObrigatórioDescrição
client_idstringSimID do canal (channel) que está realizando o logout
post_logout_redirect_uristringSimURL para onde o usuário será redirecionado após o logout

Exemplo de URL de Logout

GET https://whitelabel.meaple.app/api/oauth/logout ?client_id={CHANNEL_ID} &post_logout_redirect_uri=https://seu-app.com/logged-out

Após logout, o usuário será redirecionado para a URL especificada.

Integração com better-auth

Para aplicações Next.js, recomendamos usar a biblioteca better-auth  com o plugin genericOAuth.

import { betterAuth } from 'better-auth'; import { genericOAuth } from 'better-auth/plugins'; export const auth = betterAuth({ plugins: [ genericOAuth({ config: [ { providerId: 'meaple', clientId: process.env.MEAPLE_CLIENT_ID!, authorizationUrl: (() => { const params = new URLSearchParams({ theme: 'dark', preferred_color: '#fb923c', }); return `https://whitelabel.meaple.app/oauth/sign-in?${params.toString()}`; })(), tokenUrl: 'https://whitelabel.meaple.app/api/oauth/token', getUserInfo: async tokens => { const response = await fetch( 'https://api.meaple.com.br/v1/users/me', { headers: { Authorization: `Bearer ${tokens.accessToken}`, 'X-Channel-Id': process.env.MEAPLE_CLIENT_ID!, }, } ); const { user } = await response.json(); return { id: user.id, name: user.name, email: user.email, emailVerified: true, }; }, scopes: ['profile', 'email'], responseType: 'code', pkce: true, }, ], }), ], });

Próximos Passos

Last updated on