@riligar/auth-react 1.16.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -25,14 +25,17 @@ const getEnvVar = key => {
25
25
  };
26
26
  let API_BASE = (typeof window !== 'undefined' && window?.location ? getEnvVar('VITE_API_BASE') : null) || 'http://localhost:3000';
27
27
  let API_KEY = null;
28
+ let INTERNAL_MODE = false; // Modo interno: não exige API Key (para aplicações same-domain)
28
29
 
29
- // Permite configurar a API base e key externamente (chamado pelo AuthProvider)
30
+ // Permite configurar a API base, key e modo interno externamente (chamado pelo AuthProvider)
30
31
  function configure({
31
32
  apiUrl,
32
- apiKey
33
+ apiKey,
34
+ internal = false
33
35
  }) {
34
36
  if (apiUrl) API_BASE = apiUrl.replace(/\/$/, ''); // Remove trailing slash
35
37
  if (apiKey) API_KEY = apiKey;
38
+ INTERNAL_MODE = internal;
36
39
  }
37
40
 
38
41
  // helper fetch pré-configurado
@@ -54,12 +57,14 @@ async function api(route, opts = {}) {
54
57
  headers.Authorization = `Bearer ${token}`;
55
58
  }
56
59
 
57
- // Adiciona API Key se configurada
58
- if (API_KEY) {
60
+ // Adiciona API Key se configurada e não estiver em modo interno
61
+ if (API_KEY && !INTERNAL_MODE) {
59
62
  headers['X-API-Key'] = API_KEY;
60
63
  }
61
64
  const res = await fetch(url, {
62
65
  headers,
66
+ credentials: 'include',
67
+ // Required for sending session cookies
63
68
  ...opts
64
69
  });
65
70
 
@@ -390,46 +395,33 @@ const useAuthStore = zustand.create((set, get) => ({
390
395
  try {
391
396
  // Buscar application info primeiro (não bloqueia o init)
392
397
  fetchApplicationInfo();
398
+ let user = null;
393
399
 
394
- // Verifica se um token válido
395
- if (isAuthenticated()) {
396
- // Tenta extrair usuário do token (JWT)
397
- let user = getCurrentUser();
398
-
399
- // Se o token for opaco (não-JWT), getCurrentUser retorna null.
400
- // Precisamos buscar a sessão no servidor.
401
- if (!user) {
402
- try {
403
- const sessionData = await getSession();
404
- if (sessionData?.user) {
405
- user = sessionData.user;
406
- }
407
- if (sessionData?.session) {
408
- set({
409
- currentSession: sessionData.session
410
- });
411
- }
412
- } catch (sessionError) {
413
- console.warn('[AuthStore] Failed to fetch session:', sessionError);
414
- }
400
+ // PRIMEIRO: Tenta buscar sessão do servidor (funciona com cookies)
401
+ // Isso é essencial para Better Auth que usa session cookies
402
+ try {
403
+ const sessionData = await getSession();
404
+ if (sessionData?.user) {
405
+ user = sessionData.user;
415
406
  }
416
- if (user) {
417
- set({
418
- user,
419
- loading: false
420
- });
421
- } else {
407
+ if (sessionData?.session) {
422
408
  set({
423
- user: null,
424
- loading: false
409
+ currentSession: sessionData.session
425
410
  });
426
411
  }
427
- } else {
428
- set({
429
- user: null,
430
- loading: false
431
- });
412
+ } catch (sessionError) {
413
+ // Se falhar (401), continua para verificar localStorage token
414
+ console.log('[AuthStore] Server session not found, checking local token');
432
415
  }
416
+
417
+ // SEGUNDO: Se não encontrou sessão via cookies, verifica localStorage token (JWT)
418
+ if (!user && isAuthenticated()) {
419
+ user = getCurrentUser();
420
+ }
421
+ set({
422
+ user,
423
+ loading: false
424
+ });
433
425
  } catch (error) {
434
426
  console.error('Erro na inicialização:', error);
435
427
  set({
@@ -707,19 +699,41 @@ const useAuthStore = zustand.create((set, get) => ({
707
699
  throw err;
708
700
  }
709
701
  },
710
- revokeSession: async token => {
702
+ revokeSession: async sessionId => {
711
703
  const {
712
704
  setLoading,
713
- listSessions
705
+ currentSession,
706
+ sessions,
707
+ signOut
714
708
  } = get();
715
709
  setLoading('revokeSession', true);
716
710
  set({
717
711
  error: null
718
712
  });
719
713
  try {
720
- await revokeSession(token);
721
- // Refresh sessions list after revocation
722
- await listSessions();
714
+ console.log('[AuthStore] Revoking session:', {
715
+ targetId: sessionId,
716
+ currentId: currentSession?.id,
717
+ totalSessions: sessions.length
718
+ });
719
+
720
+ // Detect if current session OR last remaining session
721
+ const isCurrent = sessionId === currentSession?.id;
722
+ const isLast = sessions.length === 1 && sessions[0].id === sessionId;
723
+
724
+ // Se for a sessão atual ou a última, faz logout normal
725
+ if (isCurrent || isLast) {
726
+ console.log('[AuthStore] Revoking current/last session -> Executing signOut');
727
+ await signOut();
728
+ // signOut já limpa loading states e erros no finally, mas
729
+ // como estamos dentro do fluxo deste método, garantimos:
730
+ setLoading('revokeSession', false);
731
+ return;
732
+ }
733
+ await revokeSession(sessionId);
734
+
735
+ // NÃO atualiza a lista automaticamente - se for a sessão atual,
736
+ // listSessions() vai falhar com 401. O componente decide se quer atualizar.
723
737
  setLoading('revokeSession', false);
724
738
  } catch (err) {
725
739
  set({
@@ -887,11 +901,14 @@ function AuthProvider({
887
901
  apiUrl,
888
902
  // URL base da API (OBRIGATÓRIA)
889
903
  apiKey,
890
- // API Key para header X-API-Key (OBRIGATÓRIA)
904
+ // API Key para header X-API-Key (obrigatória exceto em modo internal)
905
+ internal = false,
906
+ // Modo interno: não exige API Key (para aplicações same-domain como dashboard)
891
907
  onError // Callback de erro global
892
908
  }) {
893
909
  // Validação de props obrigatórias
894
- if (!apiKey) {
910
+ // apiKey só é obrigatória se não estiver em modo internal
911
+ if (!internal && !apiKey) {
895
912
  throw new Error('[@riligar/auth-react] apiKey é obrigatória no AuthProvider. ' + 'Obtenha sua API Key no dashboard em https://dashboard.myauth.click');
896
913
  }
897
914
  if (!apiUrl) {
@@ -901,15 +918,15 @@ function AuthProvider({
901
918
  const startRefresh = useAuthStore(s => s.startRefresh);
902
919
  const checkTokenValidity = useAuthStore(s => s.checkTokenValidity);
903
920
 
904
- // Configura SDK com apiUrl e apiKey
905
- // Configura SDK com apiUrl e apiKey
921
+ // Configura SDK com apiUrl, apiKey e modo interno
906
922
  // Usamos useMemo para garantir que a configuração ocorra ANTES dos efeitos dos componentes filhos
907
923
  react.useMemo(() => {
908
924
  configure({
909
925
  apiUrl,
910
- apiKey
926
+ apiKey,
927
+ internal
911
928
  });
912
- }, [apiUrl, apiKey]);
929
+ }, [apiUrl, apiKey, internal]);
913
930
  react.useEffect(() => {
914
931
  init();
915
932
  startRefresh();
@@ -938,6 +955,8 @@ function AuthProvider({
938
955
  });
939
956
  // Dispara evento de logout para sincronizar entre abas
940
957
  localStorage.setItem('auth:logout', Date.now());
958
+ // Recarrega para redirecionar - deixa o Protect/rotas decidirem para onde ir
959
+ window.location.reload();
941
960
  };
942
961
  window.addEventListener('storage', handleStorageChange);
943
962
  window.addEventListener('auth:session-revoked', handleSessionRevoked);