Belajar Angular - Security & Auth
Episode 12 of 24

Belajar Angular - Security & Auth

Episode ini membahas keamanan dan autentikasi: pola autentikasi dengan JWT, melindungi rute dengan auth guards, penyimpanan token dan HTTP calls yang aman, serta role-based authorization dan permission checks.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Sebagian besar aplikasi menyimpan data pengguna — dan data itu harus dilindungi. Autentikasi memverifikasi siapa penggunanya, sementara otorisasi menentukan apa yang boleh mereka akses.

Episode 12 membahas pola autentikasi dengan JWT, melindungi rute dengan auth guards, penyimpanan token dan HTTP calls yang aman, serta role-based authorization dan permission checks. Keamanan bukan fitur tambahan — ia bagian dari arsitektur.

Authentication Patterns dengan JWT

Alur Autentikasi JWT

JWT (JSON Web Token) adalah token yang berisi klaim terverifikasi. Alur umumnya: pengguna login, server mengembalikan access token (dan biasanya refresh token), aplikasi menyimpannya, lalu mengirimkannya di header tiap request.

JSService autentikasi dengan JWT
import { Injectable, inject, signal } from '@angular/core';
import { HttpClient } from '@angular/common/http';
 
@Injectable({ providedIn: 'root' })
export class AuthService {
  private readonly http = inject(HttpClient);
  readonly pengguna = signal<Pengguna | null>(null);
 
  login(email: string, password: string): void {
    this.http.post<LoginResponse>('/api/login', { email, password })
      .subscribe({
        next: (res) => {
          this.simpanToken(res.accessToken);
          this.pengguna.set(res.pengguna);
        },
        error: (err) => console.error('Login gagal', err),
      });
  }
}

login mengirim kredensial, lalu menyimpan access token dan state pengguna. Setelah ini, aplikasi tahu pengguna sudah terautentikasi dan bisa menampilkan UI yang sesuai.

Menyimpan Token

Penyimpanan token menentukan tingkat keamanan:

  • localStorage: mudah dipakai, tetapi rentan terhadap XSS — kode JavaScript apa pun di halaman bisa membaca token.
  • httpOnly cookie: tidak bisa dibaca JavaScript sehingga kebal XSS, tetapi membutuhkan penanganan CSRF.
  • In-memory: paling aman terhadap XSS, tetapi hilang saat refresh halaman.

Praktik terbaik modern: simpan access token di memory, refresh token di httpOnly cookie. Ini menghindari XSS sekaligus mempertahankan sesi.

Protecting Routes dengan Auth Guards

Guard Dasar

Guard dari episode 9 dipakai untuk melindungi rute yang butuh login:

JSAuth guard dengan redirect
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from './auth.service';
 
export const authGuard: CanActivateFn = () => {
  const auth = inject(AuthService);
  const router = inject(Router);
 
  if (auth.pengguna() !== null) {
    return true;
  }
  return router.createUrlTree(['/login'], { queryParams: { kembali: router.url } });
};

Pasang guard di route yang dilindungi: { path: 'profil', component: ProfilComponent, canActivate: [authGuard] }. Ketika pengguna belum login dan mencoba membuka rute tersebut, dia diarahkan ke halaman login dengan catatan halaman asal.

Guard untuk Data yang Belum Dimuat

Kadang token sudah ada, tetapi data pengguna belum dimuat. authGuard bisa menunggu selesainya pembaruan profil:

JSGuard yang menunggu data user
export const authGuard: CanActivateFn = () => {
  const auth = inject(AuthService);
  const router = inject(Router);
  const status = auth.muatProfil();
  return status ? true : router.createUrlTree(['/login']);
};

muatProfil di sini mengecek token lokal dan memuat data pengguna jika perlu. Guard mengembalikan true hanya setelah state autentikasi benar-benar pasti.

Token Storage dan Secure HTTP Calls

Menambahkan Token ke Request

Setiap request API harus membawa token. Tempat terpusatnya adalah HTTP interceptor:

JSInterceptor menyuntik token Bearer
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.getToken();
 
  if (!token) {
    return next(req);
  }
 
  const reqBaru = req.clone({
    setHeaders: { Authorization: `Bearer ${token}` },
  });
  return next(reqBaru);
};

authInterceptor menambahkan header Authorization: Bearer <token> ke setiap request. Interceptor didaftarkan di app.config.ts lewat provideHttpClient(withInterceptors([authInterceptor])). Semua request otomatis terautentikasi tanpa mengubah kode di setiap service.

Menangani Token Kedaluwarsa

Saat access token kedaluwarsa, server mengembalikan status 401. Tangani secara terpusat: refresh token lewat endpoint, ulangi request yang gagal, atau arahkan pengguna ke halaman login. Pola ini membuat sesi bertahan tanpa membuat pengguna login berulang kali.

Role-based Authorization dan Permission Checks

Menyimpan Role dan Permission

Otorisasi berbasis peran (RBAC) mengecek role pengguna sebelum memberi akses:

JSCek role dan permission
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from './auth.service';
 
export const roleGuard: CanActivateFn = () => {
  const auth = inject(AuthService);
  const router = inject(Router);
 
  if (auth.pengguna()?.role === 'admin') {
    return true;
  }
  return router.createUrlTree(['/forbidden']);
};

roleGuard hanya mengizinkan pengguna dengan role admin. Halaman forbidden menampilkan pesan akses ditolak. Kombinasikan guard auth dan role untuk area yang membutuhkan keduanya.

Permission di UI dan di Backend

Jangan hanya menyembunyikan tombol admin di UI — permission juga harus diverifikasi di backend. UI menyembunyikan atau menonaktifkan aksi yang tidak boleh dijalankan pengguna, sementara backend tetap memvalidasi setiap request. Dua lapis ini melindungi aplikasi dari manipulasi langsung lewat API.

Penutup

Inti yang harus dibawa pulang:

  • JWT adalah standar autentikasi: access token di header, refresh token di httpOnly cookie.
  • localStorage rentan XSS; simpan token sesensitif mungkin.
  • Auth guard fungsional melindungi rute dan mengarahkan pengguna ke login.
  • Interceptor menyuntik token ke semua request secara terpusat.
  • Tangani status 401 terpusat untuk refresh token dan retry.
  • RBAC memeriksa role, dan otorisasi selalu diverifikasi ulang di backend.

Di episode 13 selanjutnya kita akan membahas secure web practices — mencegah XSS, CSRF, dan injection, menerapkan content security policy dan secure headers, men-sanitize HTML dan menangani URL aman, serta praktik terbaik keamanan sisi klien.