Atos

Atos Workspace

O produto da Atos para quem constrói sistemas com a Conta Atos. Hoje ele traz o Login Atos para os seus sistemas: o “Entrar com Atos”, um login pronto para o seu site, aplicativo ou servidor, em que a pessoa entra com a Conta Atos dela, do mesmo jeito que entra com o Google. E os Formulários (o formulário de contato do seu site, entregue no seu e-mail Atos), a página de status do seu sistema e a página de links (atos.dev.br/@nome). Ativar é gratuito: é aceitar os termos do Workspace. O Pro, opcional, aumenta os limites.

Ativar o Atos Workspace Já tenho, ir ao Workspace Ver o passo a passo Gratuito e Pro

O que é o Atos Workspace

Conta Atos e Workspace

A Conta Atos é a identidade e a carteira de cada pessoa: com ela, ela entra, assina e paga. Quem só usa um sistema precisa só da conta. O Workspace é o que você ativa, na mesma conta, para construir.

O que inclui hoje

O Login Atos para os seus sistemas, em Atos Workspace › Integrações (5 acessos por aplicativo; quantos aplicativos e pessoas, pelo plano), com os avisos ao seu sistema quando o acesso das pessoas muda e o registro de entradas de cada aplicativo, com filtro.

A página de status: endereços do seu sistema conferidos pela Atos e publicados em atos.dev.br/status/<nome>. Como funciona.

Os Formulários: o formulário de contato de um site estático, entregue no destino do seu e-mail Atos, em Atos Workspace › Formulários. Pedem o e-mail Atos com o destino confirmado, como as Integrações. Como usar.

A página de links: atos.dev.br/@nome, com o seu nome, uma frase, uma foto e os seus links, gerada pela Atos. Como é.

O e-mail Atos (em preparação na Atos): um endereço @atos.dev.br que encaminha para o seu e-mail (não é caixa de entrada) e que também entra na sua Conta Atos, com a mesma senha. Cadastrar um sistema pede o e-mail Atos com o destino confirmado; enquanto ele estiver em preparação, a área do Workspace avisa e o cadastro de sistemas espera.

Preço

Ativar é gratuito: é aceitar os termos do Atos Workspace, sem cartão nem pagamento. O Atos Workspace Pro, opcional, custa R$ 29 por mês (cartão, assinatura) ou R$ 290 por ano (cartão ou Pix).

Desativar

Quando quiser, na área do Workspace. Os aplicativos que você cadastrou continuam funcionando para quem entra neles; para vê-los e mudá-los, você ativa de novo.

Gratuito e Pro

Todo Workspace começa no gratuito. O Atos Workspace Pro custa R$ 29 por mês no cartão (uma assinatura; você cancela quando quiser em Minha conta) ou R$ 290 por ano no cartão ou no Pix (pago de uma vez, sem renovação automática). A cobrança é da Atos, pelo mesmo checkout do PAVLVS; a assinatura e as faturas ficam em Minha conta.

GratuitoPro
Sistemas no Login Atos210
Pessoas liberadas por sistema1005.000
E-mail Atos1 endereço1 endereço
Formulários1, com até 50 envios por dia10, com até 1.000 envios por dia (somando todos)
Avisos ao sistemahistórico de 30 diashistórico de 90 dias
Registro de entradas7 dias90 dias, e exportar em CSV
Página de status1 endereço, a cada 15 minutosaté 10 endereços, a cada minuto, e o aviso de queda por e-mail
Página de links1 página, até 5 links3 páginas, até 50 links cada, e os cliques por dia

Os limites valem no servidor; ao chegar num, a área do Workspace diz qual. Se o Pro acabar, nada é apagado: o que passa dos limites do gratuito fica fora do plano (sistemas só leitura, que continuam deixando entrar quem já entrava; formulários e páginas de links acima do limite parados ou fora do ar; endereços de status sem conferência) até você voltar ao Pro ou reduzir. A conferência “a cada minuto” depende da fila da Atos e pode atrasar com muitas páginas. Detalhes nos termos.

O Login Atos

O “Entrar com Atos” nos seus sistemas. Por baixo é OpenID Connect, o padrão aberto que as bibliotecas de login já conhecem.

O que o sistema recebe

Um identificador fixo da conta (o sub, que não muda), o nome e o e-mail. Só com o consentimento da pessoa, pedido na primeira vez.

Quem pode entrar

Quem cadastrou o sistema decide: só as pessoas que ele liberar, ou qualquer Conta Atos.

A pessoa no controle

Ela vê os sistemas que têm acesso em Minha conta e pode tirar a permissão quando quiser.

Padrão aberto

Código de autorização com PKCE e um id_token assinado, que o seu sistema confere sozinho pelas chaves públicas.

Como a pessoa vê

O seu sistema manda a pessoa para atos.dev.br. Ela entra (ou cria a conta), confere o que o sistema vai receber e permite. Depois volta ao seu endereço já identificada. Da segunda vez em diante, com a sessão aberta, a volta é direta.

