Desenvolvedores =============== O Sabiá é o provedor de identidade dos sistemas do SUS parceiros do LAIS: com ele, o usuário entra no seu sistema com a conta do Sabiá (CPF ou e-mail e senha, ou gov.br), sem criar outro cadastro. A integração usa `OAuth 2.0 `__. Cadastrar a aplicação ~~~~~~~~~~~~~~~~~~~~~ No portal **desenvolvedores** (entre com a sua conta do Sabiá) crie a aplicação e informe nome, descrição, logo, e-mail de contato, domínios e as URIs de redirecionamento (``http`` ou ``https``). Escolha também: - **Tipo de cliente:** *confidencial* (o ``client_secret`` fica num servidor) ou *público* (aplicativo ou página que não guarda segredo; envia só o ``client_id`` e deve usar PKCE). - **Tipo de concessão:** cada aplicação usa **um** tipo (código de autorização, implícita, senha ou credenciais do cliente), mais a atualização de token. Pedir outro tipo devolve ``unauthorized_client``. - **Escopos opcionais** que a aplicação usa (ver abaixo). Os obrigatórios ficam sempre ligados. O ``client_secret`` aparece **uma única vez**, ao criar a aplicação ou gerar um novo: copie e guarde num cofre. Se perder, gere outro; o anterior deixa de valer. **Membros:** o dono adiciona outras pessoas pelo CPF ou e-mail, como *admin* (edita a aplicação, escopos, segredo e membros) ou *developer* (só consulta). Só o dono remove admins. Endereços ~~~~~~~~~ Todos no domínio do login do Sabiá (em produção, ``https://login.sabia.ufrn.br``): =================================== ======================================================================== Endereço Uso =================================== ======================================================================== ``GET /oauth/authorize/`` Tela de entrada e de consentimento; devolve o código (ou o token, na implícita) ``POST /oauth/token/`` Troca o código, a senha, as credenciais do cliente ou o token de atualização por tokens ``POST /oauth/revoke_token/`` Revoga um token de acesso ou de atualização (`RFC 7009 `__) ``POST /api/perfil/dados/`` Dados do usuário, conforme os escopos ``GET /logout/`` Encerra a sessão do usuário no Sabiá =================================== ======================================================================== Fluxo recomendado: código de autorização com PKCE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Redirecione o usuário para a autorização, com um ``state`` aleatório e o desafio PKCE (``S256``): .. code-block:: text https://login.sabia.ufrn.br/oauth/authorize/?response_type=code&client_id=CLIENT_ID &redirect_uri=https%3A%2F%2Fseusistema.exemplo%2Fretorno%2F&scope=cpf+email+dados_publicos &state=STATE&code_challenge=DESAFIO&code_challenge_method=S256 2. O usuário entra e, na primeira vez, autoriza a aplicação. O Sabiá volta para a ``redirect_uri`` com ``?code=...&state=...`` (ou ``?error=access_denied&state=...`` se ele cancelar). Confira o ``state``. 3. Troque o código (vale **10 minutos** e uma só vez) pelos tokens: .. code-block:: bash curl -X POST https://login.sabia.ufrn.br/oauth/token/ \ -d grant_type=authorization_code -d code=CODIGO \ -d redirect_uri=https://seusistema.exemplo/retorno/ \ -d client_id=CLIENT_ID -d client_secret=CLIENT_SECRET -d code_verifier=VERIFICADOR .. code-block:: json {"access_token": "...", "expires_in": 86400, "token_type": "Bearer", "scope": "cpf email dados_publicos", "refresh_token": "..."} 4. Peça os dados do usuário (``POST``, com os escopos desejados no corpo): .. code-block:: bash curl -X POST https://login.sabia.ufrn.br/api/perfil/dados/ \ -H "Authorization: Bearer ACCESS_TOKEN" -d "scope=cpf email dados_publicos" As credenciais do cliente podem ir no corpo (``application/x-www-form-urlencoded`` ou ``multipart/form-data``) ou em HTTP Basic. A ``redirect_uri`` precisa ser **exatamente** uma das cadastradas; sem ela, vale a primeira. Escopos e dados ~~~~~~~~~~~~~~~ ``/api/perfil/dados/`` sempre devolve ``uuid`` (identificador público e estável do usuário), ``name`` e ``avatar`` (URL da foto), mais os campos dos escopos pedidos que o token tem e que estão ligados para a aplicação. Escopos não ligados são ignorados sem erro. =================================== ======================== ===================================================== Escopo Tipo Conteúdo =================================== ======================== ===================================================== ``cpf`` obrigatório CPF (11 dígitos); ``null`` para estrangeiro ``email`` obrigatório E-mail ``dados_publicos`` obrigatório Nome e foto ``cnes`` opcional Vínculos do CNES (cache da consulta) ``receita_federal`` opcional Dados da Receita Federal, ou ``{"erro": ...}`` se não validados ``experiencia_profissional`` opcional Lista de experiências (estabelecimento, profissão, datas, município, descrição), ou ``{"erro": ...}`` se vazia ``formacao_academica`` opcional Lista de formações (instituição, curso, grau, datas, município, descrição), ou ``{"erro": ...}`` se vazia =================================== ======================== ===================================================== Use o ``uuid`` como chave do usuário no seu sistema: o CPF pode faltar (estrangeiros) e o e-mail pode mudar. Validade dos tokens ~~~~~~~~~~~~~~~~~~~ - Código de autorização: 10 minutos, uso único. - Token de acesso: 24 horas. - Token de atualização: 30 dias, com rotação: cada uso devolve um novo par e invalida o anterior. Guarde sempre o último. A concessão implícita não emite token de atualização. - Revogar o token de atualização também revoga o de acesso. A revogação responde ``200`` mesmo para token desconhecido. Erros ~~~~~ ``/oauth/token/`` responde no formato da RFC 6749 (``{"error": ..., "error_description": ...}``): ``invalid_client`` (401), ``invalid_request``, ``invalid_grant`` (código ou token expirado, ``code_verifier`` inválido, usuário inativo), ``invalid_scope``, ``unauthorized_client`` e ``unsupported_grant_type``. Com o serviço indisponível, ``503`` e ``temporarily_unavailable``. Em ``/api/perfil/dados/``: ``401`` sem token válido (inclusive token de credenciais do cliente, que não tem usuário), ``405`` com ``GET``, e ``506`` com ``{"erro": {"codigo": 9}}`` (nenhum escopo válido) ou ``codigo 10`` (aplicação inativa). Ao receber ``invalid_grant`` na atualização, mande o usuário entrar de novo. Boas práticas ~~~~~~~~~~~~~ - Prefira o código de autorização com PKCE ``S256`` e ``state``; evite as concessões implícita e de senha. - Mantenha o ``client_secret`` só no servidor; aplicativos e páginas devem ser clientes públicos. - Peça só os escopos de que precisa: o usuário vê a lista na tela de consentimento. - Não guarde senhas do Sabiá nem tente reproduzir a tela de login dentro do seu sistema. API de parceiros (token de API) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Para criar e consultar contas de usuários direto do seu servidor, sem o usuário na tela, há a API de parceiros em ``https://api.sabia.ufrn.br/usuarios/``. Ela só atende aplicações com acesso à API liberado pela equipe do Sabiá (peça ao suporte) e usa o **token de API** da aplicação, gerado na tela de detalhes da aplicação no portal desenvolvedores. O token aparece uma única vez; gerar outro invalida o anterior. Envie o token no cabeçalho ``Authorization: Token ``. Sem token ou com token inválido, a resposta é ``401``; sem acesso à API, ``403``. - ``GET /usuarios/{cpf_ou_email}/``: dados da conta (perfil, formações, Receita Federal e CNES); ``404`` se não existir. - ``GET /usuarios/?cpfs=,&page=1``: várias contas por CPF, 100 por página. - ``POST /usuarios/`` em formulário com ``cpf``, ``email``, ``nome``, ``genero`` (``M`` ou ``F``) e ``data_de_nascimento`` (``AAAA-MM-DD``): cria uma conta (``201``). - ``POST /usuarios/`` em JSON com ``alunos``: cria várias contas de uma vez, cada uma com ``formacoes`` (``instituicao`` e ``curso`` pelo código do e-MEC, ``municipio`` pelo código do IBGE, ``data_inicio``, ``data_fim`` opcional, ``descricao`` e ``grau_formacao``). Se algum item tiver erro, nenhuma conta é criada e a resposta ``400`` traz todos os erros. - ``DELETE /usuarios/{cpf_ou_email}/``: remove a conta que nunca entrou no Sabiá (``401`` se já entrou). A conta criada recebe por e-mail um link para criar a senha, válido por 30 dias; depois disso, a pessoa usa "Esqueceu a senha?" na tela de entrada. Atualização para o Sabiá 2: o que muda para parceiros ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - **Continuam iguais:** os endereços acima, o ``client_id``, o ``client_secret`` e as URIs de redirecionamento. - **Tokens e sessões não são migrados:** depois da atualização, o token de atualização antigo recebe ``invalid_grant`` e todos os usuários entram de novo. Trate esse erro pedindo nova autorização. - ``/api/perfil/dados/`` exige ``POST`` com o ``scope`` no corpo e não devolve mais ``senha_criptografada``; passa a devolver o ``uuid`` do usuário. - Os tokens de API do Sabiá 1 cuja chave era o ``client_id`` não são migrados. Gere um token de API no portal desenvolvedores e troque a chave no cabeçalho ``Authorization: Token``; endereços e formatos da API de parceiros continuam iguais. As aplicações que tinham acesso à API no Sabiá 1 continuam com ele. - Saem da API de parceiros: ``/usuarios/{cpf}/logout/``, ``/usuarios/stats/``, ``/stats/``, ``/cns/`` e ``/cns-retsus/``, que passam a responder ``410``. Ajuda ~~~~~ Dúvidas sobre integração: sabia@atendimento.lais.ufrn.br, informando o nome da aplicação e o ``client_id`` (nunca envie o ``client_secret``).