Repository navigation
feat(auth): conclui o login por conexao de identidade (Sankhya Pass) a partir do codigo no fragmento (#189) - #190
BrunoPinaFelipe wants to merge 1 commit into
Conversation
…a partir do codigo no fragmento (#189) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
| // whoever obtained it. | ||
| if (browserWindow.self === browserWindow.top) { | ||
| throw new Error('Identity connection sign-in is only accepted inside the host system iframe.'); | ||
| } |
There was a problem hiding this comment.
major O retorno é aceito apenas por stateMitra com prefixo connection. e por estar em iframe (self !== top). Isso não vincula o código ao browser/origem que iniciou a conexão: uma página de terceiro pode embutir o app com código de outra conta e induzir o usuário a concluir a troca, formando login CSRF. A RFC #979 exige vínculo a app, origem e transação. Antes do POST, valide a origem ancestral contra allowedOrigins (falhando fechado quando não verificável) ou use protocolo equivalente; cubra origem permitida e negada e prove que a negada não dispara POST.
| // A token set by hand is a new session, not the identity connection's one, | ||
| // and the tab copy of that one would come back on the next reload. | ||
| this.sessionScoped = false; | ||
| removeItem(sessionStorageOrNull(), this.storageKey); |
There was a problem hiding this comment.
major setToken() troca sessionScoped para false, mas retém #refreshToken da sessão por aba anterior. saveToStorage() grava access e refresh no destino escolhido; a ponte só suprime o refresh enquanto a sessão continua restrita à aba e, fora disso, o entrega ao SDK legado. Assim, setToken() após o login por conexão pode tornar compartilhável o refresh antigo e fazer uma renovação voltar à identidade anterior. Preserve o escopo ao atualizar o mesmo par ou descarte o refresh antigo antes de ampliá-lo; teste saveToStorage em ambas as variantes e createClient com a ponte real, confirmando que o refresh antigo não chega a localStorage nem a mitra-session. Veja também a gravação conjunta de access e refresh.
|
Gandalf, análise 1 · commit Pega-rápido: A SDK passa a concluir login por conexão de identidade dentro de um iframe, atendendo a um uso concreto do Governador. O guard atual confirma que está em um iframe, mas não prova que o browser que recebeu o retorno iniciou a conexão. Insights: O mérito passa: o módulo reutiliza os fluxos de autenticação existentes. O caminho acrescenta troca e leitura de sessão apenas quando reconhece o retorno, sem recurso persistente ou crescimento contínuo. Permanecem dois riscos de fronteira: procedência do retorno e isolamento do refresh token por aba. Forma da implementação: O módulo próprio e o Findings:
Comentários e testes: As duas provas pedidas cabem nos testes da SDK: rejeitar origem não permitida antes da troca e garantir que o refresh antigo não chega ao armazenamento compartilhado nem ao SDK legado. Confiança: Moderada-alta na análise estática: a cadeia de vazamento do refresh é verificável; a falta de vínculo de origem também está no fluxo. A integração específica com o produtor IAM ainda não foi confirmada. Ativação: Mesmo após os ajustes, aguardar o endpoint IAM e a rota/CORS do gateway, a ponte web e a versão do consumidor estarem compatíveis. Merge deste PR não publica o pacote beta; a publicação é manual. Sugestão de aprendizado: Em mudanças de escopo de sessão, conferir todas as credenciais retidas e o efeito pela ponte real. Decisão: não aprovaria até os dois ajustes Não consegui confirmar o contrato do endpoint de troca: a implementação correspondente ainda não aparece no IAM. Aqui o meu check é obrigatório: depois de um push, comente |
Closes #189
O que muda
Login por conexão de identidade, o primeiro caso é o Sankhya Pass, para o app aberto dentro do iframe do SKW (o ERP web da Sankhya). A página de ponte do mitra-web (mitra-web#1145) faz o login no IAM (mitra-iam#672) e redireciona para a origem do app com um código de uso único no fragmento; o SDK troca esse código pela sessão.
src/modules/identity-connection-flow.ts(novo): lêcodeMitra,stateMitra(prefixoconnection.) econnectionMitrado fragmento; fragmento de outro fluxo fica intacto; dali em diante a URL é limpa antes de qualquer erro; só completa dentro de iframe;POST /api/v1/auth/identity-connections/{slug}/exchange {appId, code}comexpectAuthTokenResponse(allTokenspreservado).auth.completeIdentityConnectionSignInRedirect(); oinit()chama a conclusão depois do/info, com single-flight (boot duplo doStrictModetroca o código uma vez só). Erro da troca rejeita oinit()e limpa a sessão em memória que o startup tinha restaurado, sem tocar no storage.sessionStorage), porque duas bases demo da Sankhya no mesmo browser misturavam alias no legado. Regras: a sessão da aba tem precedência na leitura; gravar por aba não apaga a sessão compartilhada; gravar nolocalStorage(Google, e-mail,setSession,setToken) apaga a cópia da aba;signOutpor aba limpa só a aba.localStorage['mitra-session']; o token renovado chega peloonSessionChange. Os exports legados não renovam sozinhos nesse caso (a renovação do SDK é lazy).1.9.0-beta.0:package.json, lock, CHANGELOG esmoke-package.mjs.Fora deste PR
Checar
ancestorOriginscontra asallowedOriginsda conexão (follow-up de segurança); botão "Entrar com Sankhya Pass" fora do SKW.Prova
npm run checklocal: lint, typecheck, 484 testes, build,pack:checke smoke, cobertura 97,2% de linhas e 93,6% de branches. Auditor isolado da skill feature-implementation em quatro iterações: 8,4, 9,4 e 9,6. A prova com token real no dev depende do IAM e da ponte.Ordem
Release beta depois do merge (
release.ymlcom1.9.0-beta.0); o Governador sobe a versão e faz rebuild. Estável só depois da alpha.🤖 Generated with Claude Code