Tela de entrar da Atos aberta por um aplicativo: o título “Entrar com a conta Atos”, a frase “Para continuar em Loja da Maria”, os campos de e-mail e senha preenchidos com joao@exemplo.test, o botão Entrar e o link Criar conta.
1. EntrarA pessoa entra com o e-mail e a senha da Conta Atos, ou cria a conta ali mesmo. A página diz para qual sistema ela está entrando.
Tela de consentimento: “Loja da Maria quer entrar com a sua conta Atos”, o aviso “Cadastrado por maria.doces@atos.dev.br. Não é um aplicativo da Atos”, a conta que está entrando (João Exemplo), a lista do que o sistema poderá (saber que é você, ver o e-mail, ver o nome) e os botões Cancelar e Permitir.
2. PermitirNa primeira vez, a Atos mostra o seu sistema, quem o cadastrou (o seu e-mail Atos, nunca o pessoal) e o que ele vai receber, com os links da política de privacidade e dos termos dele. Nada segue sem o “Permitir”.
Minha conta da Atos, seção Aplicativos com acesso: a Loja da Maria, com o que ela recebe, quem a cadastrou (maria.doces@atos.dev.br, não é da Atos), a data em que foi permitida, o último acesso e o botão Tirar o acesso.
3. Tirar o acessoEm Minha conta › Aplicativos com acesso, a pessoa vê os sistemas que permitiu e tira o acesso de qualquer um. Na próxima vez, o sistema pede a permissão de novo.

Capturas com dados fictícios.

Passo a passo

  1. Crie sua Conta Atos e ative o Atos Workspace

    É a mesma conta com que as pessoas vão entrar no seu sistema. Entre (ou crie a conta) e, em atos.dev.br/workspace, aceite os termos do Workspace e ative: é gratuito. Ativar o Atos Workspace.

  2. Crie o seu e-mail Atos e entre por ele

    Em Atos Workspace › E-mail Atos, escolha o seu endereço nome@atos.dev.br e confirme o destino (o código que a Atos manda e o e-mail de verificação da Cloudflare). Depois, entre com esse endereço e a senha da sua conta: é a mesma conta. Cadastrar sistemas pede isso, e é esse endereço que quem entra no seu sistema vê como quem o cadastrou; o seu e-mail pessoal não aparece. Se você esquecer a senha, o código vai para o e-mail cadastrado da conta, nunca para o endereço @atos.dev.br.

  3. Cadastre o aplicativo

    Em Atos Workspace › Integrações, cadastre o aplicativo e o acesso:

    • O aplicativo: o nome que a pessoa verá, o site, a política de privacidade e os termos.
    • O acesso: página ou aplicativo (cliente público, sem segredo) ou servidor (cliente confidencial, com um segredo mostrado uma vez só: guarde-o na hora).
    • O endereço de volta: exato, como o seu sistema vai mandar no redirect_uri. Em https, ou http só em 127.0.0.1 e [::1] (para testar na sua máquina; um programa instalado pode aceitar a volta em qualquer porta).
  4. Escolha quem pode entrar

    Dois modos, e você troca quando quiser:

    • Qualquer Conta Atos: para um sistema aberto ao público, como uma loja. Quem ainda não tem conta cria uma no caminho: com um botão “Criar conta” ao lado do “Entrar com Atos” (o pedido leva prompt=create), a Atos abre direto no cadastro, e a pessoa volta ao seu sistema já logada. Veja a loja aberta na prática.
    • Só as pessoas liberadas (o padrão): para um sistema fechado, como o painel da equipe. Só os e-mails da Conta Atos que você liberar entram (você, que cadastrou, sempre entra). Quem não está liberado não entra, mesmo que crie a conta: a Atos avisa a pessoa, e a volta ao seu sistema traz error=access_denied. Tirar alguém da lista vale no próximo login e no /oauth/userinfo; um id_token já emitido vale até vencer. Veja o sistema fechado na prática.
  5. Integre

    O bloco “Como integrar”, em Integrações, traz o seu client_id e os endereços, um comando (PowerShell ou Linux/macOS) que grava no .env do seu projeto o emissor, o client_id e a volta (o segredo, você cola; ele nunca vai no comando), o código na sua linguagem e um pedido pronto para colar no Claude Code. Ou siga a referência técnica abaixo com a biblioteca OpenID Connect da sua linguagem. Para o botão, use o oficial: o botão “Entrar com Atos” (SVG, HTML e CSS sem script, e as regras de uso). No Chrome e no Edge, a pessoa pode continuar sem sair do seu site.

  6. Teste

    Entre com uma conta liberada, confira o nome e o e-mail que chegaram e tente com uma que não está liberada. Depois tire o acesso em Minha conta e veja o pedido de permissão aparecer de novo. Um exemplo completo, com as telas, está em Na prática.

Na sua linguagem

O mínimo para entrar com a Atos em cada linguagem, com a biblioteca OpenID Connect consagrada dela: a biblioteca confere a assinatura e os campos do id_token, sem criptografia escrita à mão. Os exemplos de servidor são de um acesso confidencial e leem do .env ATOS_ISSUER, ATOS_CLIENT_ID, ATOS_CLIENT_SECRET e ATOS_REDIRECT_URI; no de navegador, troque SEU_CLIENT_ID e a volta pelos do seu acesso.

JavaScript, Python e C#/.NET foram testados contra a Atos: quem está liberado entra, e quem não está volta com error=access_denied e vê o aviso. PHP, Java, Go e Ruby foram escritos pela documentação de cada biblioteca e ainda não rodaram aqui; estão marcados.

Biblioteca: @atos.dev.br/entrar (o pacote da Atos, sem dependências)

Testado contra a Atos: o pacote no Node e num navegador simulado (state, iss, access_denied e id_token forjados recusados), e o servidor Express abaixo.

