Skip to content

9.3 Auth

Tujuan bab

Setelah bab ini kamu bisa:

  • Mengamankan server Mastra dengan SimpleAuth untuk pengembangan dan API key
  • Mengatur rute mana yang dilindungi dan mana yang publik
  • Menggabungkan beberapa penyedia autentikasi dengan CompositeAuth
  • Memilih penyedia identitas yang sesuai untuk produksi
  • Menghubungkan hasil autentikasi ke RequestContext dan ke lapisan data

Prasyarat

Dua pertanyaan yang berbeda

Autentikasi sering dibicarakan sebagai satu hal, padahal ada dua pertanyaan terpisah:

  • Autentikasisiapa kamu? Memverifikasi identitas.
  • Otorisasikamu boleh apa? Menentukan hak akses.

Mastra menangani keduanya, tapi lewat mekanisme yang berbeda. Autentikasi lewat penyedia auth; otorisasi lewat authorizeUser, konfigurasi rute, dan — untuk kebutuhan yang lebih halus — Fine-Grained Authorization.

SimpleAuth — titik awal

SimpleAuth menyediakan autentikasi berbasis token dengan pemetaan token ke pengguna. Ia sudah termasuk dalam @mastra/core dan tidak butuh paket tambahan.

ts
// src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { SimpleAuth } from '@mastra/core/server'

type User = {
  id: string
  name: string
  role: 'admin' | 'user'
}

export const mastra = new Mastra({
  server: {
    auth: new SimpleAuth<User>({
      tokens: {
        'sk-admin-token-123': {
          id: 'user-1',
          name: 'Admin User',
          role: 'admin',
        },
        'sk-user-token-456': {
          id: 'user-2',
          name: 'Regular User',
          role: 'user',
        },
      },
    }),
  },
})

Perhatikan bahwa SimpleAuth bertipe generikSimpleAuth<User> membuat bentuk objek pengguna kamu yang tentukan, dan tipe itu mengalir ke seluruh tempat pengguna dibaca.

Kapan SimpleAuth memadai

Dokumentasi menyebutkan kasus pemakaiannya:

  • Pengembangan dan pengujian lokal
  • Autentikasi API key sederhana
  • Prototipe sebelum mengintegrasikan penyedia identitas penuh
  • Layanan internal dengan token statis

Yang tidak termasuk: pengguna akhir manusia dalam jumlah banyak. Token statis di dalam kode tidak bisa dicabut per pengguna, tidak kedaluwarsa, dan tidak punya alur pendaftaran.

Jangan pernah menulis token asli di dalam kode

Contoh di atas menulis token secara langsung supaya mudah dibaca. Di proyek sungguhan, token dibaca dari variabel lingkungan.

Token yang ter-commit ke git harus dianggap bocor selamanya — riwayat git tidak lupa, dan menghapusnya dari commit terakhir tidak menghapusnya dari riwayat.

Opsi yang tersedia

OpsiWajibKegunaan
tokensYaPeta token ke objek pengguna
headersTidakHeader tambahan yang diperiksa
nameTidakNama penyedia untuk keperluan log
authorizeUserTidakFungsi otorisasi kustom
protectedTidakPath yang memerlukan autentikasi
publicTidakPath yang melewati autentikasi

Secara bawaan, SimpleAuth memeriksa header Authorization (dengan atau tanpa awalan Bearer) dan X-Playground-Access.

protected dan public

Kedua opsi ini yang menentukan permukaan yang terbuka, dan layak dipikirkan baik-baik.

Pola yang lebih aman adalah melindungi secara default dan membuka secara eksplisit — bukan sebaliknya. Rute yang lupa kamu daftarkan sebagai protected akan terbuka; rute yang lupa kamu daftarkan sebagai public hanya akan menolak permintaan. Kegagalan jenis kedua jauh lebih murah.

Kandidat yang wajar untuk public: endpoint pemeriksaan kesehatan, dan mungkin agent card A2A kalau kamu memang ingin ditemukan.

authorizeUser — dari "siapa" ke "boleh apa"

SimpleAuth memverifikasi token dan menghasilkan objek pengguna. Yang menentukan apakah pengguna itu boleh melakukan sesuatu adalah authorizeUser:

ts
auth: new SimpleAuth<User>({
  tokens: { /* ... */ },
  authorizeUser: (user, request) => {
    return user.role === 'admin'
  },
}),

