Pada Chapter Prinsip Keamanan kita melihat connectionStatus yang melaporkan authenticatedUsers kosong — koneksi tanpa identitas yang tetap bisa berbuat apa pun. Authentication adalah mekanisme yang menjawab pertanyaan pertama keamanan: siapa yang sedang terhubung? Chapter ini membahas mekanisme yang tersedia, cara kerja SCRAM sebagai mekanisme default, peran authenticationDatabase, dan langkah menyalakan authentication di server sungguhan.

Peta materi Chapter ini:

  • Perbedaan authentication (siapa Anda) dan authorization (boleh melakukan apa).
  • Mekanisme autentikasi: SCRAM, x.509, Kerberos, LDAP, OIDC.
  • Cara kerja SCRAM-SHA-1 dan SCRAM-SHA-256, dibuktikan di server latihan.
  • authenticationDatabase dan penulisan kredensial pada connection string.
  • Menyalakan security.authorization dengan bantuan localhost exception.

Dua Pertanyaan: Siapa dan Boleh Apa #

Authentication dan authorization sering diucap bersamaan padahal menjawab dua pertanyaan berbeda. Authentication memverifikasi identitas klien; authorization menentukan hak akses identitas itu. Keduanya bekerja berurutan — authorization tanpa authentication tidak punya subjek untuk dibatasi.

AspekAuthenticationAuthorization
PertanyaanSiapa yang terhubung?Identitas ini boleh apa?
MekanismeSCRAM, x.509, Kerberos, LDAPRole dan privilege
Dibahas diChapter iniChapter Role-Based Access Control

Mekanisme yang Tersedia #

MekanismeEdisiCocok untuk
SCRAM-SHA-1 / SCRAM-SHA-256Community (default)User dengan username dan password
MONGODB-X509CommunityKlien berbasis sertifikat, mis. koneksi antar-server
GSSAPI (Kerberos)EnterpriseOrganisasi yang sudah memakai Kerberos/Active Directory
PLAIN (LDAP)EnterpriseAutentikasi lewat LDAP — deprecated sejak MongoDB 8.0
MONGODB-OIDCEnterpriseSingle sign-on lewat identity provider

SCRAM adalah mekanisme default dan yang akan kita pakai sepanjang course ini. X.509 menggantikan password dengan sertifikat digital dan mensyaratkan TLS aktif — kita bahas lagi di Chapter TLS dan Enkripsi. Kerberos dan LDAP hanya tersedia di MongoDB Enterprise; LDAP bahkan sudah ditandai deprecated sejak MongoDB 8.0 dan akan dihapus di rilis mendatang, jadi jangan dijadikan pilihan baru.

SCRAM di Balik Layar #

SCRAM (Salted Challenge Response Authentication Mechanism) adalah protokol challenge-response standar IETF. Server tidak pernah menyimpan password asli — yang tersimpan adalah hasil hash berkala dengan salt per user. Saat klien mengautentikasi, password juga tidak dikirim sebagai password: klien menghitung bukti matematis dari password, salt, dan challenge yang diberikan server, lalu mengirim bukti itu. Mendengar lalu lintas jaringan tidak serta-merta membocorkan password.

MongoDB modern membuat kredensial user baru untuk kedua varian SCRAM sekaligus. Kita buktikan pada server latihan — pembuatan user secara penuh dibahas di Chapter Database Users, di sini kita fokus pada mekanismenya:

js
use latihan_uji
// hapus sisa percobaan sebelumnya bila ada
try { db.dropUser("budi_pembaca") } catch (e) { print("user belum ada — buat baru") }
db.createUser({
  user: "budi_pembaca",
  pwd: "sandiUji123",
  roles: [{ role: "read", db: "latihan_uji" }]
})
db.runCommand({ hello: 1, saslSupportedMechs: "latihan_uji.budi_pembaca" }).saslSupportedMechs

Output yang Dihasilkan:

text
switched to db latihan_uji

user belum ada — buat baru

{
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1792261603, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
      keyId: Long('0')
    }
  },
  operationTime: Timestamp({ t: 1792261603, i: 1 })
}
[ 'SCRAM-SHA-256', 'SCRAM-SHA-1' ]

Baris terakhir memanfaatkan parameter saslSupportedMechs pada perintah hello: server menjawab mekanisme SCRAM apa saja yang cocok untuk user tersebut. Hasilnya memuat SCRAM-SHA-256 dan SCRAM-SHA-1 — user baru memang mendapat kredensial ganda demi kompatibilitas dengan klien lawas.

Sekarang kita uji proses authentication-nya. Password yang salah ditolak dengan galat AuthenticationFailed:

js
db.auth("budi_pembaca", "sandiSalah")

Output yang Dihasilkan:

