@kominfobwi/sso-sk
v0.1.0
Published
SSO Smartkampung Banyuwangi Library
Readme
@kominfobwi/sso-sk
SSO Helper Library untuk Smartkampung Banyuwangi - Menyediakan integrasi dengan SSO server Banyuwangikab (https://sso.banyuwangikab.go.id).
Fitur
- Enkripsi AES-256-CBC - Keamanan data dengan encryption standar industri
- Retry Logic - Automatic retry untuk transient failures
- TypeScript Native - Full TypeScript support dengan type definitions
- Zero Dependencies - Hanya menggunakan native Node.js modules
- Single Callback URL - Login & verifikasi dalam 1 URL endpoint saja
Instalasi
npm install @kominfobwi/sso-skPersyaratan
- Node.js >= 18.0.0
Quick Start
1. Inisialisasi SSO
import { SsoSk } from '@kominfobwi/sso-sk';
SsoSk.init({
alias: 'aplikasi-anda',
secretKeyBody: 'kunci-enkripsi-body-32-char!!',
secretKeyUrl: 'kunci-enkripsi-url-32-char!!!!',
baseUrl: 'https://sso.banyuwangikab.go.id',
options: {
timeoutMs: 10000, // timeout request (default: 10000)
maxRetries: 3, // max percobaan retry (default: 3)
retryDelayMs: 500, // delay antar retry (default: 500)
},
});2. Login Flow
Pilih salah satu method login:
// Login standar - redirect ke halaman login SSO
const loginUrl = SsoSk.login();
// Quick login - untuk login cepat tanpa halaman SSO
const quickLoginUrl = SsoSk.quickLogin();
// Redirect user
res.redirect(loginUrl);3. Single Callback URL
SSO ini menggunakan 1 URL callback saja untuk menangani login dan verifikasi tiket:
https://aplikasi-anda.com/auth/callback/:paramSetelah user login di SSO, mereka akan di-redirect ke URL callback ini dengan parameter param yang berisi data terenkripsi. Gunakan quickCheckTicket() untuk verifikasi:
import express from 'express';
import { SsoSk, SsoError } from '@kominfobwi/sso-sk';
const app = express();
app.get('/auth/callback/:param', async (req, res) => {
const { param } = req.params;
try {
const user = await SsoSk.quickCheckTicket(param);
// User berhasil diverifikasi
res.json({
success: true,
user: {
nik: user.nik,
nama: user.nama,
email: user.email,
},
});
} catch (error) {
if (error instanceof SsoError) {
console.error('SSO Error:', error.code, error.message);
res.status(400).json({
success: false,
message: error.message,
code: error.code,
});
} else {
res.status(500).json({ success: false, message: 'Internal server error' });
}
}
});4. Handle SSO Callback (Legacy)
Handler untuk Express.js dengan validasi database:
import express from 'express';
import { SsoSk } from '@kominfobwi/sso-sk';
const app = express();
app.post('/sso/callback', express.json(), async (req, res) => {
try {
const result = await SsoSk.receiveTiket(
JSON.stringify(req.body),
{
// Opsional: validasi user sebelum proses
checkUser: async (user) => {
const dbUser = await db.users.findByNik(user.nik);
return dbUser ? { ok: true } : { ok: false, message: 'User tidak terdaftar' };
},
// Wajib: proses data user yang diterima
onReceive: async (data) => {
await db.users.upsert({
nik: data.nik,
nama: data.nama,
email: data.email,
tiket: data.tiket,
token: data.token,
});
},
}
);
if (result.kode === 2007) {
res.json({ success: true, message: result.message });
} else {
res.status(400).json({ success: false, message: result.message });
}
} catch (error) {
console.error('SSO callback error:', error);
res.status(500).json({ success: false, message: 'Internal server error' });
}
});5. PWA Verification
Untuk aplikasi PWA dengan credential validation:
const result = await SsoSk.verifyTiketPwa({
tiket: 'tiket-dari-sso',
idSesi: 'session-id',
as: 'aplikasi-pwa',
authorization: 'Bearer token',
});API Reference
SsoSk.init(config)
Inisialisasi singleton SSO client.
Parameters:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| alias | string | ✅ | Identifier aplikasi |
| secretKeyBody | string | ✅ | Secret key untuk enkripsi body (32 chars) |
| secretKeyUrl | string | ✅ | Secret key untuk enkripsi URL (32 chars) |
| baseUrl | string | ❌ | Base URL SSO server (default: https://sso.banyuwangikab.go.id) |
| options.timeoutMs | number | ❌ | Request timeout dalam ms (default: 10000) |
| options.maxRetries | number | ❌ | Max retry attempts (default: 3) |
| options.retryDelayMs | number | ❌ | Delay antar retry dalam ms (default: 500) |
SsoSk.login(): string
Generate SSO login URL untuk redirect user.
Returns: Login URL string
SsoSk.quickLogin(): string
Generate SSO quick login URL untuk login cepat tanpa halaman SSO.
Returns: Quick login URL string
SsoSk.quickCheckTicket(param): Promise<SsoUser | null>
Quick check tiket SSO langsung ke server tanpa perlu cek database. Cocok untuk verifikasi tiket dari URL SSO callback.
Parameters:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| param | string | ✅ | Parameter encrypted dari URL (format: iv.data.tokenJWT) |
Returns: Promise<SsoUser | null> - Data user jika verifikasi berhasil, null jika gagal
SsoSk.receiveTiket(rawBody, hooks): Promise<ReceiveTiketResult>
⚠️ Deprecated - Gunakan
quickCheckTicket()sebagai gantinya.
Proses callback dari SSO server setelah user login.
Parameters:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| rawBody | string | ✅ | Raw JSON body dari SSO callback |
| hooks.checkUser | function | ❌ | Hook untuk validasi user sebelum proses |
| hooks.onReceive | function | ✅ | Hook untuk proses data user yang diterima |
Returns: Promise<ReceiveTiketResult>
SsoSk.checkTiket(param, hooks): Promise<CheckTiketResult>
⚠️ Deprecated - Gunakan
quickCheckTicket()sebagai gantinya.
Verifikasi ticket dari URL parameter dengan cek database.
Parameters:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| param | string | ✅ | Parameter encrypted dari URL |
| hooks.findUserByTiket | function | ✅ | Hook untuk cari user berdasarkan tiket |
Returns: Promise<CheckTiketResult>
SsoSk.verifyTiketPwa(params): Promise<SsoResponse>
Verifikasi tiket untuk aplikasi PWA.
Parameters:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| params.tiket | string | ✅ | Tiket dari SSO |
| params.idSesi | string | ✅ | Session ID |
| params.as | string | ✅ | Application alias |
| params.authorization | string | ✅ | Authorization header |
Returns: Promise<SsoResponse>
Types
SsoUser
interface SsoUser {
nik: string;
nama: string;
email: string;
[key: string]: unknown;
}ReceiveTiketHooks
interface ReceiveTiketHooks {
checkUser?: (data: SsoUser) => Promise<{ ok: true } | { ok: false; message?: string }>;
onReceive: (data: SsoUser & { tiket: string; token: string }) => Promise<void>;
}CheckTiketHooks
interface CheckTiketHooks {
findUserByTiket: (tiket: string) => Promise<UserRecord | null>;
}ReceiveTiketResult
type ReceiveTiketResult =
| { kode: 2007; status: 'sukses'; message: string }
| { kode: number; status: 'error'; message: string };CheckTiketResult
type CheckTiketResult =
| { kode: 2009; status: 'sukses'; message: null; data: SsoUser }
| { kode: number; status: 'error'; message: string };Error Handling
Package ini melempar SsoError untuk error yang terjadi:
import { SsoSk, SsoError } from '@kominfobwi/sso-sk';
try {
await SsoSk.verifyTiketPwa({ /* ... */ });
} catch (error) {
if (error instanceof SsoError) {
console.error('Error code:', error.code);
console.error('Retryable:', error.retryable);
console.error('Meta:', error.meta);
}
}Error Codes
| Code | Retryable | Description |
|------|-----------|-------------|
| SSO_SERVER_ERROR | ✅ | Server SSO mengembalikan error 5xx |
| SSO_CLIENT_ERROR | ❌ | Request invalid (4xx) |
| INVALID_CREDENTIALS | ❌ | Kredensial tidak valid |
| TIMEOUT | ✅ | Request timeout |
| INVALID_RESPONSE | ❌ | Response bukan JSON valid |
| ECONNRESET | ✅ | Connection reset |
| ECONNREFUSED | ✅ | Connection refused |
| NETWORK_ERROR | ❌ | Network error lainnya |
| INVALID_PARAM_FORMAT | ❌ | Format parameter tidak valid (quickCheckTicket) |
| INVALID_TOKEN | ❌ | Token JWT invalid atau kosong (quickCheckTicket) |
| DECRYPT_FAILED | ❌ | Gagal decrypt parameter (quickCheckTicket) |
| TIKET_NOT_FOUND | ❌ | Tiket tidak ditemukan dalam payload (quickCheckTicket) |
| VERIFICATION_FAILED | ❌ | Verifikasi tiket gagal (quickCheckTicket) |
Kode Response
| Kode | Status | Description |
|------|--------|-------------|
| 2007 | sukses | Tiket berhasil diterima |
| 2009 | sukses | Tiket berhasil diverifikasi |
| 5000 | error | Payload tidak valid |
| 5001 | error | Data user tidak lengkap |
| 5020 | error | Format parameter tidak valid |
| 5021 | error | Gagal decrypt parameter |
| 5027 | error | User tidak terdaftar |
| 5028 | error | Gagal memproses credential |
| 5052 | error | Gagal terhubung ke server SSO |
| 5053 | error | Respons SSO tidak valid |
Development
# Install dependencies
npm install
# Build TypeScript
npm run build
# Run tests
npm test
# Run tests with coverage
npm run test:coverageLicense
ISC License