Fungsi ini menerima pengguna dan permintaan, dan mengembalikan boolean. Karena ia melihat keduanya, kamu bisa membuat aturan yang bergantung path atau method — misalnya hanya admin yang boleh menyentuh endpoint tertentu.

CompositeAuth — beberapa penyedia sekaligus

CompositeAuth menggabungkan beberapa penyedia menjadi satu penangan. Ia mencoba tiap penyedia secara berurutan sampai satu berhasil.

ts
// src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { CompositeAuth, SimpleAuth } from '@mastra/core/server'
import { MastraAuthClerk } from '@mastra/auth-clerk'

type ApiKeyUser = {
  id: string
  name: string
  type: 'api-key'
}

const apiKeyAuth = new SimpleAuth<ApiKeyUser>({
  tokens: {
    'sk-integration-key-123': {
      id: 'integration-1',
      name: 'CI/CD Pipeline',
      type: 'api-key',
    },
  },
})

export const mastra = new Mastra({
  server: {
    auth: new CompositeAuth([apiKeyAuth, new MastraAuthClerk()]),
  },
})

Kegunaan yang disebut dokumentasi:

  • Mendukung API key dan token OAuth sekaligus — manusia lewat OAuth, integrasi lewat API key
  • Bermigrasi antar penyedia tanpa memutus klien yang sudah ada
  • Mengizinkan beberapa penyedia identitas
  • Peluncuran bertahap metode autentikasi baru

Kasus kedua patut diperhatikan: mengganti penyedia identitas biasanya berarti memutus semua klien sekaligus. Dengan CompositeAuth, penyedia lama dan baru bisa hidup berdampingan selama masa transisi.

Karena urutannya berpengaruh, taruh penyedia yang paling sering dipakai di depan — setiap penyedia yang dicoba dan gagal menambah latensi.

Penyedia untuk produksi

Untuk pengguna akhir manusia, kamu butuh penyedia identitas sungguhan:

PenyediaPaket
JWT dengan secret bersama@mastra/auth (MastraJwtAuth)
Clerk@mastra/auth-clerk
Supabase@mastra/auth-supabase
Firebase@mastra/auth-firebase
Auth0@mastra/auth-auth0
WorkOS@mastra/auth-workos

MastraJwtAuth adalah jalan tengah yang berguna: ia memverifikasi permintaan berdasarkan secret bersama lewat variabel MASTRA_JWT_SECRET, tanpa memerlukan layanan identitas eksternal. Cocok saat aplikasi utamamu sudah menangani login dan kamu hanya perlu server Mastra memercayai token yang sudah ia terbitkan.

Untuk kebutuhan izin tingkat sumber daya — "pengguna ini boleh membaca thread ini, tapi bukan thread itu" — tersedia Fine-Grained Authorization (FGA), yang memetakan rute ke tindakan dan membatasi cakupan sumber daya tersimpan.

Menyambungkan ke seluruh sistem

Autentikasi tidak berhenti di gerbang. Identitas yang sudah diverifikasi harus mengalir ke tempat keputusan diambil:

Tiga sambungan di bawah adalah yang membuat autentikasi benar-benar berarti:

Ke memory. Nilai resource di 3.1 harus berasal dari sini. Tanpa itu, ingatan pengguna bisa tertukar — dan dengan working memory berlingkup resource di 3.2, itu berarti profil pribadi bocor.

Ke tool. Seperti dibahas di 9.2, identitas dibaca dari requestContext, bukan dari inputSchema yang bisa dikarang model.

Ke trace. Lewat requestContextKeys di 8.1, sehingga trace bisa ditelusuri per pengguna.

Studio juga perlu diamankan

Satu hal yang mudah terlupa: Studio mengekspos agent-mu juga. Kalau kamu men-deploy Studio ke lingkungan yang bisa diakses orang lain, ia butuh perlindungan sendiri.

Mastra menyediakan alur login untuk Studio, penerusan token, kontrol akses berbasis peran, peran bawaan, dan render UI yang sadar izin. Ini dibahas lagi di 9.4.

Kesalahan umum

Gejala: Tagihan model melonjak tanpa penjelasan, dari lalu lintas yang tidak dikenali. Penyebab: Server Mastra menghadap internet tanpa autentikasi. Endpoint terbuka rutin ditemukan pemindai otomatis, dan agent adalah target yang menarik karena tiap panggilan berbiaya. Perbaikan: Pasang auth sebelum apa pun online — bahkan SimpleAuth dengan satu token jauh lebih baik daripada tidak sama sekali. Periksa juga public tidak lebih longgar dari yang kamu maksud.

