Autenticação reativa com Guards, Signals e Standalone Components em Angular (passo a passo)
Por John Pires · 16 de março de 2026

1) Por que aprender isso em 2026
Em 2026, aplicações web continuam exigindo UIs reativas, segurança nas rotas e arquiteturas componíveis. Angular evoluiu para tornar signals e standalone components peças centrais na construção de apps limpos e performáticos. Entender como integrar autenticação reativa com guards e signals evita lógica duplicada, facilita testes e reduz bugs de sincronização entre estado e UI.
Para iniciantes, a ideia central é simples: Signals mantêm estado reativo dentro do Angular sem depender exclusivamente de RxJS; Standalone Components removem a boilerplate de módulos; Guards protegem rotas com lógica executada pelo Router. Juntos, permitem um fluxo claro: serviço de autenticação (signal) → componente (consome o signal) → guard (decide acesso).
Neste artigo investigamos alternativas (RxJS, BehaviorSubject, NGRX) e escolhemos Signals por simplicidade para iniciantes, mantendo compatibilidade com RxJS quando necessário. Você verá por que essa combinação é mais robusta para apps pequenos e médios.
Resumo do problema: Como garantir que rotas estejam protegidas por um estado de autenticação que atualiza a UI de forma imediata, sem contestar a experiência do usuário e mantendo o código simples para quem está começando?
Alternativas e trade-offs
Podemos fazer autenticação com:
BehaviorSubject (RxJS): poderoso, mas adiciona complexidade de assinaturas e unsubscribe.
NGRX/Store: ótimo para apps grandes, mas complexo para iniciantes.
Signals (Angular): reatividade embutida, sintaxe direta e integração com templates.
Escolhemos Signals pela curva de aprendizado mais suave e pela integração direta com componentes standalone.
O que você vai aprender
Ao final terá um micro-projeto com:
Serviço de autenticação com signals.
Standalone components para Login, Home e Dashboard.
Guard que protege a rota de Dashboard.
Uso de Router com UrlTree para redirecionar não autenticados.
2) Configuração do ambiente
Comece com uma versão recente do Angular (16 ou superior é recomendável para signals e standalone). Tenha Node.js (>=18) e Angular CLI atualizados.
Passo a passo do setup
Crie um novo projeto Angular standalone:
npx @angular/cli@latest new auth-signals --standalone --routing --style=scssO comando acima gera um projeto sem módulos NgModule (ou reduz a sua necessidade) e já cria o roteamento básico. Depois, entre na pasta e instale dependências básicas:
cd auth-signals
npm install
Abra o projeto no editor. Vamos adicionar arquivos para serviço de autenticação, guards e componentes standalone.
Estrutura de arquivos que usaremos
Criar os arquivos abaixo:
src/app/services/auth.service.ts
src/app/guards/auth.guard.ts
src/app/login/login.component.ts (standalone)
src/app/dashboard/dashboard.component.ts (standalone)
src/app/home/home.component.ts (standalone)
Essa estrutura é didática e permite entender responsabilidades: serviço cuida do estado, guard decide sobre rotas, componentes mostram UI.
3) Hello World progressivo
Vamos construir passo a passo. Primeiro, o serviço de autenticação usando signals. Ele vai expor um signal público para o usuário e métodos login/logout. O login será simulado para manter simples.
Serviço de autenticação com signals
O código abaixo cria um serviço Angular que usa signal para armazenar o usuário autenticado. Signals são funções reativas; chama-se a signal para ler o valor e pode-se usar set para atualizar.
/* src/app/services/auth.service.ts
Serviço que mantém o estado de autenticação com signals.
- user: signal que contém um objeto { id, name } ou null
- login: simula autenticação assíncrona e atualiza a signal
- logout: limpa a signal
*/
import { Injectable, signal } from '@angular/core';
export interface User { id: string; name: string }
@Injectable({ providedIn: 'root' })
export class AuthService {
private _user = signal(null);
// exposição somente leitura (padrão: chamando a função)
user = () => this._user();
login(name: string) {
// Simula chamada de API com Promise
return new Promise((resolve) => {
setTimeout(() => {
const u: User = { id: Date.now().toString(), name };
this._user.set(u);
resolve(u);
}, 600); // simula latência
});
}
logout() {
this._user.set(null);
}
isAuthenticated(): boolean {
return !!this._user();
}
}
Após esse bloco, temos o estado centralizado. Qualquer componente pode injetar AuthService e usar auth.user() para ler o valor reativo.
Login component (standalone)
O LoginComponent usa o serviço para executar login. É um standalone component; não precisamos declarar em um módulo.
/* src/app/login/login.component.ts
Componente standalone simples com template inline.
- captura nome do usuário
- chama auth.login
*/
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { CommonModule } from '@angular/common';
import { AuthService } from '../services/auth.service';
@Component({
selector: 'app-login',
standalone: true,
imports: [CommonModule],
template:
Login
Entrar
Autenticando...
})
export class LoginComponent {
name = '';
loading = false;
constructor(private auth: AuthService, private router: Router) {}
async doLogin() {
this.loading = true;
await this.auth.login(this.name || 'Usuário');
this.loading = false;
this.router.navigateByUrl('/dashboard');
}
}
Depois de executar o login, navegamos para /dashboard. O guard da rota verificará a autenticidade.
4) Mini-projeto prático
Agora juntamos as peças: guard, rotas e componentes. O guard usará o AuthService com inject() para decisão. Também mostrarei como redirecionar com UrlTree quando não autenticado.
AuthGuard usando inject()
O guard é uma classe que implementa CanActivate. Ele injeta AuthService e Router via inject() para ser compatível com ambientes standalone e facilitar testes.
/* src/app/guards/auth.guard.ts
Guard que protege rotas. Retorna true se autenticado
ou um UrlTree apontando para /login para redirecionamento.
*/
import { Injectable, inject } from '@angular/core';
import { CanActivate, Router, UrlTree } from '@angular/router';
import { AuthService } from '../services/auth.service';
@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
canActivate(): boolean | UrlTree {
const auth = inject(AuthService);
const router = inject(Router);
if (auth.isAuthenticated()) return true;
return router.createUrlTree(['/login']);
}
}
Se não autenticado, retornamos um UrlTree que instrui o Router a redirecionar para /login. Isso evita navegações desnecessárias.
Dashboard e Home (standalone)
Dashboard mostra o usuário corrente via signal e permite logout. Home é público.
/* src/app/dashboard/dashboard.component.ts
Dashboard consome auth.user() diretamente para exibir dados.
*/
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AuthService } from '../services/auth.service';
@Component({
selector: 'app-dashboard',
standalone: true,
imports: [CommonModule],
template:
Dashboard
Bem-vindo, {{ u.name }} (id: {{ u.id }})
Estado inesperado: sem usuário
Sair
})
export class DashboardComponent {
constructor(public auth: AuthService) {}
user = this.auth.user; // signal exposta para template
logout() {
this.auth.logout();
}
}
Note que o template usa a signal como função: user(). Essa chamada reativa atualiza o template automaticamente quando o valor muda.
Roteamento com guard
Defina rotas no arquivo principal (app.routes.ts ou direto em main.ts dependendo do setup). Aqui um exemplo claro:
/* src/app/app.routes.ts
Rotas usando standalone components e guard
*/
import { Routes } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { AuthGuard } from './guards/auth.guard';
import { Component } from '@angular/core';
export const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', loadComponent: () => import('./home/home.component').then(m => m.HomeComponent) },
{ path: 'login', component: LoginComponent },
{ path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },
{ path: '**', redirectTo: 'home' }
];
Com isso, qualquer tentativa de acessar /dashboard passará pelo AuthGuard. Se o usuário não estiver autenticado, será redirecionado para /login.
Erros comuns, armadilhas e dicas práticas
Nesta seção destaco problemas que iniciantes frequentemente encontram e como evitá-los.
Erro 1: esquecer de fornecer o serviço ou importar correto
Se esquecer de adicionar providedIn: 'root' ou importar arquivos, o Angular pode criar múltiplas instâncias do serviço. Certifique-se de usar providedIn ou declarar providers apenas quando necessário.
Erro 2: chamadas síncronas no guard esperando assíncrono
Se a verificação de autenticação depende de uma chamada HTTP, transforme o guard para retornar Observable/Promise ou resolva o estado antes do navigational guard. Não bloqueie a UI com await longo; prefira retornar um UrlTree padrão e depois autenticar com flows apropriados.
Dica: para autenticação real, armazene token em cookie/secure storage e inicialize o signal na criação do serviço checando esse storage.
5) Recursos para continuar estudando
Se quiser aprofundar em cada peça, estude os seguintes tópicos e links oficiais. Aprender o core de signals e Router ajuda a construir aplicações escaláveis.
Recursos oficiais
Documentação oficial Angular — seção Signals
Guia de Router — Guards e UrlTree
Práticas recomendadas
Mantenha serviços puros: evite lógica de UI dentro deles.
Use signals para estado local e combine com RxJS quando precisar mapear streams externos.
Teste guards isoladamente injetando mocks de AuthService.
Conclusão prática
Signals + Guards + Standalone Components formam uma combinação eficiente para autenticação em Angular. Signals reduzem a complexidade das assinaturas RxJS para usos simples, standalone components tornam o projeto modular e Guards centralizam a decisão de acesso às rotas.
Próximos passos práticos:
Substitua o login simulado por uma chamada real a API e trate tokens com segurança.
Adicione um initialiser no serviço para restaurar sessão a partir do storage.
Implemente testes unitários para AuthService e AuthGuard.
O fluxo básico já implementado no mini-projeto serve como esqueleto para ampliar funcionalidades sem reescrever dependências centrais. Avance integrando Interceptor para adicionar token em requisições e usando effects/side-effects quando necessário.
Com esses conceitos consolidados você terá uma base sólida para construir aplicações reais e expandir para padrões mais avançados quando necessário.
Assuntos: Angular, signals, guards, standalone-components, routing, rxjs
Leia também
Cancelar requisições ao navegar: AbortController, Signals e RxJS em componentes standalone Angular
Padrões práticos para cancelar requisições HTTP ao navegar em Angular: combinar AbortController, rxjs/fromFetch e signals em components standalone para evitar…
Migrando BehaviorSubject para Signal em formulários Angular — passo a passo
Guia prático para migrar BehaviorSubject para Signal em formulários Angular: exemplos errados e corretos, patterns com standalone components, DI e routing, e…
Prefetch de dados por rota no Angular com Standalone Components e Signals
Aprenda a prefetch de dados por rota no Angular usando Standalone Components e Signals: combine ResolveFn com um PrefetchStore reativo para reduzir latência…
Wizard multi-step com rotas filhas, Signals e Standalone Components
Tutorial prático e direto para criar um wizard multi-step em Angular: rotas filhas para cada etapa, gerenciamento de estado com Signals e componentes…
Prefetch inteligente de rotas com Signals e RxJS em Standalone Components
Prefetch inteligente para Angular: combine Signals para estado e RxJS para orquestração de intents (hover, focus, intersection). Exemplo prático com…
Providers com escopo de rota em Angular standalone: signals, ciclo de vida e limpeza
Guia prático para usar providers com escopo de rota em Angular standalone: exemplos com Signals, factories que leem params de rota, limpeza via onCleanup e…