text
Uncaught 
MongoServerError[AuthenticationFailed]: Authentication failed.

Password yang benar diterima, dan identitas kini melekat pada koneksi:

js
db.auth("budi_pembaca", "sandiUji123")
db.runCommand({ connectionStatus: 1 }).authInfo

Output yang Dihasilkan:

text
{ ok: 1 }
{
  authenticatedUsers: [ { user: 'budi_pembaca', db: 'latihan_uji' } ],
  authenticatedUserRoles: [ { role: 'read', db: 'latihan_uji' } ]
}

Perhatikan perubahan pentingnya: authenticatedUsers yang pada chapter sebelumnya kosong kini memuat budi_pembaca dari database latihan_uji, lengkap dengan role read. Server latihan kita menjalankan authorization dalam keadaan mati sehingga pembatasan hak belum ditegakkan — tetapi proses verifikasi kredensial itu sendiri nyata dan bisa kita amati.

Terakhir, kita lepaskan identitas dan bersihkan user percobaan:

js
db.logout()
db.dropUser("budi_pembaca")
db.getUsers()

Output yang Dihasilkan:

text
{
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1792261603, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
      keyId: Long('0')
    }
  },
  operationTime: Timestamp({ t: 1792261603, i: 1 })
}
{
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1792261603, i: 2 }),
    signature: {
      hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
      keyId: Long('0')
    }
  },
  operationTime: Timestamp({ t: 1792261603, i: 2 })
}
{
  users: [],
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1792261603, i: 2 }),
    signature: {
      hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
      keyId: Long('0')
    }
  },
  operationTime: Timestamp({ t: 1792261603, i: 2 })
}

db.logout() mengembalikan koneksi ke keadaan anonim, db.dropUser() menghapus user, dan db.getUsers() memastikan daftar user di latihan_uji kembali kosong.

AuthenticationDatabase #

Setiap user MongoDB hidup di satu database — itulah authentication database-nya. User yang kita buat di atas hidup di latihan_uji; user administratif lazimnya hidup di database admin. Nama lengkap sebuah user adalah kombinasi user@database, jadi budi@aplikasi dan budi@admin adalah dua user berbeda.

Akibat praktisnya: klien harus memberi tahu server di mana user itu dicari. Dengan mongosh, gunakan parameter --authenticationDatabase; dengan connection string, gunakan authSource:

bash
mongosh -u budi_pembaca -p --authenticationDatabase latihan_uji
text
mongodb://budi_pembaca:[email protected]:27017/latihan_uji?authSource=latihan_uji

Menyalakan Authentication di Server #

Server produksi menegakkan authentication lewat konfigurasi security.authorization. Tambahkan blok berikut ke file konfigurasi mongod (misalnya /etc/mongod.conf), lalu restart layanan:

text
net:
  bindIp: 127.0.0.1
  port: 27017

security:
  authorization: enabled

Ada satu jebakan urutan: begitu authorization: enabled aktif, semua koneksi tanpa identitas ditolak — termasuk koneksi pertama yang hendak membuat user admin. MongoDB menyediakan localhost exception sebagai pintu darurat: selama belum ada satu pun user di sistem, server masih menerima perintah pembuatan user pertama dari koneksi localhost. User pertama itu harus dibuat di database admin dan harus punya hak membuat user lain, misalnya lewat role userAdminAnyDatabase:

js
// mdtest: skip
// jalankan dari koneksi localhost SETELAH security.authorization: enabled
use admin
db.createUser({
  user: "adminUtama",
  pwd: passwordPrompt(),
  roles: [{ role: "userAdminAnyDatabase", db: "admin" }]
})

Perintah di atas meminta password secara interaktif lewat passwordPrompt(). Setelah user pertama dibuat, localhost exception tertutup permanen dan semua operasi selanjutnya menuntut authentication. Server latihan bersama kita sengaja tidak menjalankan konfigurasi ini — menghidupkan auth pada server yang dipakai banyak latihan akan mengunci semua sesi — sehingga blok di atas tidak bisa kita eksekusi di sini; bentuk perintahnya kita kutip apa adanya.

Rangkuman #

  • Authentication menjawab “siapa Anda”; authorization menjawab “boleh apa” — dua lapisan berurutan dari defense in depth.
  • SCRAM (SHA-1 dan SHA-256) adalah mekanisme default Community; x.509 memakai sertifikat; Kerberos, LDAP, dan OIDC adalah fitur Enterprise.
  • SCRAM tidak mengirim password mentah — klien mengirim bukti perhitungan, server menyimpan hash berkala.
  • User hidup di satu authentication database; klien menunjuknya lewat --authenticationDatabase atau authSource.
  • Menyalakan security.authorization: enabled diikuti pembuatan user pertama via localhost exception di database admin.