Instalação
npm install @atos.dev.br/entrar
# Sem npm (página sem empacotador): baixe o mesmo código, um arquivo só, licença MIT:
#   https://atos.dev.br/pacotes/entrar/0.5.0/entrar.js
# No servidor Node, também:
npm install express express-session
Código no navegador (acesso público)
// Navegador (cliente público, sem segredo). Com empacotador (Vite, webpack...): o pacote do npm.
// Sem empacotador: baixe o entrar.js (o mesmo código) e importe de "./entrar.js".
import { entrarComAtos } from "@atos.dev.br/entrar";

const atos = entrarComAtos({
  clientId: "SEU_CLIENT_ID",
  voltaPara: "https://seusistema.com.br/retorno", // exatamente como cadastrada
});

// O botão: o oficial de https://atos.dev.br/marca/ (o HTML de lá, com id="entrar-com-atos").
// O clique gera state, nonce e code_verifier, guarda em sessionStorage e vai à Atos.
document.querySelector("#entrar-com-atos").addEventListener("click", () => atos.entrar());

// Na página de volta: confere state e iss, troca o código e confere o id_token (ES256 pela JWKS).
try {
  const pessoa = await atos.retorno(); // null quando a página não é uma volta
  if (pessoa) console.log(pessoa.id, pessoa.nome, pessoa.email); // identifique pelo id (o sub)
} catch (e) {
  if (e.codigo === "access_denied") alert(e.message); // a conta não tem acesso ou não permitiu
  else throw e;
}
Código no servidor Node (acesso confidencial)
// Servidor Node com Express (cliente confidencial), com o pacote @atos.dev.br/entrar.
// O segredo fica só em ATOS_CLIENT_SECRET (o pacote lê de lá). Rode com: node --env-file=.env servidor.mjs
import express from "express";
import session from "express-session";
import { entrarComAtos } from "@atos.dev.br/entrar";

const atos = entrarComAtos({
  clientId: process.env.ATOS_CLIENT_ID,
  voltaPara: process.env.ATOS_REDIRECT_URI,
  emissor: process.env.ATOS_ISSUER, // vazio: https://atos.dev.br
});
const app = express();
app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, cookie: { httpOnly: true, sameSite: "lax" } }));

app.get("/", (req, res) => {
  const p = req.session.pessoa;
  res.type("text").send(p ? "Olá, " + p.nome + " (" + p.email + "). id: " + p.id : "Entre em /entrar");
});
// Na sua página, o link para /entrar é o botão oficial: https://atos.dev.br/marca/ (o HTML e a folha botao.css).

app.get("/entrar", async (req, res) => {
  const { url, guardar } = await atos.comecar(); // state, nonce e code_verifier
  req.session.atos = guardar;
  res.redirect(url);
});

app.get(new URL(atos.voltaPara).pathname, async (req, res) => {
  const guardado = req.session.atos;
  delete req.session.atos;
  try {
    const pessoa = await atos.concluir(req.originalUrl, guardado); // confere tudo e troca o código
    req.session.pessoa = { id: pessoa.id, nome: pessoa.nome, email: pessoa.email };
    res.redirect("/");
  } catch (e) {
    // access_denied: a conta não tem acesso ou a pessoa não permitiu
    res.status(e.codigo === "access_denied" ? 403 : 400).type("text").send(e.message);
  }
});

app.listen(Number(new URL(atos.voltaPara).port) || 3000);

“Continuar como”: entrar sem sair do site

No Chrome e no Edge, a pessoa pode entrar sem ir à Atos: o próprio navegador mostra a Conta Atos que está aberta nele, “Continuar como <nome>”, e ela escolhe. Por baixo é o FedCM (Federated Credential Management), o padrão do W3C para isso. Na primeira vez em cada aplicativo, a Atos abre uma janela pequena com a mesma tela de permissão do login de sempre (com quem cadastrou o aplicativo); das outras vezes, a escolha basta.

Onde funciona

Chrome e Edge (o FedCM, com o modo do botão e o params, do Chrome 132 em diante). Testado no Chrome 154 no Windows. Firefox e Safari não têm FedCM: neles, o mesmo botão leva ao login de sempre, pelo redirecionamento. Se a pessoa fecha a janela do navegador, também.

O que o site recebe

Um código, como na volta do login de sempre, e só depois que a pessoa escolhe a conta. O site o troca no /oauth/token com o PKCE e, no acesso confidencial, com o segredo. Nunca o id_token direto do navegador.

Quem pode entrar

O mesmo do aplicativo: no modo “Só as pessoas liberadas”, quem está fora da lista recebe a recusa no navegador e o site recebe o erro access_denied, sem nada da pessoa. A conta só aparece para quem já entrou na Atos neste navegador, depois da verificação em duas etapas, quando ligada.

Privacidade

Para mostrar a conta, o navegador pergunta à Atos sem dizer qual site está aberto, e a resposta fica com o navegador. A Atos diz ao navegador se há alguém dentro dela (o “Login Status”), sem dizer quem. Veja a política de privacidade.

