@hanzo/iam 0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hanzo AI Inc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # @hanzo/iam
2
+
3
+ TypeScript SDK for [Hanzo IAM](https://iam.hanzo.ai) — identity & access management built on [Casdoor](https://casdoor.org).
4
+
5
+ ## Features
6
+
7
+ - **JWT Validation** — OIDC discovery + JWKS-based signature verification via [jose](https://github.com/panva/jose)
8
+ - **OAuth2 PKCE** — Browser-side login flows (redirect, popup, silent signin)
9
+ - **API Client** — Users, organizations, OIDC discovery, token exchange
10
+ - **Billing** — Subscriptions, plans, pricing, payments, orders
11
+ - **TypeScript** — Full type safety with exported interfaces
12
+ - **Zero Config** — Auto-discovers endpoints via `.well-known/openid-configuration`
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ npm install @hanzo/iam
18
+ # or
19
+ pnpm add @hanzo/iam
20
+ ```
21
+
22
+ ## Server-Side Usage
23
+
24
+ ### Validate a JWT
25
+
26
+ ```typescript
27
+ import { validateToken } from "@hanzo/iam";
28
+
29
+ const result = await validateToken(accessToken, {
30
+ serverUrl: "https://iam.hanzo.ai",
31
+ clientId: "my-app",
32
+ });
33
+
34
+ if (result.ok) {
35
+ console.log(result.userId, result.email, result.owner);
36
+ } else {
37
+ console.error(result.reason);
38
+ }
39
+ ```
40
+
41
+ ### API Client
42
+
43
+ ```typescript
44
+ import { IamClient } from "@hanzo/iam";
45
+
46
+ const client = new IamClient({
47
+ serverUrl: "https://iam.hanzo.ai",
48
+ clientId: "my-app",
49
+ clientSecret: process.env.IAM_CLIENT_SECRET,
50
+ });
51
+
52
+ // OAuth2 authorization URL
53
+ const authUrl = await client.getAuthorizationUrl({
54
+ redirectUri: "https://myapp.com/callback",
55
+ state: "random-state",
56
+ });
57
+
58
+ // Exchange code for tokens
59
+ const tokens = await client.exchangeCode({
60
+ code: "auth-code",
61
+ redirectUri: "https://myapp.com/callback",
62
+ });
63
+
64
+ // Get user info
65
+ const user = await client.getUserInfo(tokens.access_token);
66
+ ```
67
+
68
+ ### Billing
69
+
70
+ ```typescript
71
+ import { IamBillingClient } from "@hanzo/iam";
72
+
73
+ const billing = new IamBillingClient({
74
+ serverUrl: "https://iam.hanzo.ai",
75
+ clientId: "my-app",
76
+ clientSecret: process.env.IAM_CLIENT_SECRET,
77
+ orgName: "my-org",
78
+ });
79
+
80
+ const { active, subscription, plan } = await billing.isSubscriptionActive("my-org");
81
+ ```
82
+
83
+ ## Browser Usage (SPA)
84
+
85
+ ```typescript
86
+ import { BrowserIamSdk } from "@hanzo/iam";
87
+
88
+ const iam = new BrowserIamSdk({
89
+ serverUrl: "https://iam.hanzo.ai",
90
+ clientId: "my-spa",
91
+ redirectUri: "https://myapp.com/auth/callback",
92
+ });
93
+
94
+ // Start login
95
+ await iam.signinRedirect();
96
+
97
+ // On callback page
98
+ const tokens = await iam.handleCallback();
99
+
100
+ // Get a valid token (auto-refreshes if expired)
101
+ const token = await iam.getValidAccessToken();
102
+
103
+ // Fetch user info
104
+ const user = await iam.getUserInfo();
105
+
106
+ // Logout
107
+ iam.clearTokens();
108
+ ```
109
+
110
+ ## Sub-path Imports
111
+
112
+ ```typescript
113
+ // Server-side JWT validation only (lighter import)
114
+ import { validateToken } from "@hanzo/iam/auth";
115
+
116
+ // Browser PKCE flows only
117
+ import { BrowserIamSdk } from "@hanzo/iam/browser";
118
+
119
+ // Billing only
120
+ import { IamBillingClient } from "@hanzo/iam/billing";
121
+
122
+ // Types only
123
+ import type { IamConfig, IamUser } from "@hanzo/iam/types";
124
+ ```
125
+
126
+ ## Configuration
127
+
128
+ | Option | Required | Description |
129
+ |--------|----------|-------------|
130
+ | `serverUrl` | Yes | IAM server URL (e.g. `https://iam.hanzo.ai`) |
131
+ | `clientId` | Yes | OAuth2 client ID |
132
+ | `clientSecret` | No | Client secret (server-side confidential clients) |
133
+ | `orgName` | No | Organization name for scoped queries |
134
+ | `appName` | No | Application name |
135
+
136
+ ## Documentation
137
+
138
+ Full docs: [docs.hanzo.ai/services/iam/sdk](https://docs.hanzo.ai/services/iam/sdk)
139
+
140
+ ## License
141
+
142
+ MIT — [Hanzo AI](https://hanzo.ai)
package/dist/auth.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * JWT validation using jose library + OIDC JWKS discovery.
3
+ *
4
+ * Validates access/ID tokens issued by Hanzo IAM (Casdoor).
5
+ */
6
+ import type { IamConfig, IamAuthResult } from "./types.js";
7
+ /** Clear cached JWKS key sets (useful for testing or key rotation). */
8
+ export declare function clearJwksCache(): void;
9
+ /**
10
+ * Validate a JWT access token against IAM's JWKS.
11
+ *
12
+ * Uses OIDC discovery to find the JWKS URI, then verifies the token
13
+ * signature, issuer, audience, and expiry using the `jose` library.
14
+ */
15
+ export declare function validateToken(token: string, config: IamConfig): Promise<IamAuthResult>;
16
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAgB,MAAM,YAAY,CAAC;AAiBzE,uEAAuE;AACvE,wBAAgB,cAAc,IAAI,IAAI,CAErC;AA4CD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC,aAAa,CAAC,CAsExB"}
package/dist/auth.js ADDED
@@ -0,0 +1,130 @@
1
+ /**
2
+ * JWT validation using jose library + OIDC JWKS discovery.
3
+ *
4
+ * Validates access/ID tokens issued by Hanzo IAM (Casdoor).
5
+ */
6
+ import { createRemoteJWKSet, jwtVerify } from "jose";
7
+ // ---------------------------------------------------------------------------
8
+ // JWKS key set cache (per issuer)
9
+ // ---------------------------------------------------------------------------
10
+ const jwksSets = new Map();
11
+ function getJwksKeySet(jwksUri) {
12
+ let keySet = jwksSets.get(jwksUri);
13
+ if (!keySet) {
14
+ keySet = createRemoteJWKSet(new URL(jwksUri));
15
+ jwksSets.set(jwksUri, keySet);
16
+ }
17
+ return keySet;
18
+ }
19
+ /** Clear cached JWKS key sets (useful for testing or key rotation). */
20
+ export function clearJwksCache() {
21
+ jwksSets.clear();
22
+ }
23
+ const discoveryCache = new Map();
24
+ const DISCOVERY_TTL_MS = 5 * 60 * 1000;
25
+ async function resolveJwksUri(serverUrl) {
26
+ const baseUrl = serverUrl.replace(/\/+$/, "");
27
+ const cached = discoveryCache.get(baseUrl);
28
+ if (cached && Date.now() - cached.fetchedAt < DISCOVERY_TTL_MS) {
29
+ return { jwksUri: cached.jwksUri, issuer: cached.issuer };
30
+ }
31
+ const controller = new AbortController();
32
+ const timer = setTimeout(() => controller.abort(), 8_000);
33
+ try {
34
+ const res = await fetch(`${baseUrl}/.well-known/openid-configuration`, {
35
+ signal: controller.signal,
36
+ headers: { Accept: "application/json" },
37
+ });
38
+ if (!res.ok) {
39
+ throw new Error(`OIDC discovery failed: ${res.status}`);
40
+ }
41
+ const body = (await res.json());
42
+ const jwksUri = body.jwks_uri;
43
+ const issuer = body.issuer ?? baseUrl;
44
+ if (!jwksUri) {
45
+ throw new Error("OIDC discovery response missing jwks_uri");
46
+ }
47
+ discoveryCache.set(baseUrl, { jwksUri, issuer, fetchedAt: Date.now() });
48
+ return { jwksUri, issuer };
49
+ }
50
+ finally {
51
+ clearTimeout(timer);
52
+ }
53
+ }
54
+ // ---------------------------------------------------------------------------
55
+ // Token validation
56
+ // ---------------------------------------------------------------------------
57
+ /**
58
+ * Validate a JWT access token against IAM's JWKS.
59
+ *
60
+ * Uses OIDC discovery to find the JWKS URI, then verifies the token
61
+ * signature, issuer, audience, and expiry using the `jose` library.
62
+ */
63
+ export async function validateToken(token, config) {
64
+ if (!token || typeof token !== "string") {
65
+ return { ok: false, reason: "iam_token_missing" };
66
+ }
67
+ let jwksUri;
68
+ let issuer;
69
+ try {
70
+ const discovery = await resolveJwksUri(config.serverUrl);
71
+ jwksUri = discovery.jwksUri;
72
+ issuer = discovery.issuer;
73
+ }
74
+ catch {
75
+ return { ok: false, reason: "iam_discovery_failed" };
76
+ }
77
+ const keySet = getJwksKeySet(jwksUri);
78
+ let payload;
79
+ try {
80
+ const result = await jwtVerify(token, keySet, {
81
+ issuer,
82
+ audience: config.clientId,
83
+ clockTolerance: 30, // 30s clock skew
84
+ });
85
+ payload = result.payload;
86
+ }
87
+ catch (err) {
88
+ const message = err instanceof Error ? err.message : String(err);
89
+ if (message.includes("expired")) {
90
+ return { ok: false, reason: "iam_token_expired" };
91
+ }
92
+ if (message.includes("audience")) {
93
+ // Retry without audience check - some Casdoor configs don't set aud
94
+ try {
95
+ const result = await jwtVerify(token, keySet, {
96
+ issuer,
97
+ clockTolerance: 30,
98
+ });
99
+ payload = result.payload;
100
+ }
101
+ catch {
102
+ return { ok: false, reason: "iam_signature_invalid" };
103
+ }
104
+ }
105
+ else {
106
+ return { ok: false, reason: "iam_signature_invalid" };
107
+ }
108
+ }
109
+ const claims = payload;
110
+ if (!claims.sub) {
111
+ return { ok: false, reason: "iam_subject_missing" };
112
+ }
113
+ // Casdoor sub format is "org/username" - extract owner
114
+ const parts = claims.sub.split("/");
115
+ const owner = parts.length > 1 ? parts[0] : config.orgName ?? "unknown";
116
+ return {
117
+ ok: true,
118
+ userId: claims.sub,
119
+ email: typeof claims.email === "string" ? claims.email : undefined,
120
+ name: typeof claims.name === "string"
121
+ ? claims.name
122
+ : typeof claims.preferred_username === "string"
123
+ ? claims.preferred_username
124
+ : undefined,
125
+ avatar: typeof claims.picture === "string" ? claims.picture : undefined,
126
+ owner,
127
+ claims,
128
+ };
129
+ }
130
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Billing client for Hanzo IAM (Casdoor) — subscriptions, plans, pricing, usage.
3
+ */
4
+ import type { IamConfig, IamSubscription, IamPlan, IamPricing, IamPayment, IamOrder } from "./types.js";
5
+ export declare class IamBillingClient {
6
+ private readonly baseUrl;
7
+ private readonly clientId;
8
+ private readonly clientSecret;
9
+ private readonly orgName;
10
+ constructor(config: IamConfig);
11
+ private request;
12
+ /** Get all subscriptions for an owner. */
13
+ getSubscriptions(token?: string): Promise<IamSubscription[]>;
14
+ /** Get a specific subscription by ID ("owner/name" format). */
15
+ getSubscription(id: string, token?: string): Promise<IamSubscription | null>;
16
+ /** Get the subscription for a specific user. */
17
+ getUserSubscription(userId: string, token?: string): Promise<IamSubscription | null>;
18
+ /** Get all plans for an owner. */
19
+ getPlans(token?: string): Promise<IamPlan[]>;
20
+ /** Get a specific plan by ID. */
21
+ getPlan(id: string, token?: string): Promise<IamPlan | null>;
22
+ /** Get all pricing configurations for an owner. */
23
+ getPricings(token?: string): Promise<IamPricing[]>;
24
+ /** Get a specific pricing by ID. */
25
+ getPricing(id: string, token?: string): Promise<IamPricing | null>;
26
+ /** Get all payments for an owner. */
27
+ getPayments(token?: string): Promise<IamPayment[]>;
28
+ /** Get a specific payment by ID. */
29
+ getPayment(id: string, token?: string): Promise<IamPayment | null>;
30
+ /** Get all orders for an owner. */
31
+ getOrders(token?: string): Promise<IamOrder[]>;
32
+ /** Get a specific order by ID. */
33
+ getOrder(id: string, token?: string): Promise<IamOrder | null>;
34
+ /** Check if an org has an active subscription. */
35
+ isSubscriptionActive(orgName: string, token?: string): Promise<{
36
+ active: boolean;
37
+ subscription: IamSubscription | null;
38
+ plan: IamPlan | null;
39
+ }>;
40
+ }
41
+ //# sourceMappingURL=billing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing.d.ts","sourceRoot":"","sources":["../src/billing.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,OAAO,EACP,UAAU,EACV,UAAU,EACV,QAAQ,EAET,MAAM,YAAY,CAAC;AAIpB,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEjC,MAAM,EAAE,SAAS;YAWf,OAAO;IA4DrB,0CAA0C;IACpC,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IASlE,+DAA+D;IACzD,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAQlF,gDAAgD;IAC1C,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAS1F,kCAAkC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IASlD,iCAAiC;IAC3B,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAYlE,mDAAmD;IAC7C,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IASxD,oCAAoC;IAC9B,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAYxE,qCAAqC;IAC/B,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IASxD,oCAAoC;IAC9B,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAYxE,mCAAmC;IAC7B,SAAS,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IASpD,kCAAkC;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAYpE,kDAAkD;IAC5C,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QACnE,MAAM,EAAE,OAAO,CAAC;QAChB,YAAY,EAAE,eAAe,GAAG,IAAI,CAAC;QACrC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;KACtB,CAAC;CAkBH"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Billing client for Hanzo IAM (Casdoor) — subscriptions, plans, pricing, usage.
3
+ */
4
+ const DEFAULT_TIMEOUT_MS = 10_000;
5
+ export class IamBillingClient {
6
+ baseUrl;
7
+ clientId;
8
+ clientSecret;
9
+ orgName;
10
+ constructor(config) {
11
+ this.baseUrl = config.serverUrl.replace(/\/+$/, "");
12
+ this.clientId = config.clientId;
13
+ this.clientSecret = config.clientSecret;
14
+ this.orgName = config.orgName;
15
+ }
16
+ // -----------------------------------------------------------------------
17
+ // Internal HTTP helper
18
+ // -----------------------------------------------------------------------
19
+ async request(path, opts) {
20
+ const url = new URL(path, this.baseUrl);
21
+ if (opts?.params) {
22
+ for (const [k, v] of Object.entries(opts.params)) {
23
+ url.searchParams.set(k, v);
24
+ }
25
+ }
26
+ const controller = new AbortController();
27
+ const timer = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
28
+ const headers = {
29
+ Accept: "application/json",
30
+ };
31
+ if (opts?.token) {
32
+ headers.Authorization = `Bearer ${opts.token}`;
33
+ }
34
+ if (opts?.body) {
35
+ headers["Content-Type"] = "application/json";
36
+ }
37
+ if (this.clientSecret && !opts?.token) {
38
+ const credentials = `${this.clientId}:${this.clientSecret}`;
39
+ const basic = typeof Buffer !== "undefined"
40
+ ? Buffer.from(credentials).toString("base64")
41
+ : btoa(credentials);
42
+ headers.Authorization = `Basic ${basic}`;
43
+ }
44
+ try {
45
+ const res = await fetch(url.toString(), {
46
+ method: opts?.method ?? "GET",
47
+ headers,
48
+ body: opts?.body ? JSON.stringify(opts.body) : undefined,
49
+ signal: controller.signal,
50
+ });
51
+ if (!res.ok) {
52
+ const text = await res.text().catch(() => "");
53
+ throw new Error(`IAM billing request failed (${res.status}): ${text}`.trim());
54
+ }
55
+ return (await res.json());
56
+ }
57
+ finally {
58
+ clearTimeout(timer);
59
+ }
60
+ }
61
+ // -----------------------------------------------------------------------
62
+ // Subscriptions
63
+ // -----------------------------------------------------------------------
64
+ /** Get all subscriptions for an owner. */
65
+ async getSubscriptions(token) {
66
+ const owner = this.orgName ?? "admin";
67
+ const resp = await this.request("/api/get-subscriptions", { params: { owner }, token });
68
+ return resp.data ?? [];
69
+ }
70
+ /** Get a specific subscription by ID ("owner/name" format). */
71
+ async getSubscription(id, token) {
72
+ const resp = await this.request("/api/get-subscription", { params: { id }, token });
73
+ return resp.data ?? null;
74
+ }
75
+ /** Get the subscription for a specific user. */
76
+ async getUserSubscription(userId, token) {
77
+ const subs = await this.getSubscriptions(token);
78
+ return subs.find((s) => s.user === userId) ?? null;
79
+ }
80
+ // -----------------------------------------------------------------------
81
+ // Plans
82
+ // -----------------------------------------------------------------------
83
+ /** Get all plans for an owner. */
84
+ async getPlans(token) {
85
+ const owner = this.orgName ?? "admin";
86
+ const resp = await this.request("/api/get-plans", { params: { owner }, token });
87
+ return resp.data ?? [];
88
+ }
89
+ /** Get a specific plan by ID. */
90
+ async getPlan(id, token) {
91
+ const resp = await this.request("/api/get-plan", { params: { id }, token });
92
+ return resp.data ?? null;
93
+ }
94
+ // -----------------------------------------------------------------------
95
+ // Pricing
96
+ // -----------------------------------------------------------------------
97
+ /** Get all pricing configurations for an owner. */
98
+ async getPricings(token) {
99
+ const owner = this.orgName ?? "admin";
100
+ const resp = await this.request("/api/get-pricings", { params: { owner }, token });
101
+ return resp.data ?? [];
102
+ }
103
+ /** Get a specific pricing by ID. */
104
+ async getPricing(id, token) {
105
+ const resp = await this.request("/api/get-pricing", { params: { id }, token });
106
+ return resp.data ?? null;
107
+ }
108
+ // -----------------------------------------------------------------------
109
+ // Payments
110
+ // -----------------------------------------------------------------------
111
+ /** Get all payments for an owner. */
112
+ async getPayments(token) {
113
+ const owner = this.orgName ?? "admin";
114
+ const resp = await this.request("/api/get-payments", { params: { owner }, token });
115
+ return resp.data ?? [];
116
+ }
117
+ /** Get a specific payment by ID. */
118
+ async getPayment(id, token) {
119
+ const resp = await this.request("/api/get-payment", { params: { id }, token });
120
+ return resp.data ?? null;
121
+ }
122
+ // -----------------------------------------------------------------------
123
+ // Orders (if supported by IAM)
124
+ // -----------------------------------------------------------------------
125
+ /** Get all orders for an owner. */
126
+ async getOrders(token) {
127
+ const owner = this.orgName ?? "admin";
128
+ const resp = await this.request("/api/get-orders", { params: { owner }, token });
129
+ return resp.data ?? [];
130
+ }
131
+ /** Get a specific order by ID. */
132
+ async getOrder(id, token) {
133
+ const resp = await this.request("/api/get-order", { params: { id }, token });
134
+ return resp.data ?? null;
135
+ }
136
+ // -----------------------------------------------------------------------
137
+ // Convenience: check subscription status for an org
138
+ // -----------------------------------------------------------------------
139
+ /** Check if an org has an active subscription. */
140
+ async isSubscriptionActive(orgName, token) {
141
+ const subs = await this.getSubscriptions(token);
142
+ // Find subscription matching the org
143
+ const sub = subs.find((s) => s.owner === orgName && (s.state === "Active" || s.state === "active")) ?? null;
144
+ if (!sub) {
145
+ return { active: false, subscription: null, plan: null };
146
+ }
147
+ let plan = null;
148
+ if (sub.plan) {
149
+ plan = await this.getPlan(sub.plan, token);
150
+ }
151
+ return { active: true, subscription: sub, plan };
152
+ }
153
+ }
154
+ //# sourceMappingURL=billing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing.js","sourceRoot":"","sources":["../src/billing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Browser-side OAuth2 flows for Hanzo IAM.
3
+ *
4
+ * Provides PKCE-based login redirect, code exchange, token refresh,
5
+ * popup signin, and silent signin for single-page applications.
6
+ *
7
+ * Adapted and modernized from casdoor-js-sdk.
8
+ */
9
+ import type { IamConfig, TokenResponse } from "./types.js";
10
+ export type BrowserIamConfig = IamConfig & {
11
+ /** OAuth2 redirect URI (e.g. "https://app.hanzo.bot/auth/callback"). */
12
+ redirectUri: string;
13
+ /** OAuth2 scopes (default: "openid profile email"). */
14
+ scope?: string;
15
+ /** Storage to use for tokens (default: sessionStorage). */
16
+ storage?: Storage;
17
+ };
18
+ export declare class BrowserIamSdk {
19
+ private readonly config;
20
+ private readonly storage;
21
+ private discoveryCache;
22
+ constructor(config: BrowserIamConfig);
23
+ private getDiscovery;
24
+ /**
25
+ * Start the OAuth2 PKCE login flow by redirecting to the IAM authorize endpoint.
26
+ *
27
+ * Generates PKCE challenge and state, stores them in session storage,
28
+ * then redirects the browser.
29
+ */
30
+ signinRedirect(params?: {
31
+ additionalParams?: Record<string, string>;
32
+ }): Promise<void>;
33
+ /**
34
+ * Handle the OAuth2 callback after redirect. Exchanges the authorization code
35
+ * for tokens using PKCE.
36
+ *
37
+ * Call this on your callback page (e.g. /auth/callback).
38
+ * Returns the token response, or throws if the state doesn't match.
39
+ */
40
+ handleCallback(callbackUrl?: string): Promise<TokenResponse>;
41
+ /** Refresh the access token using the stored refresh token. */
42
+ refreshAccessToken(): Promise<TokenResponse>;
43
+ /**
44
+ * Open the IAM login page in a popup window. Resolves when the popup
45
+ * completes the OAuth flow and returns tokens.
46
+ */
47
+ signinPopup(params?: {
48
+ width?: number;
49
+ height?: number;
50
+ additionalParams?: Record<string, string>;
51
+ }): Promise<TokenResponse>;
52
+ /**
53
+ * Attempt silent authentication via a hidden iframe.
54
+ * Useful for checking if the user has an active IAM session.
55
+ * Returns null if silent auth fails (user needs to log in interactively).
56
+ */
57
+ signinSilent(timeoutMs?: number): Promise<TokenResponse | null>;
58
+ private storeTokens;
59
+ /** Get the stored access token (may be expired). */
60
+ getAccessToken(): string | null;
61
+ /** Get the stored refresh token. */
62
+ getRefreshToken(): string | null;
63
+ /** Get the stored ID token. */
64
+ getIdToken(): string | null;
65
+ /** Check if the stored access token is expired. */
66
+ isTokenExpired(): boolean;
67
+ /**
68
+ * Get a valid access token — refreshes automatically if expired.
69
+ * Returns null if no token and no refresh token available.
70
+ */
71
+ getValidAccessToken(): Promise<string | null>;
72
+ /** Clear all stored tokens (logout). */
73
+ clearTokens(): void;
74
+ /** Fetch user info from the OIDC userinfo endpoint using the stored access token. */
75
+ getUserInfo(): Promise<Record<string, unknown>>;
76
+ /** Build the signup URL for the IAM server. */
77
+ getSignupUrl(params?: {
78
+ enablePassword?: boolean;
79
+ }): string;
80
+ /** Build the user profile URL on the IAM server. */
81
+ getUserProfileUrl(username: string): string;
82
+ }
83
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAC;AAmB1E,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG;IACzC,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,cAAc,CAA8B;gBAExC,MAAM,EAAE,gBAAgB;YAStB,YAAY;IAkB1B;;;;;OAKG;IACG,cAAc,CAAC,MAAM,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B3F;;;;;;OAMG;IACG,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA0DlE,+DAA+D;IACzD,kBAAkB,IAAI,OAAO,CAAC,aAAa,CAAC;IAiClD;;;OAGG;IACG,WAAW,CAAC,MAAM,CAAC,EAAE;QACzB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC3C,GAAG,OAAO,CAAC,aAAa,CAAC;IAiE1B;;;;OAIG;IACG,YAAY,CAAC,SAAS,SAAO,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IA4DnE,OAAO,CAAC,WAAW;IAcnB,oDAAoD;IACpD,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B,oCAAoC;IACpC,eAAe,IAAI,MAAM,GAAG,IAAI;IAIhC,+BAA+B;IAC/B,UAAU,IAAI,MAAM,GAAG,IAAI;IAI3B,mDAAmD;IACnD,cAAc,IAAI,OAAO;IAMzB;;;OAGG;IACG,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAgBnD,wCAAwC;IACxC,WAAW,IAAI,IAAI;IAanB,qFAAqF;IAC/E,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAmBrD,+CAA+C;IAC/C,YAAY,CAAC,MAAM,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM;IAW3D,oDAAoD;IACpD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAK5C"}