---
title: Autentikasi
description: Alur OAuth2 JWT Bearer yang digunakan oleh semua kontrak IDCloud. Pelajari cara mendapatkan kredensial, membangun JWT assertion, dan menukarnya dengan access token.
canonical: https://developer.unico.io/id/developers/start/authentication
locale: id
generated_by: markdown-export
---

- [/id/](/id/)
- [Mulai](/id/developers/start/)
- Autentikasi

**Di halaman ini# Autentikasi

Semua API IDCloud (kontrak Web & SDK dan API) menggunakan **OAuth2 dengan JWT Bearer Grant Type** ([RFC 7523](https://datatracker.ietf.org/doc/html/rfc7523)). Anda membuat JWT assertion berumur pendek di back-end, menukarnya dengan Bearer token, dan menggunakan token tersebut di setiap panggilan berikutnya.
Jangan pernah lakukan ini di sisi klienJWT assertion harus dibuat di **back-end saja**. Jangan pernah mengekspos private key Anda di kode front-end, aplikasi mobile, repositori, atau log.
### Mendapatkan kredensial​

Sebelum dapat membuat token, Anda memerlukan **service account** yang disediakan oleh Unico. Hubungi dukungan Unico dan berikan:

Nama service account (maks. 12 karakter)
Nama, email, dan nomor telepon penanggung jawab (hanya nomor Brasil, AS, atau Meksiko)

Anda akan menerima:

Nama akun unik
Tenant ID
Base JWT payload
File private key (format `.pem`)

Satu akun per environmentPertahankan service account yang terpisah untuk **UAT** dan **Production**.
### Membangun JWT assertion​

Assertion adalah JWT dalam format JWS kompak: `{Base64url(Header)}.{Base64url(Payload)}.{Base64url(Signature)}`.
Header
```
{  "alg": "RS256",  "typ": "JWT"}
```

Payload
ClaimNilaiCatatan`iss``<account_name>@<tenant_id>.iam.acesso.io`Diberikan bersama kredensial Anda`aud``https://identityhomolog.acesso.io` (UAT) atau `https://identity.acesso.io` (Production)Harus sesuai dengan host token endpoint`scope``*`Memberikan semua izin`iat`Unix timestamp (detik)Waktu JWT diterbitkan`exp``iat` + maks. 3600Tidak boleh melebihi 1 jam dari `iat`
```
{  "iss": "my-account@abc123.iam.acesso.io",  "aud": "https://identity.acesso.io",  "scope": "*",  "iat": 1738086000,  "exp": 1738089600}
```

Signature
Tandatangani header + payload menggunakan **RS256** (RSA + SHA-256) dengan private key `.pem` yang diberikan oleh Unico.
Jangan tambahkan klaim ekstraField apa pun yang tidak tercantum di atas (misalnya `sub`, `jti`, `nbf`) akan menyebabkan error `1.2.22`. Gunakan hanya klaim yang ditampilkan.
### Meminta token​

Token endpoint sama untuk kedua kontrak:
EnvironmentEndpoint**Production**`POST https://identity.acesso.io/oauth2/token`**UAT**`POST https://identityhomolog.acesso.io/oauth2/token`
Request
ParameterNilai`Content-Type``application/x-www-form-urlencoded``grant_type``urn:ietf:params:oauth:grant-type:jwt-bearer``assertion`JWT yang telah ditandatangani
cURLNode.jsPython```
curl -X POST https://identity.acesso.io/oauth2/token \  -H "Content-Type: application/x-www-form-urlencoded" \  -d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" \  -d "assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
```

```
import jwt from 'jsonwebtoken';import fs from 'fs';import qs from 'querystring';const privateKey = fs.readFileSync('./private-key.pem');const now = Math.floor(Date.now() / 1000);const assertion = jwt.sign(  {    iss: 'my-account@abc123.iam.acesso.io',    aud: 'https://identity.acesso.io',    scope: '*',    iat: now,    exp: now + 3600,  },  privateKey,  { algorithm: 'RS256' });const res = await fetch('https://identity.acesso.io/oauth2/token', {  method: 'POST',  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },  body: qs.stringify({    grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',    assertion,  }),});const { access_token, expires_in } = await res.json();
```

```
import timeimport jwt  # PyJWTimport requestswith open("private-key.pem", "rb") as f:    private_key = f.read()now = int(time.time())assertion = jwt.encode(    {        "iss": "my-account@abc123.iam.acesso.io",        "aud": "https://identity.acesso.io",        "scope": "*",        "iat": now,        "exp": now + 3600,    },    private_key,    algorithm="RS256",)response = requests.post(    "https://identity.acesso.io/oauth2/token",    data={        "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",        "assertion": assertion,    },)token_data = response.json()access_token = token_data["access_token"]
```

Response
```
{  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",  "token_type": "Bearer",  "expires_in": 3600}
```

FieldTipeDeskripsi`access_token`stringJWT access token. Gunakan di `Authorization: Bearer <token>` pada semua panggilan API.`expires_in`integerWaktu kedaluwarsa dalam detik. Contoh: `3600`.`token_type`stringSelalu `Bearer`.
### Menggunakan token​

Tambahkan token ke header `Authorization` di setiap permintaan API. Header-nya identik untuk kedua kontrak — yang berbeda adalah **host dan path** dari API yang Anda panggil:
KontrakProduction hostUAT host**Web & SDK**`https://api.idcloud.unico.app``https://api.idcloud.uat.unico.app`**API**`https://api.id.unico.app``https://api.id.uat.unico.app`
**Web & SDK** — `Authorization` adalah satu-satunya header autentikasi yang diperlukan:
```
curl -X POST https://api.idcloud.unico.app/client/v1/process \  -H "Authorization: Bearer $ACCESS_TOKEN" \  -H "Content-Type: application/json" \  -d '{ ... }'
```

**API** — `Authorization` digunakan bersama header `APIKEY`:
```
curl -X POST https://api.id.unico.app/processes/v1 \  -H "Authorization: Bearer $ACCESS_TOKEN" \  -H "APIKEY: $API_KEY" \  -H "Content-Type: application/json" \  -d '{ ... }'
```

### Pembaruan token​

Token kedaluwarsa setelah 3600 detik. Terapkan pembaruan proaktif di back-end Anda:

Pantau `expires_in` dari respons token dan simpan timestamp kedaluwarsa.
Minta token baru **ketika tersisa 10 menit atau kurang** sebelum kedaluwarsa.
Jangan pernah menunggu `401` di production untuk memicu pembaruan.

### Referensi API​

Spesifikasi OpenAPI lengkap untuk token endpoint tersedia di [`authentication.yaml`](/id/assets/files/authentication-1d221f9a7230435e9c390ba98dac7321.yaml).
MetodePathDeskripsi`POST``/oauth2/token`Tukarkan JWT assertion yang ditandatangani dengan Bearer access token
### Kode error​

KodeDeskripsiTindakan`1.0.1`ID yang diberikan dalam pembentukan `iss` salahVerifikasi field `iss` sesuai dengan tenant ID yang diberikan saat private key dibuat`1.0.14`Aplikasi tidak aktifTanyakan ke project manager apakah aplikasi yang digunakan sudah aktif`1.1.1`Parameter `scope` tidak diberikanTambahkan `"scope": "*"` ke JWT payload Anda`1.2.4`JWT assertion tidak validJWT assertion tidak lagi valid. Dua kemungkinan penyebab: (a) waktu saat ini sudah melewati `exp` (JWT benar-benar kedaluwarsa — buat assertion baru untuk setiap permintaan token); atau (b) `exp` melebihi `iat + 3600` (durasi terlalu panjang — batasi `exp` pada `iat + 3600`).`1.2.5`Validasi JWT gagalJWT tidak dapat divalidasi. Verifikasi parameter dan pastikan ditandatangani dengan RS256 dan private key yang benar`1.2.6`Private key tidak lagi validPrivate key yang digunakan untuk menandatangani JWT tidak lagi diterima. Minta kredensial baru untuk akun tersebut`1.2.7`JWT sudah digunakanJWT tidak lagi diterima karena sudah digunakan. Buat assertion baru untuk setiap permintaan token`1.2.11`Akun tidak aktifAkun yang digunakan tidak aktif`1.2.14`Akun tidak memiliki izin yang diperlukanAkun yang digunakan tidak memiliki izin yang diperlukan`1.2.18`Akun dikunci sementaraAkun telah dikunci sementara karena melebihi jumlah percobaan autentikasi yang tidak valid`1.2.19`Peniruan identitas pengguna tidak diizinkanJWT berisi klaim `sub` yang mengarah ke akun yang tidak diizinkan untuk peniruan identitas. Hapus klaim `sub` dari payload.`1.2.20`Dekoding JWT gagalGagal mendekode JWT. Verifikasi format token dan pastikan ditandatangani dengan RS256.`1.2.21`Private key salah / Autentikasi gagalTanda tangan JWT tidak dapat diverifikasi terhadap kunci mana pun yang dikenal untuk akun ini. Pastikan Anda menggunakan file private key `.pem` yang benar untuk service account dan environment ini.`1.2.22`Field yang tidak diizinkan dalam payloadJWT berisi field payload ekstra yang tidak diizinkan. Hapus klaim apa pun yang tidak tercantum dalam panduan ini (misalnya `sub`, `jti`, `nbf`). Catatan: jika Anda menyertakan klaim `sub` dan menerima error `1.2.19`, error tersebut yang berlaku.`1.3.1`Pembatasan akses IPIP Anda tidak ada dalam daftar yang diizinkan untuk akun ini`1.3.2`Pembatasan akses berbasis waktuPermintaan berada di luar jendela waktu yang diizinkan untuk akun ini
### Langkah berikutnya​

[Environments](/id/developers/start/environments) — host sandbox vs production
Web & SDK — Create Process — panggilan pertama setelah autentikasi
[API — Create Process](/id/developers/api-reference/post-processes) — panggilan pertama setelah autentikasi
[SSO / SAML](/id/developers/start/sso-saml) — autentikasikan pengguna Anda ke portal produk Unico menggunakan identity provider Anda sendiri, sebagai pengganti alur server-to-server di atas
Terakhir diperbarui pada 8 Okt 2026**