Passo a passo

  1. Confira a origem do seu site

    O pedido vem da página do seu site, e a Atos confere a origem dela contra o acesso: vale uma origem cadastrada no acesso ou a de um endereço de volta (https://loja.com.br/auth/volta autoriza https://loja.com.br). Nada mais para cadastrar.

  2. Use o pacote 0.4.0 ou mais novo

    O continuarComFedCM() é do @atos.dev.br/entrar 0.4.0 ou mais novo: npm install @atos.dev.br/entrar. Numa página sem empacotador, o mesmo código num arquivo só, servido pela Atos: https://atos.dev.br/pacotes/entrar/0.5.0/entrar.js.

  3. Ponha o botão

    O botão oficial com o texto “Continuar com Atos”, como link para o login de sempre. No clique, chame o FedCM (ele precisa do clique: o modo do botão).

  4. Troque o código

    Numa página sem servidor (acesso público), o pacote troca e devolve a pessoa. Com servidor (acesso confidencial), o servidor começa (comecarFedCM(), que guarda o code_verifier na sessão), a página entrega o código e o servidor troca com o segredo (concluirFedCM()).

// Acesso público: a página troca o código e confere o id_token.
import { entrarComAtos } from "./entrar.js"; // https://atos.dev.br/pacotes/entrar/0.4.0/entrar.js

const atos = entrarComAtos({ clientId: "SEU_CLIENT_ID", voltaPara: "https://seusistema.com.br/retorno" });
botao.addEventListener("click", async (e) => {
  e.preventDefault();
  // null: foi pelo login de sempre (sem FedCM no navegador, ou a janela fechada)
  const pessoa = await atos.continuarComFedCM();
  if (pessoa) console.log(pessoa.id, pessoa.nome, pessoa.email);
});
// Acesso confidencial: o servidor começa e troca (com ATOS_CLIENT_SECRET).
app.post("/fedcm/comecar", async (req, res) => {
  const { params, guardar } = await atos.comecarFedCM();
  req.session.atosFedcm = guardar;
  res.json({ params });
});
app.post("/fedcm/concluir", express.json(), async (req, res) => {
  const guardado = req.session.atosFedcm;
  delete req.session.atosFedcm;
  const pessoa = await atos.concluirFedCM(req.body.codigo, guardado);
  req.session.pessoa = { id: pessoa.id, nome: pessoa.nome, email: pessoa.email };
  res.json({ ok: true });
});

// Na página, no clique:
const { params } = await (await fetch("/fedcm/comecar", { method: "POST" })).json();
const r = await atos.continuarComFedCM({ params, semFedCM: "/entrar" }); // { codigo } ou null
if (r) await fetch("/fedcm/concluir", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ codigo: r.codigo }) });

Num iframe de outra origem, o FedCM precisa de allow="identity-credentials-get". Com uma CSP que limita connect-src, inclua https://atos.dev.br. A Loja da Maria (exemplos/loja-de-exemplo) tem os dois botões funcionando.

Os endereços

Well-known
https://atos.dev.br/.well-known/web-identity
Configuração (configURL)
https://atos.dev.br/fedcm/config.json
Contas
/fedcm/contas (só o navegador, com Sec-Fetch-Dest: webidentity)
Aplicativo
/fedcm/cliente (a política e os termos que o navegador mostra)
Afirmação
/fedcm/afirmar: o código, ou a janela de permissão da Atos (continue_on), ou o erro
Desconectar
/fedcm/desconectar (IdentityCredential.disconnect: tira a permissão do aplicativo)
params
{ nonce, code_challenge, code_challenge_method: "S256", scope }; o código se troca no /oauth/token sem redirect_uri

Na prática: do zero ao login

Um exemplo rodando de verdade, do cadastro ao “Olá”. A Maria tem um site, a Loja da Maria, e quer que os clientes dela entrem com a Conta Atos. Quem pode entrar depende do modo que ela escolhe na Atos:

  • Qualquer Conta Atos, para a loja aberta a clientes: o Pedro, cliente novo, clica em “Criar conta” na loja, cria a Conta Atos, permite e volta à loja já logado. Veja abaixo.
  • Só as pessoas liberadas, para um sistema fechado: só os e-mails da lista entram. A Maria libera o João; o Pedro, que não está na lista, não entra. Veja abaixo.

Feito num ambiente de teste com dados fictícios. A Atos rodou nesta máquina, por isso alguns endereços mostram 127.0.0.1. As contas são de mentira, e a loja é a de exemplos/loja-de-exemplo no repositório. Em atos.dev.br, os passos e as telas são os mesmos.

Loja aberta: qualquer Conta Atos

