#angular
#auth
#jwt
#security
Day 8 β Authentication, JWT, Guards, Interceptors & Auth Store
π Day 8 β Authentication, JWT, Guards, Interceptors & Auth Store
Zero to Hero β Hands-on Angular Tutorial
Today you will build:
- βοΈ Login page
- βοΈ
AuthService(signals + localStorage) - βοΈ JWT storage
- βοΈ HTTP Interceptor attaching Authorization headers
- βοΈ
AuthGuardblocking unauthorized pages - βοΈ Auto-redirect after login
- βοΈ Logout function
- βοΈ Protected dashboard page
This is real-world Angular authentication. Letβs do it! π
π¦ 1. Create AuthService (Signal-based Authentication Store)
Generate:
ng g service auth/auth
Open: auth.service.ts
import { Injectable, signal, computed, effect, inject } from '@angular/core';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root',
})
export class AuthService {
private http = inject(HttpClient);
private router = inject(Router);
private apiUrl = 'https://reqres.in/api/login'; // mock login endpoint
token = signal<string | null>(localStorage.getItem('token'));
isLoggedIn = computed(() => !!this.token());
constructor() {
effect(() => {
if (this.token()) {
localStorage.setItem('token', this.token()!);
} else {
localStorage.removeItem('token');
}
});
}
login(email: string, password: string) {
return this.http
.post<{ token: string }>(this.apiUrl, { email, password })
.subscribe({
next: (res) => {
this.token.set(res.token);
this.router.navigate(['/dashboard']);
},
error: () => alert('Invalid credentials'),
});
}
logout() {
this.token.set(null);
this.router.navigate(['/login']);
}
}
- βοΈ Uses signals
- βοΈ Persists login state
- βοΈ Auto-navigates on login/logout
- βοΈ Works with mock API
- βοΈ Ready to plug into real backend
π© 2. Create Login Page
Generate:
ng g component pages/login --standalone
login.component.ts
import { Component, inject } from '@angular/core';
import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';
import { AuthService } from '../../auth/auth.service';
@Component({
selector: 'app-login',
standalone: true,
imports: [ReactiveFormsModule],
templateUrl: './login.component.html',
})
export class LoginComponent {
fb = inject(FormBuilder);
auth = inject(AuthService);
form = this.fb.group({
email: ['', [Validators.required, Validators.email]],
password: ['', Validators.required],
});
submit() {
if (this.form.invalid) return;
const { email, password } = this.form.value;
this.auth.login(email!, password!);
}
}
login.component.html
<h2>Login</h2>
<form [formGroup]="form" (ngSubmit)="submit()">
<label>Email</label>
<input formControlName="email" />
<div *ngIf="form.controls['email'].touched && form.controls['email'].invalid">
Enter a valid email
</div>
<label>Password</label>
<input type="password" formControlName="password" />
<div *ngIf="form.controls['password'].touched && form.controls['password'].invalid">
Password is required
</div>
<button type="submit">Login</button>
</form>
- βοΈ A real login form
- βοΈ Validates input
- βοΈ Calls AuthService
π₯ 3. Create Dashboard (Protected Page)
Generate:
ng g component pages/dashboard --standalone
dashboard.component.ts
import { Component, inject } from '@angular/core';
import { AuthService } from '../../auth/auth.service';
@Component({
selector: 'app-dashboard',
standalone: true,
templateUrl: './dashboard.component.html',
})
export class DashboardComponent {
auth = inject(AuthService);
}
dashboard.component.html
<h2>Dashboard</h2>
<p>Welcome! You are logged in.</p>
<button (click)="auth.logout()">Logout</button>
- βοΈ Accessible only after login
- βοΈ Includes logout
π§ 4. Add AuthGuard
Generate:
ng g guard auth/auth --standalone
Open: auth.guard.ts
import { CanActivateFn, Router } from '@angular/router';
import { inject } from '@angular/core';
import { AuthService } from './auth.service';
export const authGuard: CanActivateFn = () => {
const auth = inject(AuthService);
const router = inject(Router);
if (auth.isLoggedIn()) {
return true;
} else {
router.navigate(['/login']);
return false;
}
};
- βοΈ Protects routes
- βοΈ Redirects automatically
- βοΈ Based on signal state
π¦ 5. Protect Routes
Open: app.routes.ts
import { authGuard } from './auth/auth.guard';
export const routes: Routes = [
{ path: 'login', loadComponent: () => import('./pages/login/login.component').then(m => m.LoginComponent) },
{
path: 'dashboard',
canActivate: [authGuard],
loadComponent: () => import('./pages/dashboard/dashboard.component').then(m => m.DashboardComponent)
},
{ path: '', redirectTo: 'login', pathMatch: 'full' }
];
- βοΈ Dashboard is protected
- βοΈ Login remains public
π§ 6. Add JWT to Every Request (Auth Interceptor)
Generate:
ng g interceptor auth/auth
auth.interceptor.ts
import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
import { AuthService } from './auth.service';
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const auth = inject(AuthService);
const token = auth.token();
if (!token) return next(req);
const cloned = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`,
},
});
return next(cloned);
};
Add to providers (main.ts or app.config.ts):
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { authInterceptor } from './auth/auth.interceptor';
bootstrapApplication(AppComponent, {
providers: [
provideHttpClient(withInterceptors([authInterceptor]))
]
});
- βοΈ Automatically attaches JWT
- βοΈ Works for all API requests
- βοΈ Clean and centralized
π© 7. Auto-Logout (Optional Bonus)
Inside AuthService:
autoLogoutAfter(ms: number) {
setTimeout(() => this.logout(), ms);
}
Call after login:
this.autoLogoutAfter(3600_000); // 1 hour
π« 8. Show Login State in Navbar
In AppComponent:
import { AuthService } from './auth/auth.service';
auth = inject(AuthService);
app.component.html:
<nav>
<a routerLink="/login" *ngIf="!auth.isLoggedIn()">Login</a>
<a routerLink="/dashboard" *ngIf="auth.isLoggedIn()">Dashboard</a>
<button *ngIf="auth.isLoggedIn()" (click)="auth.logout()">Logout</button>
</nav>
<router-outlet></router-outlet>
- βοΈ Reactive navbar
- βοΈ No RxJS
- βοΈ Pure signal goodness
π End of Day 8 β What You Achieved
Today you built:
- βοΈ Login form
- βοΈ AuthService with signals
- βοΈ AuthGuard
- βοΈ AuthInterceptor
- βοΈ Protected dashboard
- βοΈ LocalStorage persistence
- βοΈ Auto navigation on login/logout
- βοΈ Enterprise authentication pattern
This is a complete, modern Angular authentication setup. You are really leveling up πͺπ₯
π§ͺ Day 8 Challenge
Build a Profile Page that:
- is protected by
AuthGuard - loads user info from an API
- uses
authInterceptorfor token - has a logout button
- shows UI only when logged in