Setiap developer web pasti pernah merasakan momen frustrasi ketika browser melontarkan pesan merah di console: "Access to XMLHttpRequest at '...' from origin '...' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."
Pesan ini, meskipun terasa seperti dinding penghalang, sebenarnya adalah bagian penting dari arsitektur keamanan web modern. CORS atau Cross-Origin Resource Sharing, adalah mekanisme keamanan yang diimplementasikan oleh browser untuk melindungi pengguna dari serangan lintas situs berbahaya. Tapi bagi kita para developer, ini seringkali jadi rintangan yang bikin pusing.
Artikel ini akan menjadi panduan lengkap Anda untuk memahami, mendiagnosis, dan mengatasi CORS policy error. Kita akan bahas dari sudut pandang server maupun client, serta strategi dan praktik terbaik yang saya pribadi gunakan dalam project nyata.
Apa Itu CORS Policy Error? Mengapa Ini Muncul?
Sebelum masuk ke solusi, mari kita pahami dulu akarnya. CORS bukanlah “bug” melainkan fitur keamanan yang sangat penting. Inti dari CORS adalah Same-Origin Policy (SOP).
Same-Origin Policy (SOP): Fondasi Keamanan Web
SOP adalah prinsip keamanan fundamental yang diterapkan oleh semua browser web modern. Aturan dasarnya sederhana: sebuah script yang dimuat dari satu “origin” (kombinasi protokol, host, dan port) hanya dapat mengakses sumber daya dari “origin” yang sama. Jika Anda mencoba mengambil data dari origin yang berbeda, browser akan memblokirnya.
Contoh:
https://aplikasi-saya.commencoba mengakses API dihttps://api.aplikasi-saya.com– Ini bukan same-origin karena subdomain berbeda.https://aplikasi-saya.com:8080mencoba mengakses API dihttps://aplikasi-saya.com:3000– Ini bukan same-origin karena port berbeda.http://aplikasi-saya.commencoba mengakses API dihttps://aplikasi-saya.com– Ini bukan same-origin karena protokol berbeda.
Tujuan SOP adalah mencegah situs jahat membaca data sensitif dari situs lain yang mungkin sedang Anda buka (misalnya, data bank, sesi login, dll.) tanpa izin eksplisit.
Bagaimana CORS Memainkan Peran?
CORS hadir sebagai “pelonggaran” terkontrol dari SOP. Ini memungkinkan server untuk secara eksplisit memberi tahu browser bahwa “boleh, saya mengizinkan sumber daya saya diakses oleh origin ini.” Tanpa CORS, setiap kali aplikasi frontend Anda (misalnya, React, Vue, Angular) yang berjalan di localhost:3000 mencoba mengambil data dari backend API di api.domain.com, browser akan memblokirnya secara default.
Proses CORS melibatkan beberapa header HTTP spesifik yang dipertukarkan antara browser dan server:
- Request Header: Browser mengirimkan header
Originyang berisi origin dari mana permintaan berasal (misalnya,Origin: https://aplikasi-saya.com). - Response Header: Server harus merespons dengan header
Access-Control-Allow-Origin(misalnya,Access-Control-Allow-Origin: https://aplikasi-saya.comatauAccess-Control-Allow-Origin: *untuk mengizinkan semua origin).
Preflight Request (Permintaan OPTIONS)
Untuk permintaan HTTP tertentu (yang dianggap “non-simple”), browser akan mengirimkan permintaan “preflight” (OPTIONS request) terlebih dahulu sebelum permintaan sebenarnya (GET, POST, PUT, DELETE). Permintaan non-simple meliputi:
- Penggunaan metode HTTP selain GET, POST, HEAD.
- Penggunaan header kustom (misalnya,
Authorization). - Tipe konten tertentu (misalnya,
application/jsondengan metode POST).
Preflight request bertujuan untuk menanyakan kepada server apakah permintaan yang akan datang diizinkan. Server harus merespons dengan header CORS yang sesuai untuk permintaan OPTIONS tersebut, termasuk Access-Control-Allow-Methods dan Access-Control-Allow-Headers. Jika preflight berhasil, browser akan melanjutkan dengan permintaan aslinya.
Mendeteksi CORS Error: Gejala dan Pesan Kesalahan
CORS error selalu muncul di developer console browser Anda (biasanya dengan menekan F12 lalu pilih tab “Console”). Beberapa pesan kesalahan umum yang akan Anda lihat:
Access to XMLHttpRequest at '...' from origin '...' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.- Ini adalah pesan paling umum. Artinya server tidak mengirimkan header
Access-Control-Allow-Originsama sekali, atau nilai yang dikirimkan tidak cocok dengan origin browser Anda.
- Ini adalah pesan paling umum. Artinya server tidak mengirimkan header
Access to XMLHttpRequest at '...' from origin '...' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied origin.- Server mengirimkan header
Access-Control-Allow-Origin, tetapi nilainya tidak cocok dengan origin permintaan Anda.
- Server mengirimkan header
Access to XMLHttpRequest at '...' from origin '...' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.- Ini mengindikasikan masalah pada permintaan preflight (OPTIONS). Server mungkin tidak merespons dengan status 200 OK untuk permintaan OPTIONS, atau tidak mengirimkan header CORS yang benar pada respons OPTIONS.
Access to XMLHttpRequest at '...' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-untrusted, https.- Ini sering terjadi ketika Anda mencoba mengakses file lokal (misalnya,
file:///index.html) yang mencoba melakukan permintaan ke server. Originfile://dianggapnulloleh browser.
- Ini sering terjadi ketika Anda mencoba mengakses file lokal (misalnya,
Kunci untuk mendiagnosis adalah melihat tab “Network” di developer console Anda. Periksa permintaan API yang gagal, lihat bagian “Headers”, dan cari header Origin pada request dan header Access-Control-Allow-Origin pada response. Seringkali, masalah ada pada konfigurasi header response server.
Cara Mengatasi CORS Policy Error (Sisi Server)
Mayoritas solusi CORS ada di sisi backend. Server Anda perlu secara eksplisit “mengizinkan” permintaan dari origin tertentu.
1. Mengkonfigurasi Header `Access-Control-Allow-Origin`
Ini adalah header paling krusial. Server harus menyertakan header ini dalam responsnya.
- Mengizinkan Origin Tertentu (Paling Aman):
Jika Anda tahu persis dari mana permintaan frontend akan datang, sebutkan origin tersebut. Ini adalah praktik terbaik untuk keamanan.
Access-Control-Allow-Origin: https://aplikasi-frontend-saya.comJika Anda memiliki beberapa origin yang sah (misalnya, pengembangan dan produksi), Anda bisa mengatur server untuk secara dinamis memeriksa header
Origindari request dan merespons denganAccess-Control-Allow-Originyang cocok, atau daftar putih (whitelist) beberapa origin. - Mengizinkan Semua Origin (Kurang Aman, Hanya untuk Pengembangan/API Publik):
Menggunakan wildcard
*berarti server Anda akan menerima permintaan dari origin mana pun. Ini sangat nyaman untuk pengembangan, tapi berisiko di produksi kecuali API Anda memang ditujukan untuk publik dan tidak menangani data sensitif.Access-Control-Allow-Origin: *Catatan: Jika Anda menggunakan
Access-Control-Allow-Origin: *, Anda tidak bisa menyertakan headerAccess-Control-Allow-Credentials: true. Browser akan memblokir ini karena dianggap tidak aman.
2. Mengizinkan Metode HTTP Tertentu (`Access-Control-Allow-Methods`)
Untuk permintaan preflight (OPTIONS), server perlu memberitahu browser metode HTTP apa saja yang diizinkan (GET, POST, PUT, DELETE, dll.).
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
3. Mengizinkan Header Kustom (`Access-Control-Allow-Headers`)
Jika frontend Anda mengirimkan header kustom (misalnya, Authorization token, X-Custom-Header), server perlu mengizinkannya di respons preflight.
Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With, Accept, Origin
Sertakan semua header yang diharapkan akan dikirimkan oleh klien Anda.
4. Menangani Kredensial (`Access-Control-Allow-Credentials`)
Jika permintaan frontend Anda perlu mengirimkan cookies atau authentication header (seperti token JWT yang disimpan di cookies), server harus menyertakan header ini.
Access-Control-Allow-Credentials: true
Penting: Jika Anda menggunakan Access-Control-Allow-Credentials: true, nilai Access-Control-Allow-Origin tidak boleh *. Anda harus menyebutkan origin spesifik (misalnya, https://aplikasi-frontend-saya.com).
5. Masa Berlaku Preflight Request (`Access-Control-Max-Age`)
Untuk meningkatkan performa, Anda bisa memberitahu browser berapa lama hasil preflight request bisa di-cache. Ini mengurangi jumlah preflight request yang dikirimkan browser.
Access-Control-Max-Age: 86400 // Cache selama 24 jam (dalam detik)
Contoh Implementasi Sederhana di Backend
Implementasi akan sangat tergantung pada teknologi backend Anda. Berikut adalah beberapa contoh konsep:
Node.js dengan Express
Menggunakan middleware cors sangat direkomendasikan:
const express = require('express');
const cors = require('cors');
const app = express();
const corsOptions = {
origin: 'https://aplikasi-frontend-saya.com', // Ganti dengan origin frontend Anda
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
credentials: true, // Izinkan cookies atau header otentikasi
optionsSuccessStatus: 204 // Untuk preflight request
};
app.use(cors(corsOptions));
// Atau, untuk mengizinkan semua (hati-hati di produksi):
// app.use(cors());
app.get('/api/data', (req, res) => {
res.json({ message: 'Data dari API' });
});
app.listen(3000, () => {
console.log('Server berjalan di port 3000');
});
Python dengan Flask
Menggunakan Flask-CORS:
from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
CORS(app, resources={r"/api/*": {"origins": "https://aplikasi-frontend-saya.com"}})
# Atau CORS(app) untuk mengizinkan semua (hati-hati)
@app.route('/api/data')
def get_data():
return jsonify({"message": "Data dari API"})
if __name__ == '__main__':
app.run(debug=True)
PHP dengan Laravel (di app/Http/Middleware/Cors.php atau menggunakan package)
Anda bisa membuat middleware atau menggunakan package seperti barryvdh/laravel-cors:
// Contoh manual di dalam middleware handle()
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin', 'https://aplikasi-frontend-saya.com')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'Content-Type, X-Requested-With, Authorization');
}
Nginx sebagai Reverse Proxy
Jika Nginx berada di depan backend Anda, Anda bisa mengkonfigurasi CORS di Nginx:
server {
listen 80;
server_name api.domain.com;
location / {
# Mengizinkan origin spesifik
# if ($http_origin ~* "^https?://(aplikasi-frontend-saya.com)$") {
# add_header "Access-Control-Allow-Origin" "$http_origin";
# }
# Atau mengizinkan semua (hati-hati)
add_header "Access-Control-Allow-Origin" "*";
add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, PUT, DELETE";
add_header "Access-Control-Allow-Headers" "Content-Type, Authorization";
add_header "Access-Control-Allow-Credentials" "true"; // Jika perlu
if ($request_method = 'OPTIONS') {
add_header "Access-Control-Max-Age" "1728000";
add_header "Content-Type" "text/plain charset=UTF-8";
add_header "Content-Length" "0";
return 204;
}
proxy_pass http://localhost:PORT_BACKEND; // Ganti dengan port backend Anda
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Cara Mengatasi CORS Policy Error (Sisi Client/Frontend)
Meskipun sebagian besar masalah CORS harus diselesaikan di sisi server, ada beberapa strategi yang bisa Anda terapkan di frontend, terutama untuk pengembangan.
1. Menggunakan Proxy Server (Saat Pengembangan)
Ini adalah solusi paling umum dan direkomendasikan untuk pengembangan frontend. Anda mengkonfigurasi server pengembangan frontend (misalnya, Webpack Dev Server, Create React App proxy, Vue CLI proxy) untuk meneruskan permintaan API ke backend Anda.
Browser Anda akan melihat permintaan API sebagai “same-origin” karena permintaan tersebut sebenarnya ditujukan ke server pengembangan frontend Anda, yang kemudian meneruskannya ke backend. Dengan begini, browser tidak akan memblokir karena tidak melihat adanya permintaan lintas origin.
Contoh di Create React App (package.json)
// package.json
{
"name": "my-react-app",
"version": "0.1.0",
"private": true,
"dependencies": { /* ... */ },
"scripts": { /* ... */ },
"eslintConfig": { /* ... */ },
"browserslist": { /* ... */ },
"proxy": "http://localhost:5000" // Ganti dengan URL backend Anda
}
Sekarang, jika Anda memanggil /api/data dari frontend, itu akan otomatis dialihkan ke http://localhost:5000/api/data.
2. Memastikan URL API yang Benar
Terkadang, masalahnya sesederhana salah ketik URL API atau lupa menyertakan protokol yang benar (misalnya, menggunakan http:// padahal backend berjalan di https://). Selalu periksa ulang URL yang Anda panggil di kode frontend Anda.
3. Menggunakan Browser Extension (Hanya untuk Debugging/Pengujian Pribadi)
Ada ekstensi browser seperti “CORS Unblock” atau “Allow CORS: Access-Control-Allow-Origin” yang bisa menonaktifkan atau memodifikasi CORS di sisi browser Anda. Ini sama sekali tidak direkomendasikan untuk penggunaan sehari-hari atau untuk produksi, karena melemahkan keamanan browser Anda. Gunakan hanya untuk debugging cepat di lingkungan pengembangan dan pastikan untuk menonaktifkannya setelah selesai.
Pengalaman dan Pertimbangan Praktis dalam Mengatasi CORS
Sebagai seorang developer yang sering berkutat dengan integrasi API, saya punya beberapa observasi dan tips praktis:
- Keamanan Selalu Nomor Satu: Jangan pernah mengabaikan keamanan demi kemudahan. Menggunakan
Access-Control-Allow-Origin: *di lingkungan produksi untuk API yang menangani data sensitif adalah resep bencana. Selalu spesifikkan origin yang diizinkan. - Preflight Sering Terlupakan: Banyak developer baru lupa bahwa permintaan OPTIONS juga perlu dikonfigurasi dengan benar. Jika Anda melihat error terkait preflight, pastikan server Anda merespons dengan status 204 atau 200 OK dan header CORS yang lengkap untuk metode OPTIONS.
- Cache Browser Dapat Menyesatkan: Terkadang, setelah Anda memperbaiki konfigurasi CORS di server, browser masih menyimpan respons lama. Coba lakukan “hard refresh” (Ctrl+Shift+R atau Cmd+Shift+R) atau kosongkan cache browser.
- CORS Bukan Otentikasi: Penting untuk diingat bahwa CORS hanya mengatur izin browser untuk melakukan permintaan lintas origin. Itu tidak menggantikan kebutuhan untuk otentikasi dan otorisasi API Anda. Bahkan jika permintaan diizinkan oleh CORS, API Anda masih harus memverifikasi siapa yang membuat permintaan dan apakah mereka memiliki izin.
- Lingkungan Pengembangan vs. Produksi: Selalu pisahkan konfigurasi CORS untuk lingkungan pengembangan dan produksi. Di pengembangan, Anda mungkin bisa lebih longgar (misalnya, mengizinkan
localhost:3000). Di produksi, Anda harus sangat ketat. - Peran Load Balancer/Proxy: Jika Anda menggunakan Nginx, Apache, atau layanan Load Balancer/API Gateway (seperti AWS API Gateway) di depan backend Anda, pastikan konfigurasi CORS dilakukan di sana, atau setidaknya diperiksa ulang. Terkadang, proxy tersebut justru yang menghapus atau mengubah header CORS.
Masalah yang Sering Terjadi dan Solusi Cepatnya
CORS bisa jadi rumit, dan beberapa masalah muncul berulang kali. Berikut adalah skenario umum dan solusinya:
1. Error: `Origin null is not allowed by Access-Control-Allow-Origin`
Gejala: Pesan ini muncul saat mengakses file lokal (misalnya, file:///index.html) yang mencoba membuat permintaan API.
Penyebab: Browser menganggap origin file:// sebagai null karena tidak memiliki host atau port yang jelas. Server Anda tidak secara eksplisit mengizinkan origin null.
Solusi:
- Jangan mengakses langsung file HTML lokal. Selalu jalankan aplikasi frontend Anda melalui server pengembangan (misalnya,
npm startuntuk React,yarn serveuntuk Vue) sehingga memiliki origin yang valid (misalnya,http://localhost:3000). - Jika terpaksa harus menguji dari file lokal dan ini hanya untuk pengembangan, Anda bisa menambahkan
nullke daftar origin yang diizinkan di server Anda (misalnya,Access-Control-Allow-Origin: null), tapi ini sangat tidak direkomendasikan untuk lingkungan selain pengembangan.
2. Error: `No ‘Access-Control-Allow-Origin’ header is present`
Gejala: Browser console menampilkan error yang mengatakan header tersebut tidak ada.
Penyebab: Server API Anda sama sekali tidak mengirimkan header Access-Control-Allow-Origin, atau mengirimkannya dengan nilai yang salah (misalnya, salah ketik).
Solusi:
- Periksa konfigurasi CORS di server backend Anda. Pastikan kode atau konfigurasi web server (Nginx/Apache) Anda secara eksplisit menambahkan header
Access-Control-Allow-Originke setiap respons yang relevan. - Gunakan developer tools (tab Network) untuk memeriksa respons dari server. Lihat apakah header tersebut benar-benar ada dan nilainya sesuai.
- Jika Anda menggunakan framework backend, pastikan middleware CORS diaktifkan dan dikonfigurasi dengan benar.
3. Error: `Response to preflight request doesn’t pass access control check`
Gejala: Permintaan yang melibatkan metode non-simple (POST dengan JSON, PUT, DELETE, dll.) gagal pada fase OPTIONS request.
Penyebab: Server Anda tidak menangani permintaan OPTIONS dengan benar, atau tidak menyertakan header CORS yang lengkap pada respons OPTIONS.
Solusi:
- Pastikan server Anda merespons permintaan OPTIONS dengan status 200 OK atau 204 No Content.
- Pastikan header
Access-Control-Allow-MethodsdanAccess-Control-Allow-Headersdisertakan dalam respons untuk permintaan OPTIONS, dan nilainya mencakup metode dan header yang akan digunakan klien Anda. - Jika Anda menggunakan Nginx atau Apache, pastikan blok konfigurasi untuk metode OPTIONS ada dan benar (seperti contoh Nginx di atas).
4. CORS di Lingkungan Produksi vs. Pengembangan
Gejala: API berfungsi baik di localhost tapi error di server produksi.
Penyebab: Konfigurasi CORS Anda hanya mengizinkan localhost atau IP pengembangan, bukan URL domain produksi.
Solusi:
- Perbarui daftar origin yang diizinkan di konfigurasi CORS server Anda untuk menyertakan domain produksi frontend Anda (misalnya,
https://aplikasi-anda.com). - Jika Anda memiliki lingkungan staging dan produksi, pertimbangkan untuk memiliki konfigurasi CORS yang berbeda untuk masing-masing lingkungan, atau daftar putih kedua domain tersebut.
FAQ
Apa itu Same-Origin Policy (SOP)?
Same-Origin Policy adalah kebijakan keamanan browser yang membatasi dokumen atau script yang dimuat dari satu origin (kombinasi protokol, host, dan port) untuk berinteraksi dengan sumber daya dari origin yang berbeda. Ini mencegah situs jahat membaca data sensitif dari situs lain.
Apakah mengizinkan `Access-Control-Allow-Origin: *` aman?
Mengizinkan semua origin dengan * tidak aman untuk API yang menangani data sensitif atau memerlukan otentikasi. Ini membuka potensi serangan Cross-Site Request Forgery (CSRF) dan memungkinkan situs manapun untuk membaca data Anda. Sebaiknya hanya digunakan untuk API publik tanpa kredensial atau dalam lingkungan pengembangan.
Bagaimana CORS di `localhost`?
CORS policy tetap berlaku di localhost. Jika frontend Anda berjalan di http://localhost:3000 dan backend di http://localhost:5000, mereka dianggap sebagai origin yang berbeda karena port yang berbeda. Maka, konfigurasi CORS di backend tetap diperlukan untuk mengizinkan http://localhost:3000.
Apakah CORS terjadi pada POST requests saja?
Tidak. CORS bisa terjadi pada semua jenis permintaan HTTP (GET, POST, PUT, DELETE, dll.) jika permintaan tersebut lintas origin. Namun, permintaan “non-simple” (seperti POST dengan Content-Type: application/json, PUT, DELETE, atau yang menggunakan header kustom) akan memicu preflight request (OPTIONS) terlebih dahulu.
Kesimpulan
CORS policy error adalah tantangan yang hampir pasti akan dihadapi setiap developer web. Meskipun terasa menjengkelkan, memahami dasar-dasar Same-Origin Policy dan bagaimana CORS bekerja adalah kunci untuk mengatasi masalah ini secara efektif.
Ingat, sebagian besar solusi ada di sisi server dengan mengkonfigurasi header HTTP yang benar. Selalu utamakan keamanan dengan mengizinkan origin spesifik daripada menggunakan wildcard, terutama di lingkungan produksi. Dengan pemahaman dan implementasi yang tepat, CORS tidak akan lagi menjadi penghalang, melainkan mekanisme keamanan yang Anda kuasai untuk membangun aplikasi web yang kuat dan aman.
TAGS: CORS, CORS Policy Error, Mengatasi CORS, API, Developer Tools, Web Development, Backend, Frontend, HTTP Headers, Debugging