O caso de uma loja: qualquer pessoa pode virar cliente, e quem ainda não tem Conta Atos cria uma no caminho, sem sair do pedido da loja.

  1. A Maria cadastra a loja na Atos

    Ela ativa o Atos Workspace e cria o e-mail Atos dela, maria.doces@atos.dev.br, confirmando o destino. Com ele confirmado, a Atos pede que ela entre pelo endereço novo (a mesma senha), e as Integrações abrem.

    Atos Workspace › E-mail Atos da Maria: o endereço maria.doces@atos.dev.br encaminhando, o destino maria@exemplo.test e o aviso “Destino confirmado. Para cadastrar sistemas nas Integrações, entre com maria.doces@atos.dev.br (a mesma senha da conta)”, com o botão Entrar com maria.doces@atos.dev.br.
    Ela tinha entrado com o e-mail pessoal: o botão sai e volta à tela de entrar com o endereço Atos preenchido. No ambiente de teste, a verificação da Cloudflare é simulada.

    Já entrando por maria.doces@atos.dev.br, em Atos Workspace › Integrações, ela cria o aplicativo “Loja da Maria” e, em “Quem pode entrar”, escolhe “Qualquer Conta Atos”. Depois cria um acesso confidencial, porque a loja tem servidor, com o endereço de volta da loja. A Atos mostra o segredo do acesso uma vez só, e ela o guarda.

    Atos Workspace › Integrações da Maria: o aplicativo Loja da Maria com “Quem pode entrar” em “Qualquer Conta Atos” (qualquer pessoa com Conta Atos entra, cadastro aberto), a lista de liberados vazia e um acesso confidencial ligado com o endereço de volta da loja.
    O aplicativo, quem pode entrar e o acesso. O endereço de volta é 127.0.0.1 porque é o ambiente de teste; num site publicado, é o endereço https dele.
  2. Ela abre o “Como integrar”

    O cartão traz o client_id, os endereços e um comando que grava no .env do projeto o emissor, o client_id e a volta. O segredo ela cola à mão em ATOS_CLIENT_SECRET: ele nunca vai no comando.

    O cartão Como integrar do acesso da Loja da Maria: a tabela com a descoberta, o issuer, o client_id, os endereços de autorização, token, userinfo, JWKS e revogação, os escopos e a volta; os cinco passos do fluxo; e o início do comando PowerShell que grava o .env.
    No ambiente de teste, os endereços são os da Atos local (127.0.0.1:8787). Em atos.dev.br, o emissor é https://atos.dev.br.
  3. Ela instala o pacote

    Na pasta da loja, um servidor Node com Express, basta um comando: o pacote @atos.dev.br/entrar vem do npm, junto com o Express e a sessão.

    Um terminal com o comando npm install @atos.dev.br/entrar express express-session e a resposta: added 74 packages, and audited 75 packages in 6s; 30 packages are looking for funding; found 0 vulnerabilities.
    A saída real do npm install desta demonstração, com o @atos.dev.br/entrar 0.1.0 do registro do npm. O “Criar conta” usa a opção criarConta, que é do 0.2.0; nas capturas do Pedro, a loja rodou com o 0.2.0 do repositório. Com o 0.1, a opção é ignorada e o botão abre a tela de entrar, que também tem “Criar conta”.
  4. Ela escreve os trechos

    Criar o cliente, mandar a pessoa para a Atos (para entrar ou para criar a conta) e receber a volta. O resto da loja é dela. Este é o trecho do servidor.mjs da loja de exemplo:

    import { entrarComAtos } from "@atos.dev.br/entrar";
    
    // 1. O cliente, com o que o .env tem (o segredo o pacote lê sozinho de ATOS_CLIENT_SECRET).
    const atos = entrarComAtos({
      clientId: process.env.ATOS_CLIENT_ID,
      voltaPara: process.env.ATOS_REDIRECT_URI, // exatamente como cadastrada na Atos
      emissor: process.env.ATOS_ISSUER || undefined, // vazio: https://atos.dev.br
    });
    
    // 2. "Entrar com Atos" vai a /entrar; "Criar conta", a /criar-conta: a Atos abre em "Criar a conta Atos".
    async function irParaAtos(req, res, extra) {
      const { url, guardar } = await atos.comecar(extra);
      req.session.atos = guardar;
      res.redirect(url);
    }
    app.get("/entrar", (req, res) => irParaAtos(req, res));
    app.get("/criar-conta", (req, res) => irParaAtos(req, res, { criarConta: true }));
    
    // 3. A Atos devolve a pessoa aqui (o endereço de volta cadastrado). O pacote confere tudo e troca o código.
    app.get(new URL(atos.voltaPara).pathname, async (req, res) => {
      const guardado = req.session.atos;
      delete req.session.atos;
      try {
        const pessoa = await atos.concluir(req.originalUrl, guardado);
        req.session.pessoa = { id: pessoa.id, nome: pessoa.nome, email: pessoa.email };
        res.redirect("/");
      } catch (e) {
        // access_denied: a conta não está liberada na Loja, ou a pessoa não permitiu.
        if (e.codigo === "access_denied") return res.redirect("/sem-acesso");
        // ... (a página de erro da loja, com e.message)
      }
    });
    O que o pacote faz por trás
    • comecar() sorteia o state, o nonce e o code_verifier do PKCE e monta o endereço da Atos. Com { criarConta: true }, o endereço leva também prompt=create. A loja só guarda o que ele devolve na sessão de quem está entrando.
    • concluir() confere se o state e o emissor que voltaram são os esperados e troca o código pelo token, com o segredo e o code_verifier. Depois confere o id_token: a assinatura, pelas chaves públicas da Atos; se foi emitido para esta loja; se está na validade; e se o nonce é o do começo. A volta é igual para quem entrou e para quem acabou de criar a conta.
    • Se a Atos voltou com error=access_denied, o concluir() lança um erro com codigo igual a "access_denied", e a loja decide o que mostrar.
  5. O Pedro, cliente novo, abre a loja

    A loja mostra “Entrar com Atos”, para quem já tem conta, e “Criar conta”. O Pedro ainda não tem Conta Atos e clica em “Criar conta”. O clique leva ao /criar-conta da loja, que manda o Pedro para a Atos.

    A página inicial da Loja da Maria, um site claro de bolos e doces caseiros: o título “Bolos e doces feitos em casa”, os botões “Entrar com Atos” e “Criar conta” no topo e abaixo do texto, e três produtos com preço.
    O site é da Maria, com a cara dela. Os dois botões levam à Atos; o “Criar conta” pede que ela abra no cadastro.
  6. Ele cria a Conta Atos

    A Atos abre direto em “Criar a conta Atos”, para continuar na Loja da Maria. Ele preenche o nome, o e-mail e a senha, e a Atos manda um código de 6 dígitos para o e-mail dele. Com o código confirmado, a conta existe e a sessão na Atos está aberta. Quem já tem conta clica em “Já tem conta? Entrar” e segue no mesmo pedido.

    A tela da Atos “Criar a conta Atos”, “Para continuar em Loja da Maria”, com o nome Pedro Exemplo, o e-mail pedro@exemplo.test e as duas senhas preenchidos, o botão Criar conta e o link “Já tem conta? Entrar”.
    Na Atos, aberta pelo “Criar conta” da loja. O código chega por e-mail; no ambiente de teste, onde o e-mail não sai, ele foi lido da Atos local.
  7. Ele permite

    Como a loja aceita qualquer Conta Atos, a conta nova entra sem ninguém liberar. É a primeira vez, então a Atos mostra quem cadastrou a loja, avisa que ela não é um aplicativo da Atos e diz o que a loja vai receber. Ele permite.

    A tela de consentimento: “Loja da Maria quer entrar com a sua conta Atos”, “Cadastrado por maria.doces@atos.dev.br. Não é um aplicativo da Atos”, a conta do Pedro Exemplo, o que a loja poderá (saber que é você, ver o e-mail, ver o nome) e os botões Cancelar e Permitir.
    O consentimento aparece só na primeira vez, com quem cadastrou a loja e o que ela vai receber.
  8. De volta à loja, já logado

    A Atos devolve o Pedro ao endereço de volta com um código. A loja chama o concluir(), que confere tudo e entrega o identificador, o nome e o e-mail. A loja abre a sessão dela e mostra o “Olá”. Da próxima vez, ele clica em “Entrar com Atos”; com a sessão da Atos ainda aberta, a volta é direta.

    A Loja da Maria depois do cadastro: “Área de clientes”, “Olá, Pedro Exemplo”, o e-mail pedro@exemplo.test, o quadro Seus pedidos e o link Sair no topo.
    O nome e o e-mail vieram da Atos, conferidos pelo pacote. Para guardar o cliente, a loja usa o id, que não muda.