Gejala: Pengguna melihat data pengguna lain, padahal autentikasi jelas bekerja dan token diverifikasi dengan benar. Penyebab: Autentikasi berhenti di gerbang. Identitas terverifikasi tidak diteruskan ke resource pada memory, atau tool masih menerima userId lewat inputSchema. Perbaikan: Alirkan identitas dari hasil autentikasi ke RequestContext, lalu pakai nilai itu untuk resource memory dan untuk identitas di dalam tool. Autentikasi tanpa penerusan hanya mengamankan pintu depan.

Coba sendiri

Tantangan: Amankan aplikasi dari 9.2 dari gerbang sampai ke lapisan data, lalu serang sendiri untuk membuktikannya.

Ketentuan:

  1. Pasang SimpleAuth dengan tiga pengguna berbeda peran, token dibaca dari variabel lingkungan — bukan ditulis di kode
  2. Atur public hanya untuk endpoint pemeriksaan kesehatan; sisanya terlindungi
  3. Tambahkan authorizeUser yang membatasi satu endpoint tertentu hanya untuk peran admin
  4. Alirkan identitas terverifikasi ke RequestContext, lalu pakai sebagai resource pada memory
  5. Uji empat skenario: tanpa token, token tidak valid, token valid peran biasa ke endpoint admin, dan token valid peran admin
  6. Uji isolasi data: masuk sebagai pengguna A, simpan sesuatu ke memory, lalu masuk sebagai pengguna B dan coba mengaksesnya — termasuk dengan membujuk agent lewat kalimat
  7. Ganti SimpleAuth menjadi CompositeAuth yang menggabungkan dua SimpleAuth berbeda, dan pastikan keduanya tetap bekerja
  8. Periksa apakah trace-mu bisa difilter per pengguna

Checklist penerimaan:

  • [ ] Tidak ada token yang tertulis di dalam kode
  • [ ] Endpoint kesehatan bisa diakses tanpa token; sisanya menolak
  • [ ] Keempat skenario di langkah 5 memberi hasil yang tepat, termasuk perbedaan antara 401 dan 403
  • [ ] Langkah 6 gagal mengakses data pengguna lain — baik lewat API maupun lewat bujukan kalimat ke agent
  • [ ] CompositeAuth menerima token dari kedua penyedia
  • [ ] Trace bisa difilter berdasarkan pengguna
  • [ ] Kamu bisa menjelaskan perbedaan peran auth dan authorizeUser

Petunjuk: Langkah 6 adalah yang paling penting dan paling sering terlewatkan. Banyak aplikasi lulus uji autentikasi di gerbang tapi gagal di lapisan data — karena resource memory diisi nilai tetap, atau diambil dari parameter yang dikirim klien. Cobalah dua jalur serangan: mengirim resource lain lewat API, dan meminta agent secara halus lewat percakapan. Kalau identitas benar-benar mengalir dari RequestContext, keduanya buntu.

Ikhtisar

  • Autentikasi menjawab "siapa kamu", otorisasi menjawab "boleh apa". Yang pertama lewat penyedia auth, yang kedua lewat authorizeUser, konfigurasi rute, dan FGA.
  • SimpleAuth ada di @mastra/core/server, bertipe generik, dan cocok untuk pengembangan, API key, prototipe, dan layanan internal — bukan untuk pengguna akhir manusia.
  • Jangan tulis token di kode. Baca dari variabel lingkungan.
  • Lindungi secara default, buka secara eksplisit — kegagalan public yang terlupa jauh lebih murah daripada protected yang terlupa.
  • CompositeAuth mencoba beberapa penyedia berurutan — untuk mendukung API key dan OAuth bersamaan, atau bermigrasi tanpa memutus klien.
  • Untuk produksi: MastraJwtAuth dengan secret bersama, atau penyedia identitas seperti Clerk, Supabase, Firebase, Auth0, WorkOS. FGA untuk izin tingkat sumber daya.
  • Autentikasi harus mengalir: ke resource memory, ke identitas di dalam tool, dan ke metadata trace. Berhenti di gerbang berarti hanya mengamankan pintu depan.
  • Studio juga mengekspos agent-mu dan butuh perlindungan sendiri.

Lanjut ke mana

Bab terakhir: membawa semua ini keluar dari laptopmu — 9.4 Deployment & Checklist Rilis.

Materi belajar mandiri. Bukan dokumentasi resmi Mastra.