BazaarLinkBazaarLink
Masuk
DokumentasiReferensi APIReferensi SDKPenggunaan AgentikSkill AI
Daftar isi

OAuth PKCE

OAuth PKCE

OAuth 2.0 PKCE (Proof Key for Code Exchange) memungkinkan aplikasi klien publik (browser SPA, aplikasi mobile) membuat panggilan API atas nama pengguna individu tanpa menyimpan rahasia server jangka panjang di sisi klien.

Kapan Menggunakan OAuth PKCE

  • Membangun browser SPA atau aplikasi mobile yang membutuhkan tagihan per pengguna
  • SaaS multi-tenant — setiap pengguna akhir membayar penggunaan API mereka sendiri
  • Anda tidak dapat menyimpan rahasia bersama di sisi klien (klien publik)
  • Anda membutuhkan kunci terpisah yang dapat dicabut untuk setiap pengguna (berlaku sampai pengguna mencabutnya) alih-alih satu kunci API bersama

Yang akan dilihat pengguna Anda

Jelaskan langkah-langkah ini di layar masuk Anda sendiri:

  1. Di aplikasi Anda, mereka memilih "Masuk dengan BazaarLink" (atau apa pun nama tombol Anda).
  2. Browser mereka membuka halaman otorisasi BazaarLink. Jika belum masuk, mereka masuk terlebih dahulu lalu otomatis kembali ke halaman ini.
  3. Halaman menampilkan alamat aplikasi Anda dan apa yang terjadi jika mereka mengizinkan: kunci API baru dibuat untuk aplikasi, penggunaan ditagihkan ke saldo BazaarLink mereka, dan mereka dapat mencabut kunci kapan saja. Mereka dapat menamai kunci dan menetapkan batas pengeluaran bulanan (keduanya opsional).
  4. Mereka mengklik Izinkan lalu dikembalikan ke aplikasi Anda. Jika mereka mengklik Tolak, tidak ada kunci yang dibuat, aplikasi Anda tidak diberi tahu, dan mereka melihat halaman "Akses ditolak".
  5. Untuk mencabut akses nanti, mereka membuka halaman Kunci API (https://bazaarlink.ai/keys) dan menonaktifkan atau menghapus kunci yang dinamai sesuai aplikasi Anda.

Cara kerjanya

Langkah 1 — Mulai Autentikasi — Hasilkan code_verifier acak (string acak panjang) dan hash SHA-256-nya sebagai code_challenge, lalu arahkan pengguna ke halaman autentikasi BazaarLink.

https://bazaarlink.ai/auth?callback_url=https://yourapp.com/callback&code_challenge=CODE_CHALLENGE&code_challenge_method=S256

Parameter URL otorisasi

  • callback_url (wajib) — tujuan pengguna kembali setelah mengizinkan. Aturan di bawah.
  • code_challenge (wajib) — SHA-256 dari code_verifier Anda yang dikodekan base64url (43 karakter, tanpa padding).
  • code_challenge_method (wajib) — harus S256.
  • state (opsional) — nilai CSRF buram milik Anda sendiri, 1 sampai 256 karakter ASCII yang dapat dicetak. BazaarLink mengembalikannya apa adanya sebagai &state=… tepat setelah code. State yang salah format membuat halaman otorisasi menampilkan "Permintaan otorisasi tidak valid".
  • key_label (opsional) — hingga 100 karakter. Mengisi nama kunci di halaman persetujuan secara otomatis (pengguna tetap dapat mengubahnya). Label yang terlalu panjang atau kosong diabaikan.
  • Headless tools (CLI / desktop, no callback_url) — omit callback_url. After the user allows, the page shows a one-time code (valid 5 minutes, single use) for them to enter into your tool; exchange it exactly like a redirected code. The page cannot show which app is asking, so tell users to enter the code only in a tool they started themselves.

Tidak didukung

  • workspace_id dan required_workspace_id — tidak didukung. Kunci selalu milik akun pengguna sendiri.
  • code_challenge_method=plain — tidak didukung (hanya S256).

Aturan callback_url

  • Harus https://. http:// hanya diterima untuk localhost, 127.0.0.1, dan [::1] (port apa pun); halaman persetujuan kemudian menampilkan peringatan pengembangan lokal.
  • Tanpa fragmen (#), tanpa nama pengguna atau kata sandi di URL, maksimal 2048 karakter.
  • Halaman persetujuan menampilkan nama host callback Anda agar pengguna tahu aplikasi mana yang meminta.
  • Setelah pengguna mengizinkan, browser diarahkan ke callback_url Anda dengan code=… ditambahkan (dan state=… jika Anda mengirimnya; query string yang sudah ada dipertahankan). Code berlaku 10 menit dan hanya dapat dipakai sekali.

Langkah 2 — Tukar Kode dengan Kunci API — Setelah pengguna mengotorisasi permintaan, BazaarLink mengarahkan ke callback_url Anda dengan code sekali pakai. Code berlaku selama 10 menit dan hanya dapat dipakai sekali; code_verifier yang salah akan menghanguskannya. POST code, code_verifier, dan code_challenge_method (ketiganya wajib) untuk menerima kunci API pengguna.

curl https://bazaarlink.ai/api/v1/auth/keys \
-H "Content-Type: application/json" \
-d '{
  "code": "<CODE_FROM_CALLBACK_URL>",
  "code_verifier": "<CODE_VERIFIER>",
  "code_challenge_method": "S256"
}'

# Response
# { "key": "sk-bl-...", "user_id": "..." }

Langkah 3 — Gunakan Kunci Cakupan Pengguna — Kunci yang dikembalikan adalah kunci API BazaarLink biasa milik pengguna yang memberi otorisasi — penggunaan ditagihkan ke saldo pengguna tersebut, bukan saldo Anda.

curl https://bazaarlink.ai/api/v1/chat/completions \
-H "Authorization: Bearer sk-bl-..." \
-H "Content-Type: application/json" \
-d '{"model": "google/gemini-3.5-flash", "messages": [{"role": "user", "content": "Hello"}]}'

Contoh JavaScript (browser)

// 1) Create a verifier + S256 challenge, then send the user to BazaarLink
const b64url = (buf) => btoa(String.fromCharCode(...new Uint8Array(buf)))
.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
const verifier = b64url(crypto.getRandomValues(new Uint8Array(32)));
const challenge = b64url(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier)));
sessionStorage.setItem("bl_verifier", verifier);
// "state" is optional: BazaarLink hands it back unchanged next to the code.
const state = b64url(crypto.getRandomValues(new Uint8Array(16)));
sessionStorage.setItem("bl_state", state);
location.href =
"https://bazaarlink.ai/auth?callback_url=" + encodeURIComponent(location.origin + "/callback") +
"&code_challenge=" + challenge + "&code_challenge_method=S256&state=" + state;