Sistema fechado: só as pessoas liberadas

O caso de um sistema que não é para qualquer um: uma área só para quem já fez encomenda, o painel da equipe. Os passos de cadastro e de código são os mesmos; muda o modo do aplicativo.

  1. A Maria escolhe “Só as pessoas liberadas”

    Em “Quem pode entrar”, ela escolhe “Só as pessoas liberadas” (o modo padrão) e libera o e-mail do João. Ela, que cadastrou, sempre entra.

    Atos Workspace › Integrações da Maria: o aplicativo Loja da Maria, “Quem pode entrar” em “Só as pessoas liberadas” com joao@exemplo.test na lista, e um acesso confidencial ligado com o endereço de volta da loja.
    A lista de quem pode entrar. Um e-mail liberado que ainda não tem Conta Atos entra quando a pessoa cria a conta com ele.
  2. O João entra e permite

    Na Atos, ele entra com o e-mail e a senha da Conta Atos dele. Como é a primeira vez, a Atos mostra quem cadastrou a loja, avisa que ela não é um aplicativo da Atos e diz o que a loja vai receber. Ele permite.

    A tela de entrar da Atos: “Entrar com a conta Atos”, “Para continuar em Loja da Maria”, o e-mail joao@exemplo.test e a senha preenchidos e o botão Entrar.
    Na Atos: “Para continuar em Loja da Maria”. A senha fica na Atos; a loja não a recebe.
    A tela de consentimento: “Loja da Maria quer entrar com a sua conta Atos”, “Cadastrado por maria.doces@atos.dev.br. Não é um aplicativo da Atos”, a conta do João Exemplo, o que a loja poderá (saber que é você, ver o e-mail, ver o nome) e os botões Cancelar e Permitir.
    O consentimento aparece só na primeira vez.
  3. De volta à loja, já identificado

    A volta é a mesma da loja aberta: o concluir() confere tudo, e a loja mostra o “Olá”.

    A Loja da Maria depois do login: “Área de clientes”, “Olá, João Exemplo”, o e-mail joao@exemplo.test, o quadro Seus pedidos e o link Sair no topo.
    O João, liberado, dentro da área de clientes.
  4. E o Pedro, que não está liberado

    O Pedro tem Conta Atos, mas a Maria não liberou o e-mail dele. A Atos não pede consentimento nem entrega código: avisa que a conta dele não tem acesso. Quando ele volta à loja, a volta traz error=access_denied, o concluir() lança esse erro e a loja mostra a página de “sem acesso” dela. Neste modo, o “Criar conta” não abre a porta: quem cria a Conta Atos sem estar na lista fica com a conta, mas chega a esta mesma tela.

    A tela da Atos “Sem acesso a este aplicativo”: a Loja da Maria, cadastrada por maria.doces@atos.dev.br, a conta Pedro Exemplo, o aviso “Sua Conta Atos não tem acesso a este aplicativo. Peça a quem o administra.” e os botões Voltar ao aplicativo e Entrar com outra conta.
    Na Atos: a conta do Pedro não está na lista da Loja da Maria.
    A página da Loja da Maria “Sua conta ainda não tem acesso”, explicando que a área de clientes é para quem já fez encomenda, com o botão Voltar à loja.
    Na loja, depois do “Voltar ao aplicativo”: o texto é da Maria, que decide o que dizer a quem não tem acesso.

Para rodar a loja de exemplo contra a Atos de verdade, veja o README de exemplos/loja-de-exemplo: como cadastrar o aplicativo, escolher o modo e gravar o .env.

Avisos ao seu sistema

