plicflixdevelopers
Entrar Criar conta
Esta página faz parte do roteiro de integração. Ela detalha a fase 4 (formato B: o botão "Entrar com Plicflix" fora do app). Para pôr um jogo no plicflix do zero até ele aparecer no catálogo, siga o roteiro em ordem: Comece aqui (fases 1 a 8, com quem faz cada passo).

Entrar com Plicflix (fora do app)

O botão "Entrar com Plicflix" no seu site ou app. O jogador entra com a conta do plicflix e o seu jogo recebe o mesmo jogador da entrada pelo app: o mesmo id (pf_…, fixo por pessoa e por jogo) e o mesmo apelido. Assim, uma conta do seu jogo serve às duas portas:

porta quando como o jogo recebe o jogador
pelo app (SDK) o jogador toca em Jogar no plicflix token pft_… no endereço → POST /v1/ingresso/trocar
fora do app (esta página) o jogador abriu o seu site direto, ou o seu app nativo OAuth 2.0 + PKCE → POST /v1/oauth/token

É OAuth 2.0 padrão (RFC 6749), com PKCE S256 obrigatório (RFC 7636). Qualquer biblioteca de OAuth serve. O plicflix não emite id_token: o jogador vem direto na resposta do token.

Para IAs: siga as seções 1 a 5 na ordem. A seção 4 é o caminho recomendado (com servidor). O exemplo inteiro, em Node, está na seção 4.3. Os ajudantes prontos ficam em plicflix.mjs e plicflix.go (servidor) e plicflix.js 2.4+ (navegador).

1. Os endereços

o quê endereço
autorizar (o navegador vai até lá) https://plicflix.com/oauth/authorize
trocar o código POST https://api.plicflix.com/v1/oauth/token
quem é (com o access token) GET https://api.plicflix.com/v1/oauth/userinfo
revogar o access token POST https://api.plicflix.com/v1/oauth/revogar
descoberta (RFC 8414) https://plicflix.com/.well-known/oauth-authorization-server
client_id o slug do seu jogo
client_secret (opcional) uma chave pk_… deste jogo (ou a antiga do estúdio)
escopo perfil (openid e profile são aceitos como sinônimos)

2. Cadastrar os endereços de volta

No portal: developers.plicflix.com → o seu jogo → Integração → Entrar com Plicflix, um redirect_uri por linha (até 10). Ou pela API, com a chave:

curl -X PUT https://api.plicflix.com/v1/parceiro/jogos/SEU-SLUG/oauth \
  -H "Authorization: Bearer pk_…" -H "Content-Type: application/json" \
  -d '{"redirect_uris":["https://seujogo.com/api/plicflix/volta","http://localhost:5173/api/plicflix/volta"]}'
# → {"client_id":"SEU-SLUG","redirect_uris":[…],"authorization_endpoint":…,"token_endpoint":…}

As regras:

  • https://…. http:// só vale em localhost, 127.0.0.1 e ::1 (para testar).
  • App nativo: um esquema próprio com ponto no nome (com.estudio.jogo:/oauth, RFC 8252).
  • Sem #. A comparação é exata, caractere por caractere, inclusive a query.
  • Vale em qualquer situação do jogo: rascunho, revisão ou publicado. O login é do seu site, não do catálogo. O que se exige é o estúdio ativo (taxa de entrada paga, não suspenso). Sem isso, a página mostra o erro e não volta.

3. O fluxo

seu jogo                         navegador                       plicflix
   │ 1. gera verifier + state       │                                │
   │──── 302 /oauth/authorize ─────▶│──────────────────────────────▶ │ 2. entra (se precisar)
   │                                │                                │    e autoriza (1ª vez)
   │◀──── redirect_uri?code&state ──│◀────────────────────────────── │
   │ 3. confere o state                                              │
   │──── POST /v1/oauth/token (code + verifier [+ pk_]) ───────────▶ │
   │◀─── { jogador: { id: "pf_…", nome }, jogo, assinante, access_token } │
   │ 4. acha/cria a conta por jogador.id e abre a SUA sessão         │

1. Mandar o navegador para:

https://plicflix.com/oauth/authorize?response_type=code
  &client_id=SEU-SLUG
  &redirect_uri=https%3A%2F%2Fseujogo.com%2Fapi%2Fplicflix%2Fvolta
  &state=ALEATORIO            ← guarde (cookie curto); confira na volta
  &code_challenge=BASE64URL(SHA256(verifier))
  &code_challenge_method=S256
  &scope=perfil
  [&prompt=consent]           ← pergunta de novo mesmo se já autorizou

