Bayangkan ini: Kamu baru selesai membangun frontend React atau Vue yang berjalan di http://localhost:3000, dan REST API berbasis Laravel di http://localhost:8000. Setiap endpoint diuji melalui Postman atau Insomnia, semuanya mengembalikan data dengan lancar. Namun, begitu frontend memanggil API lewat fetch() atau axios dari browser, request justru diblokir. Di konsol developer muncul error berwarna merah:
Access to fetch at 'http://localhost:8000/api/users' from origin 'http://localhost:3000'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
on the requested resource.
Bagi developer yang baru beralihlah dari arsitektur monolitik ke arsitektur terpisah (decoupled), pesan error ini sering disalahartikan sebagai kerusakan di Laravel atau bug di PHP. Padahal server sebenarnya memproses request dan mengembalikan respons dengan baik. Yang menyaring adalah browser, bukan server.
CORS (Cross-Origin Resource Sharing) bukanlah error, dan juga bukan fitur yang bertugas mengamankan server dari serangan. CORS adalah mekanisme keamanan yang dijalankan oleh browser untuk melindungi data pengguna saat halaman web mencoba mengakses sumber daya dari origin yang berbeda.
Artikel ini membahas secara menyeluruh Same-Origin Policy, mengapa error CORS muncul, perbedaan Simple Request dan Preflight Request, penanganan kredensial dan cookie, konfigurasi di Laravel, PHP native, Nginx, dan Apache, serta solusi untuk error CORS yang paling sering muncul — tanpa mengabaikan aspek keamanan.
Mengenal Same-Origin Policy (SOP) dan Kenapa CORS Dibutuhkan
Sebelum membahas CORS, penting untuk memahami fondasi di baliknya: Same-Origin Policy (SOP). SOP adalah kebijakan keamanan wajib yang diberlakukan oleh semua browser modern. Kebijakan ini membatasi dokumen atau script yang dimuat dari satu origin agar tidak bebas berinteraksi dengan sumber daya dari origin lain.
Tujuan SOP sederhana: mencegah situs jahat membaca data sensitif milik situs lain. Tanpa SOP, jika kamu sedang login di https://bank-anda.com di satu tab, sambil membuka http://situs-jahat.com di tab lain, script milik situs jahat tersebut tidak boleh mengambil data rekening atau informasi pribadi kamu dari halaman bank melalui browser.
Anatomi Origin
Browser menentukan apakah dua alamat memiliki origin yang sama berdasarkan tiga komponen gabungan:
Origin = Protocol (Scheme) + Host (Domain/IP) + Port
Jika salah satu komponen berbeda, browser menganggapnya sebagai cross-origin (beda origin). Path dalam URL tidak berpengaruh pada penentuan origin.
Berdasarkan rute dasar https://example.com:443/app, berikut beberapa contohnya:
https://example.com/api— Same Origin. Protokol, host, dan port sama. Path berbeda tidak memengaruhi origin.http://example.com/api— Cross Origin. Protokol berbeda (httpdibandinghttps).https://api.example.com/app— Cross Origin. Host berbeda karena subdomainapibukanexample.com.https://example.com:8080/app— Cross Origin. Port berbeda (8080dibanding443).https://example.com/app/users— Same Origin. Semua komponen origin identik.
CORS Melonggarkan SOP dengan Cara Terkontrol
Arsitektur web modern memisahkan frontend dan backend. Frontend SPA mungkin di-host di https://app.com, sementara backend REST API berada di https://api.com atau subdomain lain. Tanpa mekanisme tambahan, browser akan memblokir fetch() dan XMLHttpRequest lintas origin, meskipun server sudah berhasil memproses request dan mengembalikan respons.
CORS hadir sebagai solusi standar. Melalui sekumpulan HTTP header, server memberitahu browser bahwa origin tertentu diizinkan untuk membaca respons dari API tersebut. Dengan CORS, SOP dapat "diloonggarkan" secara terkontrol dan aman, bukan dibuang seluruhnya. CORS adalah cara server untuk "opt-in" membagikan respons ke origin lain yang dipercaya.
Mengapa Error CORS Muncul di Browser
Error CORS terjadi bukan karena server Laravel atau PHP crash, menolak koneksi, atau mengembalikan status 500. Server biasanya memproses request dan mengembalikan respons HTTP dengan baik. Yang memblokir adalah browser, karena respons dari server tidak menyertakan HTTP header CORS yang mengizinkan origin pemanggil.
Sebuah respons yang valid dari sudut server bisa saja ditolak browser saat dicek terhadap kebijakan CORS. Ini sebabnya error CORS sering terlihat sebagai "error browser" padahal akar masalahnya ada pada konfigurasi header respons.
Mekanisme CORS berjalan sepenuhnya melalui HTTP Request Header dan HTTP Response Header. Berikut header utama yang terlibat:
Header pada Request (dikirim browser)
Browser secara otomatis menyertakan beberapa header saat melakukan request lintas origin. Header Origin dikirim pada setiap request cross-origin, baik yang sederhana maupun preflight. Header ini berisi origin tempat script dipanggil, hanya terdiri dari scheme, host, dan port (tanpa path).
Origin: https://frontend-aplikasi.com
Header Origin termasuk forbidden header name, yang berarti JavaScript di sisi klien tidak dapat memalsukan atau mengubah nilainya. Ini mencegah situs jahat meniru origin situs lain untuk menipu server.
Pada preflight request, browser juga menyertakan:
Access-Control-Request-Method— memberitahu server metode HTTP yang akan digunakan request aktual (misalnyaPUTatauDELETE).Access-Control-Request-Headers— memberitahu server header kustom yang akan dikirim request aktual (misalnyaAuthorizationatauContent-Type).
Header pada Respons (dikirim server)
Server merespons dengan header yang memberitahu browser apakah respons boleh dibagikan ke JavaScript di origin pemanggil:
Access-Control-Allow-Origin— origin yang diizinkan membaca respons. Nilai bisa berupa origin spesifik (https://app.com) atau wildcard (*). Untuk request yang membawa kredensial, wildcard tidak diperbolehkan dan harus diisi origin secara eksplisit.Access-Control-Allow-Methods— daftar metode HTTP yang diizinkan server (hanya relevan pada respons preflight), misalnyaGET, POST, PUT, DELETE, OPTIONS.Access-Control-Allow-Headers— daftar header kustom request yang diizinkan server, sebagai tanggapan terhadapAccess-Control-Request-Headers, misalnyaContent-Type, Authorization, X-Requested-With.Access-Control-Allow-Credentials— bernilaitrueuntuk memberitahu browser bahwa respons boleh dibagikan jika request dikirim dengan kredensial (cookie, HTTP Auth, atau sertifikat klien TLS).Access-Control-Expose-Headers— response header mana yang boleh diakses JavaScript klien melaluiresponse.headers. Secara default hanya beberapa safelisted response headers yang dapat dibaca tanpa header ini.Access-Control-Max-Age— durasi dalam detik hasil preflight boleh disimpan dalam cache browser (preflight cache). Defaultnya 5 detik. Browser menerapkan batas maksimum internal, misalnya Chromium 7200 detik, Firefox 86400 detik, dan Safari/WebKit 600 detik. Nilai0menonaktifkan cache preflight.Vary: Origin— harus disertakan saatAccess-Control-Allow-Originditetapkan secara dinamis berdasarkan headerOriginrequest. Header ini memberitahu proxy dan CDN bahwa respons bervariasi menurut origin, sehingga cache tidak salah melayani respons milik origin A kepada pemanggil dari origin B.
Simple Request dan Preflight Request (OPTIONS)
Browser mengelompokkan request cross-origin ke dalam dua kategori: Simple Request dan Preflight Request. Pengelompokan ini menentukan apakah browser mengirim request langsung atau harus meminta izin kepada server terlebih dahulu.
Simple Request
Request dikategorikan sebagai Simple Request jika memenuhi semua syarat berikut:
- Menggunakan metode HTTP
GET,HEAD, atauPOST. - Hanya menggunakan header yang terdaftar dalam CORS-safelisted headers:
Accept,Accept-Language,Content-Language,Content-Type, danRange(hanya satu nilai range). - Nilai header
Content-Typeterbatas padaapplication/x-www-form-urlencoded,multipart/form-data, atautext/plain. - Tidak ada event listener pada
XMLHttpRequestUpload, dan tidak ada penggunaanReadableStream.
Pada Simple Request, browser langsung mengirim request HTTP ke server sambil menyertakan header Origin. Saat server merespons, browser memeriksa header Access-Control-Allow-Origin. Jika nilai header tidak cocok dengan origin pemanggil, browser melempar error dan menyembunyikan respons dari JavaScript.
Preflight Request (OPTIONS)
Jika request tidak memenuhi syarat Simple Request, browser menahan request utama dan mengirim Preflight Request terlebih dahulu menggunakan metode OPTIONS.
Kasus yang memicu preflight pada REST API modern meliputi penggunaan header Authorization (misalnya Bearer <token>), pengiriman data JSON dengan Content-Type: application/json, serta penggunaan metode PUT, PATCH, atau DELETE.
Alur kerja preflight terdiri dari tiga tahap:
-
Pengiriman preflight (
OPTIONS). Browser mengirim requestOPTIONSke server dengan headerAccess-Control-Request-MethoddanAccess-Control-Request-Headers, sertakanOrigin:OPTIONS /api/v1/users/12 HTTP/1.1 Host: api.example.com Origin: https://app.example.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: authorization, content-type -
Evaluasi server. Server memproses request
OPTIONSdan mengembalikan status HTTP200 OKatau204 No Contentbeserta header CORS:HTTP/1.1 204 No Content Access-Control-Allow-Origin: https://app.example.com Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS Access-Control-Allow-Headers: Authorization, Content-Type Access-Control-Allow-Credentials: true Access-Control-Max-Age: 86400 -
Pengiriman request aktual. Jika respons preflight disetujui, browser baru mengirim request aktual (misalnya
PUT /api/v1/users/12). Jika ditolak, browser menghentikan request dan mencetak error CORS di konsol.
Preflight request tidak pernah menyertakan kredensial seperti cookie. Namun, respons preflight boleh menyertakan Access-Control-Allow-Credentials: true untuk memberikan izin kepada request aktual yang membawa kredensial.
Kredensial, Cookie, dan Header Authentication
Kredensial dalam spesifikasi CORS mencakup cookie HTTP, header autentikasi HTTP (seperti Basic Auth), dan sertifikat klien TLS.
Secara default, browser tidak mengirim kredensial pada request cross-origin menggunakan fetch() atau XMLHttpRequest. Pengiriman kredensial harus diaktifkan secara eksplisit di sisi klien:
- Fetch:
fetch(url, { credentials: 'include' }) - Axios:
axios.defaults.withCredentials = true
Aturan utama: kredensial tidak boleh pasangan wildcard *
Ini adalah aturan terpenting saat bekerja dengan kredensial dan CORS. Jika request dikirim dengan kredensial (credentials: 'include'), header Access-Control-Allow-Origin tidak boleh menggunakan wildcard *. Server wajib mengembalikan nama origin secara eksplisit.
Jika kamu mengatur 'supports_credentials' => true di config/cors.php Laravel, tetapi 'allowed_origins' masih berisi ['*'], browser akan memblokir respons dan mencatat error:
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*'
when the request's credentials mode is 'include'.
Aturan yang sama juga berlaku untuk Access-Control-Allow-Headers, Access-Control-Allow-Methods, dan Access-Control-Expose-Headers saat kredensial digunakan: harus berupa daftar eksplisit, bukan *.
Integrasi Laravel Sanctum dan Session SPA
Jika kamu membangun SPA dengan Laravel Sanctum atau session cookie, tentukan allowed_origins secara eksplisit di config/cors.php, dan sesuaikan SESSION_DOMAIN serta SANCTUM_STATEFUL_DOMAINS di file .env agar session cookie dikenali di seluruh subdomain yang terlibat.
SESSION_DOMAIN=.domainanda.com
SANCTUM_STATEFUL_DOMAINS="localhost:3000,myapp.com"
Mengonfigurasi CORS di Laravel
Mulai Laravel 7, penanganan CORS sudah built-in melalui paket fruitcake/laravel-cors yang terintegrasi ke dalam framework dengan middleware Illuminate\Http\Middleware\HandleCors.
Middleware HandleCors dipasang secara global di paling atas stack middleware. Posisi ini krusial karena preflight request OPTIONS biasanya tidak membawa token autentikasi. Jika rute OPTIONS dihentikan oleh middleware autentikasi sebelum mencapai middleware CORS, server akan mengembalikan status 401 Unauthorized atau 405 Method Not Allowed, yang menyebabkan preflight gagal.
File konfigurasi config/cors.php
File konfigurasi utama CORS di Laravel dapat dihasilkan dengan perintah:
php artisan config:publish cors
Isi default config/cors.php biasanya seperti berikut:
<?php
return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => [
'http://localhost:3000',
'https://app.domainanda.com',
],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 86400,
'supports_credentials' => true,
];
Penjelasan setiap opsi konfigurasi
paths: Array pola URL yang diproses oleh middleware CORS. Defaultnya mencakupapi/*dansanctum/csrf-cookie.allowed_methods: Metode HTTP yang diizinkan. Nilai['*']mengizinkan semua metode.allowed_origins: Array domain frontend yang diizinkan. Jangan gunakan['*']jika kamu mengaktifkansupports_credentials.allowed_origins_patterns: Pencocokan origin menggunakan regex PHP (preg_match()), berguna untuk subdomain dinamis. Contoh:['#^https://.*\.domainanda\.com$#'].allowed_headers: Header request klien yang diizinkan server terima.exposed_headers: Header respons yang boleh dibaca oleh JavaScript di sisi klien.max_age: Durasi cache preflight request di browser dalam detik.supports_credentials: Settruejika frontend mengirim cookie session atau headerAuthorization.
Mengonfigurasi CORS di PHP Native dan Web Server
Jika kamu tidak menggunakan framework, header CORS dapat diatur secara manual dengan fungsi header() di PHP. Perlu diingat bahwa header() harus dipanggil sebelum ada output apa pun dikirim ke browser.
PHP Native (Plain PHP)
Contoh penanganan CORS dalam PHP murni dengan whitelist origin dan respons preflight OPTIONS:
<?php
$allowedOrigins = [
'http://localhost:3000',
'https://frontend.domainanda.com',
];
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin, $allowedOrigins, true)) {
header("Access-Control-Allow-Origin: {$origin}");
header("Access-Control-Allow-Credentials: true");
header("Vary: Origin");
}
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With");
header("Access-Control-Max-Age: 86400");
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit();
}
header("Content-Type: application/json");
echo json_encode(["status" => "success", "message" => "Data berhasil dimuat"]);
Header Vary: Origin sangat penting saat Access-Control-Allow-Origin ditetapkan secara dinamis dari PHP. Header ini meminta reverse proxy atau CDN untuk tidak menyajikan respons cache milik origin A kepada pemanggil dari origin B.
Peringatan: jangan gabungkan Access-Control-Allow-Origin: * dengan Access-Control-Allow-Credentials: true. Browser akan menolak kombinasi tersebut.
Nginx
Menangani CORS di level Nginx mempercepat respons karena Nginx dapat menjawab request OPTIONS tanpa meneruskannya ke PHP-FPM. Gunakan blok map sebagai whitelist agar tidak memantulkan $http_origin secara langsung, terutama saat Access-Control-Allow-Credentials bernilai true:
map $http_origin $cors_origin {
default "";
"https://app.domainanda.com" $http_origin;
"http://localhost:3000" $http_origin;
}
server {
listen 80;
server_name api.domainanda.com;
root /var/www/api/public;
index index.php;
location /api/ {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' $cors_origin always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Max-Age' 86400 always;
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain; charset=utf-8';
return 204;
}
add_header 'Access-Control-Allow-Origin' $cors_origin always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Vary' 'Origin' always;
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
}
Blok map di atas berfungsi sebagai whitelist. Hanya origin yang terdaftar yang akan diteruskan ke header Access-Control-Allow-Origin. Jika origin pengirim tidak cocok, variabel $cors_origin tetap kosong sehingga browser menolak request tersebut.
Jangan langsung memantulkan $http_origin tanpa validasi. Tanpa whitelist, konfigurasi tersebut sama saja mengizinkan semua origin membaca respons yang membawa kredensial — sebuah celah keamanan yang dikenal sebagai arbitrary origin reflection.
Apache
Pada Apache dengan modul mod_headers aktif, tambahkan aturan berikut pada file .htaccess atau VirtualHost:
<IfModule mod_headers.c>
Header always set Access-Control-Allow-Origin "https://frontend.domainanda.com"
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Header always set Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With"
Header always set Access-Control-Allow-Credentials "true"
Header always set Access-Control-Max-Age "86400"
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ - [R=204,L]
</IfModule>
Pilih satu layer saja
Pilih satu layer untuk menangani CORS: Laravel/PHP atau Nginx/Apache. Jangan mengaktifkan CORS di kedua layer sekaligus, karena akan menghasilkan header duplikat dan membuat browser menolak respons.
Error CORS yang Sering Muncul dan Cara Mengatasinya
Berikut beberapa error CORS yang sering ditemui dan solusinya:
Header Access-Control-Allow-Origin tidak ada
Pesan error:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Penyebab: Server tidak mengirim header CORS pada respons.
Solusi: Aktifkan middleware HandleCors di Laravel, atau tambahkan header header() di PHP/Nginx/Apache sesuai stack yang kamu gunakan.
Wildcard origin dengan kredensial
Pesan error:
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*'
when the request's credentials mode is 'include'.
Penyebab: Frontend mengirim kredensial (withCredentials: true), tetapi backend Laravel menggunakan 'allowed_origins' => ['*'].
Solusi: Ubah config/cors.php dan ganti wildcard * dengan domain spesifik:
'allowed_origins' => [
'http://localhost:3000',
'https://myapp.com',
],
'supports_credentials' => true,
Preflight request gagal (403 Forbidden atau 405 Method Not Allowed)
Pesan error:
Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
Penyebab: Request OPTIONS diblokir oleh web server, WAF, atau middleware autentikasi sebelum mencapai middleware CORS.
Solusi:
-
Pastikan rute
OPTIONStidak dimasukkan dalam grup middleware autentikasi. -
Pastikan
HandleCorsberada pada middleware global teratas. -
Bersihkan cache konfigurasi Laravel:
php artisan config:clear php artisan route:clear
Header duplikat Access-Control-Allow-Origin
Penyebab: Header CORS dikirim dua kali karena dikonfigurasi di Nginx/Apache dan di Laravel/PHP secara bersamaan.
Solusi: Hapus baris add_header CORS di Nginx atau Header di Apache jika CORS sudah dikelola via config/cors.php Laravel.
Best Practice Keamanan CORS
CORS bukan keamanan server
Miskonsepsi terbesar adalah anggap CORS sebagai fitur yang mengamankan API server dari hacker. Fakta: CORS bukan keamanan server. CORS adalah pembatasan yang dieksekusi oleh web browser.
Non-browser client seperti cURL, Postman, script Python, atau bot dapat dengan mudah memalsukan header Origin. Oleh karena itu, server tetap membutuhkan lapisan autentikasi dan otorisasi yang kuat (API Key, JWT Bearer Token, OAuth2, dan rate limiting). CORS hanya membatasi JavaScript dari origin lain untuk membaca respons cross-origin, bukan mencegah request dikirim sama sekali.
CORS vs CSRF
CORS sering dibingungkan dengan CSRF (Cross-Site Request Forgery), tetapi keduanya melindungi hal yang berbeda:
CORS membatasi browser agar JavaScript dari origin lain tidak dapat membaca respons API. Solusinya adalah pertukaran HTTP response header (Access-Control-Allow-*).
CSRF mencegah browser mengeksekusi mutasi data tanpa persetujuan pengguna, biasanya melalui tag HTML otomatis seperti formulir. Solusinya adalah anti-CSRF token dan atribut cookie SameSite.
Form HTML biasa tidak terpengaruh pembatasan CORS. Karena itu, CORS tidak menggantikan proteksi CSRF. Jika kamu menggunakan session cookie untuk autentikasi, pastikan masih menerapkan anti-CSRF token dan SameSite cookie, seperti yang dijelaskan dalam panduan CSRF dan autentikasi.
Checklist keamanan CORS
- Hindari wildcard
*di produksi jika menggunakan autentikasi atau kredensial. Daftarkan domain frontend secara eksplisit. - Batasi
allowed_methodsdanallowed_headerssesuai kebutuhan, jangan sembarangan*jika tidak perlu. - Jangan memantulkan
Originsecara sembarangan. Gunakan whitelist di Nginx (map) atau PHP (in_array). - Set
Vary: OriginsaatAccess-Control-Allow-Originditetapkan secara dinamis. - Gunakan
max_ageyang memadai (misalnya86400) untuk mengurangi beban preflightOPTIONSberulang, tetapi perhatikan batas maksimum per-browser. - Pisahkan asset publik (boleh menggunakan wildcard) dari API yang terautentikasi.
Skenario Nyata dan Solusinya
Development: SPA di localhost:3000, Laravel API di localhost:8000
Skenario paling umum saat mengembangkan SPA React/Vue dengan Laravel API. Pertama kali fetch() dipanggil, browser akan menampilkan error CORS karena origin localhost:3000 belum terdaftar di backend.
Solusi: tambahkan http://localhost:3000 ke allowed_origins di config/cors.php, dan set supports_credentials => true jika kamu menggunakan Sanctum dengan cookie session.
Produksi: frontend di app.com, API di api.com
Beda subdomain dianggap cross-origin oleh browser. Pastikan allowed_origins berisi domain produksi secara eksplisit, dan hindari wildcard * jika API menggunakan autentikasi atau cookie.
API publik tanpa login
API yang tidak membutuhkan autentikasi boleh menggunakan Access-Control-Allow-Origin: * untuk akses luas, asalkan tidak menangani kredensial.
Frontend dan API di balik Nginx reverse proxy
Ada risiko header duplikat jika CORS diatur baik di Nginx maupun Laravel. Rekomendasikan biarkan Laravel menangani CORS dan hapus konfigurasi CORS di Nginx, kecuali untuk aset statis.
Subdomain dinamis untuk banyak klien
Gunakan allowed_origins_patterns dengan regex untuk mencocokkan subdomain dinamis, atau pantulkan Origin secara dinamis di PHP dengan whitelist serta Vary: Origin.
Request JSON dengan Bearer token
Penggunaan header Authorization memicu preflight OPTIONS. Pastikan rute OPTIONS melewati middleware CORS tanpa terhenti di middleware autentikasi, agar preflight tidak gagal dengan status 401 atau 405.
Penutup
CORS (Cross-Origin Resource Sharing) bukan bug server, melainkan standar keamanan browser untuk melindungi data pengguna dari akses tidak sah lintas origin. Memahami Same-Origin Policy, perbedaan Simple Request dan Preflight Request, serta aturan kredensial adalah kunci untuk membangun aplikasi web terpisah yang aman dan handal.
Bagi developer PHP dan Laravel, langkah praktis yang bisa diambil adalah mengonfigurasi config/cors.php dengan domain frontend secara eksplisit, menghindari wildcard * saat supports_credentials => true, memastikan HandleCors berada di paling atas stack middleware agar preflight OPTIONS tidak diblokir autentikasi, dan memilih satu layer saja (Laravel atau web server) untuk menangani CORS sehingga tidak ada header duplikat. Terakhir, ingat bahwa CORS hanya membatasi pembacaan respons oleh browser; server tetap membutuhkan autentikasi dan otorisasi yang kuat sebagai pertahanan utama.
Untuk memahami spesifikasi dan perilaku browser terkait CORS lebih dalam, kamu bisa membaca dokumentasi MDN tentang CORS dan dokumentasi resmi Laravel mengenai dukungan CORS.
Jika kamu ingin mendalami topik keamanan terkait, baca artikel tentang CSRF dan Cara Mencegahnya dan Autentikasi dan Cara Kerjanya.
Fitur komentar belum diaktifkan oleh administrator.