Em cada aplicativo (Atos Workspace › Integrações), cadastre um endereço https do seu sistema. A Atos mostra um segredo uma vez e manda ali, assinado com ele, um POST JSON {id, tipo, criado, app, dados} quando o acesso das pessoas muda. Assim o seu sistema encerra a sessão de quem tirou a permissão sem esperar o token vencer.

acesso.revogado
A pessoa tirou a permissão do seu aplicativo em Minha conta. dados: {sub}.
liberado.adicionado
Você liberou e-mails na lista. dados: {pessoas: [{email, sub?}]}: o sub só de quem já permitiu o aplicativo; de quem nunca entrou, só o e-mail.
liberado.removido
Você tirou um e-mail da lista. O mesmo formato.
aviso.teste
O botão “Mandar um aviso de teste”. dados: {}.
Assinatura
Atos-Assinatura: t=<segundos>,v1=<HMAC-SHA256 hex de "<t>.<corpo>">, com o segredo do aviso; Atos-Evento traz o id (o mesmo em toda tentativa: aplique uma vez). Recuse o que tiver mais de 5 minutos.
Entrega
Responda 2xx. Senão, a Atos tenta de novo em 1 min, 5 min, 30 min, 2 h e 12 h e marca “falhou”; na área você vê cada entrega, a última resposta e “Tentar de novo”. Ela espera até 10 s e não segue redirecionamentos. O endereço precisa ser público (sem IP, rede interna ou a própria Atos).

O registro de entradas

Também em cada aplicativo: quem entrou nos últimos 7 dias (no gratuito) ou 90 dias (no Pro) (o sub, e o e-mail e o nome só com os escopos email e profile permitidos), quando, o lugar aproximado e o navegador resumido, e as recusas de quem não está liberado (sem dizer quem). Com filtro por período, resultado e busca; no Pro, exportar em CSV.

Conferir no Node

import { verificarAviso } from "@atos.dev.br/entrar"; // 0.3.0 ou mais novo

app.post("/atos/avisos", express.text({ type: "application/json" }), async (req, res) => {
  let aviso;
  try {
    aviso = await verificarAviso(req.body, req.get("atos-assinatura"), process.env.ATOS_AVISOS_SEGREDO);
  } catch {
    return res.sendStatus(401);
  }
  if (aviso.tipo === "acesso.revogado") await encerrarSessoesDe(aviso.dados.sub);
  res.sendStatus(200);
});

Passe o corpo cru (o texto, antes do JSON.parse). Em outra linguagem: calcule o HMAC-SHA256 de t + "." + corpo com o segredo, compare em tempo constante com v1 e confira a idade de t.

Página de status

Em Atos Workspace › Status, cadastre os endereços https do seu sistema (uma página por conta; pede o e-mail Atos confirmado, como os Formulários): no gratuito, 1 endereço conferido a cada 15 minutos; no Pro, até 10 a cada minuto, mais ou menos. A Atos publica, se você quiser, atos.dev.br/status/<nome>: no ar, instável ou fora, o tempo de resposta e o histórico de 30 ou 90 dias, sem as URLs. No Pro, se você ligar, ela avisa por e-mail (no destino do seu e-mail Atos) quando um endereço cai, depois de duas conferências seguidas fora, e quando volta.

A conferência
GET com User-Agent: AtosStatus/1, sem seguir redirecionamentos, até 10 s, sem ler o corpo. 2xx e 3xx: no ar (acima de 3 s, lento); 4xx, 5xx, erro ou tempo esgotado: fora.
Os endereços
Só https público, na porta padrão: sem IP, rede interna, nomes reservados ou a Atos. Um endereço leve, como /saude, é o melhor.
Histórico
90 dias. A página pública não carrega script e fica 60 s em cache.

Formulários