// 2) On /callback: check your own state, then exchange the one-time code for a user key
const params = new URLSearchParams(location.search);
if (params.get("state") !== sessionStorage.getItem("bl_state")) throw new Error("state mismatch");
const res = await fetch("https://bazaarlink.ai/api/v1/auth/keys", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
  code: params.get("code"),
  code_verifier: sessionStorage.getItem("bl_verifier"),
  code_challenge_method: "S256",
}),
});
if (!res.ok) throw new Error((await res.json()).error?.message ?? "exchange failed"); // 403 invalid_code: ask the user to authorize again
const { key } = await res.json(); // use as: Authorization: Bearer <key>
Keamanan: Hanya S256
Atur code_challenge_method ke S256 (hash SHA-256). Hanya S256 yang didukung: permintaan dengan plain atau tanpa code_challenge_method ditolak dengan HTTP 400.
Catatan
Jika pengguna menolak, BazaarLink tidak mengalihkan kembali ke callback_url Anda dan tidak memberi tahu aplikasi Anda. Hanya halaman "Akses ditolak" yang ditampilkan, sehingga /auth tidak pernah menjadi open redirect. Tangani status belum diotorisasi di dalam aplikasi Anda (misalnya dengan timeout atau tombol coba lagi).

Halaman /auth dan POST /api/v1/auth/keys dilayani dari https://bazaarlink.ai (bukan api.bazaarlink.ai). Kunci yang Anda terima berfungsi di kedua base URL: https://bazaarlink.ai/api/v1 dan https://api.bazaarlink.ai/v1.

Jika pengguna menetapkan batas pengeluaran saat memberi otorisasi, batas itu bersifat bulanan dan direset mengikuti periode bulanan akun.

Kesalahan

Kesalahan menggunakan format ala OpenAI {"error":{"message","type","code"}}. POST /api/v1/auth/keys dapat mengembalikan:

  • 400 invalid_code_challenge_method — code_challenge_method tidak ada, plain, atau selain S256.
  • 400 — body JSON tidak valid, atau code / code_verifier tidak ada.
  • 403 invalid_code — code tidak dikenal, kedaluwarsa atau sudah dipakai, code_verifier salah, atau akun tidak lagi diizinkan. Semua kasus ini sengaja mengembalikan pesan yang sama agar pemanggil tidak dapat membedakannya. code_verifier yang salah juga menghanguskan code: minta pengguna mengotorisasi ulang.
  • 429 rate_limited — lebih dari 30 percobaan pertukaran dalam 10 menit dari satu IP (lihat header Retry-After).
  • 429 key_total_cap — akun sudah memiliki maksimum 200 kunci API.
  • 405 — hanya POST yang diterima.

Buat kode dari server Anda (Kunci Manajemen)

