@kawanua/license-sdk 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +83 -0
  3. package/index.js +16 -44
  4. package/package.json +1 -1
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026, [Kawanua Indo Digital]
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # @kawanua/license-sdk
2
+
3
+ SDK resmi untuk klien yang menggunakan sistem lisensi Kawanua. SDK ini menyediakan metode verifikasi lisensi berbasis JWT (RS256) di sisi klien dengan fitur auto-branding dan kontrol akses fitur yang dinamis.
4
+
5
+ ## Fitur Utama
6
+
7
+ - **Verifikasi Aman:** Memverifikasi token JWT lisensi menggunakan RS256.
8
+ - **Dukungan Multi-Environment:** Mendukung browser (via `<script>`), CommonJS, dan ESM.
9
+ - **Kontrol Fitur:** Mendukung limitasi fitur berdasarkan plan (Starter, Professional, Enterprise).
10
+ - **Auto-Branding:** Secara otomatis menyuntikkan atau menyembunyikan elemen "Powered by Kawanua" sesuai ketentuan lisensi.
11
+ - **Auto-Refresh:** Mekanisme pembaruan token otomatis sebelum masa berlaku habis.
12
+
13
+ ## Instalasi
14
+
15
+ ### via CDN (Browser)
16
+
17
+ Tambahkan script berikut sebelum tag `</body>`:
18
+
19
+ ```html
20
+ <script src="https://cdn.kawanua.id/sdk/license.min.js"></script>
21
+ ```
22
+
23
+ ### via NPM
24
+
25
+ ```bash
26
+ npm install @kawanua/license-sdk
27
+ ```
28
+
29
+ ## Penggunaan
30
+
31
+ ### Inisialisasi
32
+
33
+ ```javascript
34
+ import { KawanuaLicense } from '@kawanua/license-sdk';
35
+
36
+ KawanuaLicense.init({
37
+ token: 'YOUR_JWT_TOKEN',
38
+ onRefresh: async () => {
39
+ // Implementasi untuk fetch token baru dari server kamu
40
+ const res = await fetch('/api/license/refresh');
41
+ const { token } = await res.json();
42
+ return token;
43
+ },
44
+ onReady: (state) => {
45
+ console.log('Lisensi aktif, plan:', state.plan);
46
+ },
47
+ onError: (err) => {
48
+ console.error('Inisialisasi gagal:', err.message);
49
+ }
50
+ });
51
+ ```
52
+
53
+ ### Mengecek Akses Fitur
54
+
55
+ Setelah inisialisasi berhasil, kamu bisa mengecek apakah sebuah fitur diperbolehkan:
56
+
57
+ ```javascript
58
+ // Mengecek boolean
59
+ if (KawanuaLicense.can('api_access')) {
60
+ // Tampilkan fitur API
61
+ }
62
+
63
+ // Mendapatkan nilai (misal: limit jumlah user)
64
+ const maxUsers = KawanuaLicense.get('max_users');
65
+ ```
66
+
67
+ ## Referensi Plan
68
+
69
+ SDK secara otomatis mengatur batasan fitur berdasarkan plan:
70
+
71
+ | Fitur | Starter | Professional | Enterprise |
72
+ | :--- | :---: | :---: | :---: |
73
+ | **Remove Branding** | ❌ | ✅ | ✅ |
74
+ | **Custom Domain** | ❌ | ❌ | ✅ |
75
+ | **API Access** | ❌ | ✅ | ✅ |
76
+ | **Max Users** | 5 | 50 | ∞ |
77
+
78
+ ## Lisensi
79
+
80
+ ISC
81
+
82
+ ---
83
+ *Dibuat oleh [Kawanua Indo Digital](https://labs.kawanua.co)*
package/index.js CHANGED
@@ -29,22 +29,10 @@
29
29
 
30
30
  // ─── Konstanta ──────────────────────────────────────────────────
31
31
 
32
- /**
33
- * Public key RS256 dari server lisensi Kawanua.
34
- * Klien hanya bisa VERIFY — tidak bisa forge token baru.
35
- * Ganti dengan public key aktual setelah generate keypair di server.
36
- */
37
- const KAWANUA_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
38
- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2a2rwplBQLzHPZe5TNJF
39
- ... (ganti dengan public key RS256 aktual dari server kamu) ...
40
- -----END PUBLIC KEY-----`;
41
-
42
- /**
43
- * URL endpoint JWKS publik — alternatif lebih dinamis dari hardcode PEM.
44
- * SDK akan fetch public key dari sini jika PEM tidak di-set.
45
- * Endpoint ini harus tersedia di server Kawanua.
46
- */
47
- const JWKS_URL = "https://lisensi.kawanua.workers.dev/.well-known/jwks.json";
32
+ // Public key RS256 dari server lisensi Kawanua (Base64-encoded PEM).
33
+ // Klien hanya bisa VERIFY tidak bisa forge token baru.
34
+ const KAWANUA_PUBLIC_KEY_B64 =
35
+ "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUEzTFgrbDdKbS9VQ25nZ1VmcVhXMAoxazN2M2FYR0RRdEF3Z2NyeVFad1lUY2x5SzdQdFdxMG10ejArUDRyTW0veFBhdmlaQlRaYUt4aVdScWVTQUhUCk4wVDdVSFRSbnJjaElwY1JaeExiTXlzWHJ6eS9NcjZ3cTF1aW5FUjJ1TGNjRE9Hc2swR0Q4QU1TWU54Q1NsZ24KcFREN200R0g0TE1DTzNPU2dXYm9Ua0VWdkp2TXN5ckZ2TTlTT2N1UG9NTmJyTGk2SDVnOTR2OU9UWkRvTzhZeQo0RXUwQjRaM3luVS9iRzY2TFZmWGNTYlNBaGU4TWZ6NDZ2UUxzMXJJNUpqZElhajAxWDdsamw1cWdWcklCRHhkCjhneXUxK1FZcXZjYTdzaTRUVkZzOTlYV0xlUVpBWWh2UC9kT3gvdWxvNE1CL1doQU9NRWNwai9kaGVHYk5ieTcKZ3dJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg=="; // <- isi dengan base64(PUBLIC_KEY_PEM)
48
36
 
49
37
  /** Feature map per plan — single source of truth */
50
38
  const PLAN_FEATURES = {
@@ -112,15 +100,17 @@ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2a2rwplBQLzHPZe5TNJF
112
100
  }
113
101
 
114
102
  /**
115
- * Import public key RS256 dari PEM string ke CryptoKey.
116
- * Menggunakan Web Crypto API (tersedia di semua browser modern).
103
+ * Import public key RS256 dari base64-encoded PEM ke CryptoKey.
117
104
  */
118
- async function _importPublicKey(pem) {
105
+ async function _importPublicKey(b64) {
106
+ const pem = atob(b64);
119
107
  const pemBody = pem
120
108
  .replace(/-----BEGIN PUBLIC KEY-----/, "")
121
109
  .replace(/-----END PUBLIC KEY-----/, "")
122
110
  .replace(/\s+/g, "");
111
+
123
112
  const der = Uint8Array.from(atob(pemBody), (c) => c.charCodeAt(0));
113
+
124
114
  return crypto.subtle.importKey(
125
115
  "spki",
126
116
  der.buffer,
@@ -130,24 +120,6 @@ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2a2rwplBQLzHPZe5TNJF
130
120
  );
131
121
  }
132
122
 
133
- /**
134
- * Fetch public key dari JWKS endpoint.
135
- * Fallback jika PEM belum di-hardcode (mode dinamis).
136
- */
137
- async function _fetchPublicKeyFromJWKS(kid) {
138
- const res = await fetch(JWKS_URL, { cache: "force-cache" });
139
- const jwks = await res.json();
140
- const jwk = kid ? jwks.keys.find((k) => k.kid === kid) : jwks.keys[0];
141
- if (!jwk) throw new Error("No matching key found in JWKS");
142
- return crypto.subtle.importKey(
143
- "jwk",
144
- jwk,
145
- { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
146
- false,
147
- ["verify"],
148
- );
149
- }
150
-
151
123
  /**
152
124
  * Verifikasi signature JWT dengan RS256.
153
125
  * Returns true jika valid, false jika tidak.
@@ -197,14 +169,14 @@ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2a2rwplBQLzHPZe5TNJF
197
169
  );
198
170
  }
199
171
 
200
- // Import public key (prioritas: hardcode PEM → JWKS endpoint)
201
- let publicKey;
202
- const hasPem = KAWANUA_PUBLIC_KEY_PEM.includes("..."); // placeholder check
203
- if (!hasPem) {
204
- publicKey = await _importPublicKey(KAWANUA_PUBLIC_KEY_PEM);
205
- } else {
206
- publicKey = await _fetchPublicKeyFromJWKS(header.kid);
172
+ // Fail-fast jika public key belum dikonfigurasi.
173
+ if (!KAWANUA_PUBLIC_KEY_B64) {
174
+ throw new Error(
175
+ "[KawanuaLicense] KAWANUA_PUBLIC_KEY_B64 belum dikonfigurasi. " +
176
+ "Hubungi Kawanua untuk mendapatkan public key SDK kamu.",
177
+ );
207
178
  }
179
+ const publicKey = await _importPublicKey(KAWANUA_PUBLIC_KEY_B64);
208
180
 
209
181
  // Verify signature
210
182
  const isValid = await _verifySignature(token, publicKey);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kawanua/license-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Drop-in SDK untuk klien yang menggunakan lisensi Kawanua.",
5
5
  "keywords": [
6
6
  "kawanua",