Para o formulário de contato de um site estático, sem servidor seu. Em Atos Workspace › Formulários, você dá um nome, diz de quais sites ele é enviado (a origem, como https://exemplo.com.br; até 5) e escolhe os campos (nome, e-mail, assunto, mensagem e até 5 livres). A Atos dá o endereço https://atos.dev.br/f/<id>; cada envio vira um e-mail da Atos no destino confirmado do seu e-mail Atos, e responder a ele vai para o e-mail que a pessoa digitou.

A Atos não guarda o que foi preenchido: do envio, fica só quando, o site, o resultado e o tamanho, por 30 dias, no registro do formulário. Envios de outros sites são recusados; campos que você não escolheu são ignorados; arquivos não são aceitos.

No HTML

<form action="https://atos.dev.br/f/SEU_FORMULARIO" method="post">
  <label>Nome <input name="nome"></label>
  <label>E-mail <input name="email" type="email" required></label>
  <label>Mensagem <textarea name="mensagem" required></textarea></label>
  <!-- A armadilha contra robôs: fica escondida e vazia. -->
  <div style="position:absolute;left:-10000px" aria-hidden="true"><input name="_armadilha" tabindex="-1" autocomplete="off"></div>
  <button type="submit">Enviar</button>
</form>

Depois de enviar, a pessoa vê a página de “obrigado” da Atos (com o botão de voltar ao site) ou vai para o endereço que você escolher, num dos sites do formulário. A área do Workspace mostra o exemplo já com o endereço e os campos do seu formulário.

Por fetch

const r = await fetch("https://atos.dev.br/f/SEU_FORMULARIO", {
  method: "POST",
  headers: { "content-type": "application/json", accept: "application/json" },
  body: JSON.stringify({ nome, email, mensagem }),
});
const d = await r.json(); // {ok: true} ou {ok: false, erro, codigo}

O CORS só libera os sites cadastrados no formulário.

Contra robôs

Sempre
A origem de cada envio tem de ser um dos sites cadastrados; o campo-armadilha _armadilha (quem o preenche recebe o “obrigado” e nada sai); 5 envios por hora do mesmo endereço de internet em cada formulário; o limite por dia que você escolhe (até 200); 32 KB por envio; e um teto diário da Atos inteira.
Verificação
Quando a Atos tem o Cloudflare Turnstile ligado, você pode pedi-lo em cada formulário: o envio passa por uma página da Atos com o desafio antes da entrega. Com ele ligado, o envio por fetch/JSON é recusado (codigo: "verificacao"). Sem ele na Atos, a opção não aparece.
Respostas
Por fetch: 200 {ok: true}; 400 campos inválidos; 403 site não cadastrado ou formulário desligado; 404 formulário não encontrado; 413 grande demais; 429 limite; 503 o formulário não está recebendo (o e-mail Atos do dono parado, o Workspace desativado) ou o teto da Atos; 502 o e-mail não saiu (tente de novo).

Referência técnica

Para quem integra à mão. Qualquer biblioteca OpenID Connect que lê a descoberta configura o resto sozinha a partir do emissor.

Endereços

Emissor (issuer)
https://atos.dev.br
Descoberta
https://atos.dev.br/.well-known/openid-configuration
Autorização
https://atos.dev.br/entrar
Token
https://atos.dev.br/oauth/token
Dados da pessoa
https://atos.dev.br/oauth/userinfo
Chaves públicas (JWKS)
https://atos.dev.br/oauth/jwks
Revogação
https://atos.dev.br/oauth/revogar

Como funciona

Fluxo
Código de autorização (response_type=code), com a volta na consulta (response_mode=query).
PKCE
Obrigatório para todos os clientes, só com S256.
Escopos
openid (obrigatório), email e profile.
state e nonce
O state volta como foi mandado; o nonce vem dentro do id_token. A volta também traz iss=https://atos.dev.br.
Código
Vale 2 minutos e uma vez só. Trocado em POST /oauth/token com o code_verifier e o mesmo redirect_uri.
Cliente confidencial
Manda o segredo por client_secret_basic ou client_secret_post. O cliente público não usa segredo.
id_token
JWT assinado em ES256. Confira a assinatura pela JWKS (pelo kid) e os campos iss, aud (o seu client_id), exp e nonce.
Campos
sub; com email: email e email_verified; com profile: name. Também auth_time e amr.
amr
Como a pessoa entrou na Atos, nos valores da RFC 8176: pwd (senha), fed (pelo Google), otp (o código do aplicativo autenticador ou um código de recuperação), hwk ou swk (uma chave de acesso presa ao aparelho ou sincronizada na nuvem dele), user (a pessoa confirmou no aparelho) e mfa (passou por mais de um fator). Exemplos: ["pwd"], ["pwd","otp","mfa"], ["hwk","user","mfa"]. Para exigir duas etapas no seu sistema, confira se amr tem mfa; sem ele, a entrada não passou por duas etapas (a pessoa pode não ter a verificação ligada na conta Atos) e o seu sistema decide o que fazer, por exemplo pedir que ela ligue em Minha conta › Segurança. Uma sessão aberta na Atos antes de o amr existir (outubro de 2026; as sessões duram até 30 dias) não o traz: trate a falta como “só a senha”.
Validade
id_token e access_token valem 1 hora. Não há refresh_token: para outra hora, peça o login de novo (com a sessão aberta na Atos, a volta é direta).
prompt
none, login, consent e create; também max_age e login_hint. none não combina com outro valor (error=invalid_request).
prompt=create
Abre a Atos em “Criar a conta Atos” (Initiating User Registration via OpenID Connect 1.0; a descoberta anuncia create em prompt_values_supported). Lá, “Já tem conta? Entrar” continua o mesmo pedido. Com a sessão já aberta na Atos, o pedido segue como sempre: a permissão, ou a volta direta. Só a volta com o código e o id_token diz que a pessoa entrou; quem entra depende do modo do aplicativo, e a conta criada fora da lista volta com access_denied. No pacote JavaScript: entrar({ criarConta: true }) e comecar({ criarConta: true }).
Erros na volta
error=access_denied quando a pessoa não permite ou não está liberada; com prompt=none, login_required ou consent_required.

O pedido de autorização

https://atos.dev.br/entrar
  ?client_id=SEU_CLIENT_ID
  &redirect_uri=https%3A%2F%2Fseusistema.com.br%2Fretorno
  &response_type=code
  &scope=openid%20email%20profile
  &state=VALOR_ALEATORIO
  &nonce=OUTRO_VALOR_ALEATORIO
  &code_challenge=BASE64URL_DO_SHA256_DO_VERIFIER
  &code_challenge_method=S256

As quebras de linha são só para ler: a URL vai numa linha só.

A troca do código

POST https://atos.dev.br/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=CODIGO_RECEBIDO
&redirect_uri=https%3A%2F%2Fseusistema.com.br%2Fretorno
&client_id=SEU_CLIENT_ID
&code_verifier=O_VERIFIER_DO_INICIO

A resposta traz id_token, access_token (Bearer, para /oauth/userinfo), expires_in e scope.

Veja também os Termos de uso e a Política de privacidade da Conta Atos.