Imagine um cenário com vários sistemas web interconectados (A, B, C, D, E, F) que compartilham o mesmo domínio raiz (por exemplo, .meudominio.com). O objetivo é implementar um sistema de login único onde, após o usuário se autenticar em qualquer um desses sistemas, ele possa acessar todos os outros sem a necessidade de fazer login novamente. O token de autenticação tem uma validade de 12 horas e é renovado a cada acesso.
A solução para este problema se baseia no uso estratégico dos Cookies do navegador.
Quando um usuário faz login com sucesso, o frontend do sistema de autenticação armazena o token em um cookie. Vamos enalisar o comportamento:
O nome da chave do cookie utilizado é _micro.common-info.
O valor associado a essa chave é uma estrutura de dados definida pelo frontend, que geralmente combina informações do ambiente (como ENV) e o token de autneticação.
O campo Domain do cookie é crucial aqui. Ele permite que o cookie seja acessível por diferentes subdomínios dentro de um mesmo domínio raiz.
As funções principais para gerenciar esses cookies são setCookie e getCookie. Segue um exemplo de implementação em JavaScript:
import Cookies from 'js-cookie';
const TOKEN_KEY = 'sessionToken';
const COOKIE_STORE_KEY = '_auth_session';
const CURRENT_ENV = import.meta.env.VITE_APP_ENV; // Exemplo: 'production', 'staging'
const COOKIE_DOMAIN_MAIN = 'meudominio.com';
const DOMAIN_PATTERN = /meudominio\.com$/;
export function retrieveToken() {
const allStoredCookies = loadAllCookies();
const envCookies = allStoredCookies[CURRENT_ENV];
return envCookies ? envCookies[TOKEN_KEY] : null;
}
export function persistToken(token) {
const storedCookies = loadAllCookies();
if (!storedCookies[CURRENT_ENV]) {
storedCookies[CURRENT_ENV] = {};
}
storedCookies[CURRENT_ENV][TOKEN_KEY] = token;
return new Promise((resolve, reject) => {
try {
Cookies.set(COOKIE_STORE_KEY, JSON.stringify(storedCookies), {
domain: determineCookieDomain(),
expires: 365, // Exemplo: expira em 1 ano para persistência mais longa
secure: true, // Recomendado em produção
sameSite: 'lax' // Recomendado
});
resolve();
} catch (error) {
console.error("Erro ao salvar cookie:", error);
reject(error);
}
});
}
export function clearToken() {
// Limpa o token definindo-o como uma string vazia
return persistToken('');
}
function determineCookieDomain() {
const currentHost = window.location.hostname;
const localHosts = ['localhost', '127.0.0.1', '::1']; // Adicionar outros hosts locais se necessário
if (localHosts.includes(currentHost)) {
return currentHost; // Usa o host local para testes
} else if (DOMAIN_PATTERN.test(currentHost)) {
return COOKIE_DOMAIN_MAIN; // Usa o domínio principal para subdomínios
} else {
return currentHost; // Usa o domínio atual se não corresponder
}
}
function loadAllCookies() {
const cookieString = Cookies.get(COOKIE_STORE_KEY, {
domain: determineCookieDomain(),
});
if (cookieString && typeof cookieString === 'string') {
try {
const parsedCookie = JSON.parse(cookieString);
if (parsedCookie && typeof parsedCookie === 'object') {
return parsedCookie;
}
} catch (e) {
console.error("Erro ao parsear cookie JSON:", e);
}
}
return {}; // Retorna um objeto vazio se o cookie não for encontrado ou for inválido
}
A lógica dentro da função determineCookieDomain é particularmente importante:
function determineCookieDomain() {
const currentHost = window.location.hostname;
const localHosts = ['localhost', '127.0.0.1', '::1'];
if (localHosts.includes(currentHost)) {
return currentHost;
} else if (DOMAIN_PATTERN.test(currentHost)) { // DOMAIN_PATTERN = /meudominio\.com$/
return COOKIE_DOMAIN_MAIN; // COOKIE_DOMAIN_MAIN = 'meudominio.com'
} else {
return currentHost;
}
}
Esta função determina qual domínio deve ser usado para o cookie. Se o domínio atual for um host local como 'localhost', ele usa o próprio host. Caso contrário, verifica se o domínio atual termina com 'meudominio.com' usando a expressão regular /meudominio\.com$/. Se corresponder, o cookie será associado ao domínio principal 'meudominio.com'; caso contrário, o cookie será associado ao domínio atual.
Dessa forma, quando os sistemas A, B, C, D, E e F são acessados, eles primeiro consultam o cookie _auth_session no domínio 'meudominio.com' para obter o token. Como todos os sistemas estão configurados para usar o mesmo domínio de cookie, o token persistido em um subdomínio se torna acessível aos outros, permitindo o login único e a autenticação transparente entre eles.