O verifier tem de 43 a 128 caracteres de [A-Za-z0-9-._~] (por exemplo, 48 bytes aleatórios em base64url).

2. O plicflix cuida do resto:

  • quem já está logado no plicflix nesse navegador não digita nada;
  • quem não está entra, ou cria a conta e confirma o e-mail, ali mesmo;
  • da segunda vez em diante a autorização é automática: o jogador nem vê a tela.

A tela mostra o que o jogo recebe (o apelido, um id só deste jogo e se é assinante) e o que nunca recebe (o e-mail, a senha, os amigos).

3. A volta. O navegador chega em redirect_uri?code=pfc_…&state=…. Se o jogador cancelou, chega com error=access_denied&state=…. O código vale 5 minutos e uma troca.

Um pedido malformado volta com error=invalid_request, invalid_scope ou unsupported_response_type. Se o client_id ou o redirect_uri não conferem, o plicflix não volta: mostra o erro na própria página.

4. A troca, de preferência no seu servidor:

curl -X POST https://api.plicflix.com/v1/oauth/token \
  -u "SEU-SLUG:pk_…" \
  -d grant_type=authorization_code -d code=pfc_… \
  -d redirect_uri=https://seujogo.com/api/plicflix/volta -d code_verifier=…
{
  "jogador": { "id": "pf_3k2j…", "nome": "Ana", "avatar": "https://midia.plicflix.com/midia/avatares/aurea-lena.png" },
  "jogo": "seu-slug",
  "assinante": true,
  "sub": "pf_3k2j…",
  "name": "Ana",
  "picture": "https://midia.plicflix.com/midia/avatares/aurea-lena.png",
  "access_token": "pfa_…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "perfil"
}
  • Quem entra é o perfil escolhido no plicflix daquele aparelho (cada conta tem até 5). jogador.avatar (e picture, no padrão OpenID) é a imagem dele: URL https pública, 256×256. Sem imagem, avatar vem "" e picture não vem.
  • O corpo pode ser application/x-www-form-urlencoded (o padrão) ou JSON.
  • A chave vai como Basic (client_id:pk_…), como client_secret no corpo ou como Authorization: Bearer pk_….
  • Sem a chave, o pedido é de um cliente público (o jogo sem servidor, o app nativo): o PKCE é a prova.
  • jogador.id é igual ao da entrada pelo app (/v1/ingresso/trocar): ligue a conta por ele.

5. Depois: o access_token vale 1 hora e só serve para GET /v1/oauth/userinfo, que devolve as mesmas chaves (sem o token). Não há refresh token: o seu jogo abre a própria sessão. Para saber de novo quem é, repita o fluxo; da segunda vez em diante ele é automático e invisível.

4. Com servidor (recomendado)

4.1 As duas rotas

  • GET /api/plicflix/oauth:
    1. gere verifier e state (novoPKCE());
    2. guarde os dois num cookie HttpOnly; Secure; SameSite=Lax de 10 minutos;
    3. responda 302 para urlDeEntrada(...).
  • GET /api/plicflix/volta:
    1. confira state contra o cookie e apague o cookie;
    2. se veio error, mande o jogador de volta à sua tela de login;
    3. chame trocarCodigo(code, …) com a chave pk_;
    4. ache ou crie a conta por jogador.id, abra a sessão e responda 302 para o jogo.

A conta segue as mesmas regras da entrada pelo app (SDK): coluna única plicflix_id, login interno reservado (pf_…@plicflix.invalid) e apelido atualizado a cada entrada.

4.2 O botão

O botão oficial, como link para a sua rota:

<script src="/plicflix.js" defer></script>
<plicflix-entrar href="/api/plicflix/oauth" largura="100%"></plicflix-entrar>

Tem os estilos destaque, solido, simples e o seu próprio (proprio), explicados com todas as opções e as regras da marca em BOTAO. O código já preenchido com o seu jogo sai da página Botão oficial.

4.3 Exemplo completo (Node 18+, sem dependências)

import { createServer } from "node:http";
import { novoPKCE, urlDeEntrada, trocarCodigo } from "./plicflix.mjs"; // PLICFLIX_CHAVE no ambiente

const CLIENTE = "seu-slug";
const VOLTA = "https://seujogo.com/api/plicflix/volta";
const cookies = (req) => Object.fromEntries((req.headers.cookie || "").split(/; */).filter(Boolean).map((c) => c.split("=").map(decodeURIComponent)));