Pemilik Kunci Manajemen (Management Key) pribadi dapat membuat kode otorisasi langsung dengan POST /api/v1/auth/keys/code tanpa mengarahkan pengguna ke halaman browser (kompatibel dengan OpenRouter). Kode terikat pada pemilik Kunci Manajemen, sehingga kunci yang ditukar adalah kunci standar di akun pemilik tersebut, dengan batas, periode, masa berlaku, dan nama yang dipilih di sini. Gunakan bila alat Anda sendiri sudah memegang Kunci Manajemen dan ingin memberikan kunci terbatas kepada sebuah aplikasi. Penukaran (POST /api/v1/auth/keys) sama seperti di atas.

  • callback_url (wajib) dan code_challenge + code_challenge_method=S256 (wajib) — aturan sama dengan URL otorisasi.
  • key_label (opsional) — hingga 100 karakter; nama kunci. Default: "App: <host callback Anda>".
  • limit (opsional) — batas pengeluaran dalam USD, 0 atau lebih; 0 atau tidak diisi berarti tanpa batas.
  • usage_limit_type (opsional) — daily, weekly, atau monthly: seberapa sering batas direset. Hanya dipakai bersama limit; default monthly.
  • expires_at (opsional) — kapan kunci kedaluwarsa: waktu ISO 8601 UTC dengan detik di masa depan, misalnya 2026-12-31T23:59:59Z. Nilai dengan presisi menit ditolak. Jika tidak diisi, kunci tetap berlaku sampai dicabut.
  • workspace_id — tidak didukung (400). spawn_agent dan spawn_cloud diterima tetapi diabaikan.
curl https://bazaarlink.ai/api/v1/auth/keys/code \
-H "Authorization: Bearer sk-bl-YOUR_MGMT_KEY" \
-H "Content-Type: application/json" \
-d '{
  "callback_url": "https://yourapp.com/callback",
  "code_challenge": "<CODE_CHALLENGE>",
  "code_challenge_method": "S256",
  "key_label": "My app",
  "limit": 10,
  "usage_limit_type": "monthly",
  "expires_at": "2026-12-31T23:59:59Z"
}'

# Response
# { "data": { "id": "<ONE_TIME_CODE>", "app_id": 123456789, "created_at": "2026-10-22T12:00:00.000Z" } }
# Then POST { "code": "<ONE_TIME_CODE>", "code_verifier": "<CODE_VERIFIER>", "code_challenge_method": "S256" } to /api/v1/auth/keys

Respons: { "data": { "id", "app_id", "created_at" } }. id adalah kode sekali pakai untuk ditukar (berlaku 10 menit, satu kali). BazaarLink tidak memiliki registri aplikasi, sehingga app_id adalah bilangan bulat tetap yang diturunkan dari alamat callback Anda: alamat yang sama selalu mendapat app_id yang sama.

  • 401 unauthorized — tidak ada kunci Bearer, atau kunci tidak dikenal.
  • 403 management_key_required — kunci bukan Kunci Manajemen pribadi (kunci standar dan Kunci Manajemen organisasi ditolak).
  • 403 account_not_allowed — pemilik kunci ditangguhkan atau dihapus.
  • 400 — invalid_callback_url, invalid_code_challenge_method, invalid_code_challenge, invalid_expires_at, workspace_not_supported, atau body yang tidak valid.
  • 429 rate_limited — lebih dari 30 kode per jam untuk satu pemilik atau 120 per jam dari satu IP (lihat Retry-After).

Kunci yang Anda terima

  • Kunci API BazaarLink standar (sk-bl-…), jenis yang sama dengan kunci yang dibuat di halaman Kunci API. Berlaku sampai pengguna mencabutnya.
  • Penggunaan ditagihkan ke saldo BazaarLink pengguna. Jika pengguna menetapkan batas pengeluaran di halaman persetujuan, batas itu bersifat bulanan.
  • Berfungsi di kedua base URL: https://bazaarlink.ai/api/v1 dan https://api.bazaarlink.ai/v1.
  • Dihitung dalam batas 200 kunci per akun dan muncul di daftar Kunci API pengguna, tempat pengguna dapat menonaktifkan atau menghapusnya kapan saja.
  • Akun yang ditangguhkan atau dihapus tidak dapat mengotorisasi aplikasi, dan code yang diterbitkan sebelum penangguhan ditolak saat pertukaran (403 invalid_code).

Yang Anda dapatkan

  • Alur Authorization Code + PKCE untuk aplikasi klien publik
  • Tagihan per pengguna: setiap pengguna membayar penggunaannya sendiri dari saldonya sendiri
  • Satu kunci terpisah untuk setiap pengguna, tercantum di halaman Kunci API pengguna tempat ia dapat mencabutnya
Support
Hi! How can we help you?
Send a message and we'll get back to you soon.
OAuth PKCE | BazaarLink