createServer(async (req, res) => {
  const url = new URL(req.url, "https://seujogo.com");
  if (url.pathname === "/api/plicflix/oauth") {
    const { verificador, desafio, estado } = novoPKCE();
    res.writeHead(302, {
      "Set-Cookie": `pf_oauth=${estado}.${verificador}; Path=/api/plicflix; HttpOnly; Secure; SameSite=Lax; Max-Age=600`,
      Location: urlDeEntrada({ cliente: CLIENTE, volta: VOLTA, desafio, estado }),
    });
    return res.end();
  }
  if (url.pathname === "/api/plicflix/volta") {
    const [estado, verificador] = (cookies(req).pf_oauth || ".").split(".");
    const apagar = "pf_oauth=; Path=/api/plicflix; Max-Age=0";
    if (!estado || url.searchParams.get("state") !== estado || !url.searchParams.get("code")) {
      res.writeHead(302, { "Set-Cookie": apagar, Location: "/sign-in?erro=plicflix" });
      return res.end();
    }
    const r = await trocarCodigo(url.searchParams.get("code"), { cliente: CLIENTE, volta: VOLTA, verificador });
    const conta = await acharOuCriarConta(r.jogador.id, r.jogador.nome); // a SUA conta
    res.writeHead(302, { "Set-Cookie": [apagar, await abrirSessao(conta)], Location: "/play" });
    return res.end();
  }
}).listen(8080);

Em Go é o mesmo, com plicflix.NovoPKCE(), plicflix.URLDeEntrada(cliente, volta, pk) e cliente.TrocarCodigo(ctx, cliente, code, volta, verificador). Os dois ajudantes estão em plicflix.go.

5. Sem servidor (jogo só de navegador)

O SDK faz tudo:

<script src="/plicflix.js"></script>
<div id="entrar"></div>
<script type="module">
  const CLIENTE = "seu-slug", VOLTA = location.origin + "/";
  const r = await Plicflix.voltouDoPlicflix();        // na volta: troca direto na API (cliente público)
  if (r) iniciar(r.jogador);                          // { id: "pf_…", nome }
  else Plicflix.botaoEntrar("#entrar", { cliente: CLIENTE, volta: VOLTA });   // = <plicflix-entrar cliente volta>
</script>
  • voltouDoPlicflix() confere o state, troca o código e limpa a URL.
  • Com { servidor: "/sua/rota" }, ele manda { code, code_verifier, redirect_uri } ao seu servidor em vez de trocar direto. É o meio-termo para quem já tem uma página e quer trocar no servidor.
  • Como tudo o que roda no navegador, o resultado de um cliente público serve para mostrar o nome e guardar o progresso local. Nunca use para proteger moedas, ranking ou compras: para isso, troque no servidor (seção 4).

6. Segurança (confira cada uma)

  • O state é aleatório, fica num cookie HttpOnly e é conferido na volta.
  • O verifier nunca sai do seu lado: só o code_challenge vai na URL.
  • A chave pk_… só existe no servidor (nunca no navegador nem no app).
  • A conta é achada por jogador.id, nunca pelo apelido (o apelido muda).
  • O login interno …@plicflix.invalid é recusado no seu cadastro normal.
  • Os redirect_uri de localhost saem da lista antes de publicar, se você não quiser que funcionem em produção.

7. Erros

O token responde no formato do OAuth: {"error": "...", "error_description": "..."}.

status error quando
400 invalid_grant o código é inválido, venceu (5 min), já foi usado ou é de outro jogo; ou o redirect_uri é diferente; ou o code_verifier não confere. Um código que falha morre: recomece o fluxo.
400 invalid_request falta code ou code_verifier, ou o corpo é inválido
400 unsupported_grant_type só authorization_code
401 invalid_client o client_id não existe ou a chave não é deste jogo (nem a antiga do estúdio dono)
401 invalid_token userinfo: o pfa_ é inválido ou venceu
429 — limite por IP; espere um minuto

Na volta para o seu redirect_uri, os erros possíveis são access_denied (o jogador cancelou), invalid_request (faltou o PKCE S256), invalid_scope e unsupported_response_type.

8. Testar

  1. Cadastre http://localhost:PORTA/api/plicflix/volta (seção 2).
  2. Use uma conta testadora do jogo (com o e-mail confirmado) se ele ainda não está publicado.
  3. Abra http://localhost:PORTA/api/plicflix/oauth e entre: você volta logado no seu jogo. O jogador.id é o mesmo de quando a mesma conta abre o jogo pelo app.
  4. Abra de novo: desta vez a volta é direta, sem a tela de autorizar. Para ver a tela outra vez, use prompt=consent.