@hanzo/iam 0.6.1 → 0.7.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 (47) hide show
  1. package/dist/auth.d.ts +1 -1
  2. package/dist/auth.js +3 -3
  3. package/dist/auth.js.map +1 -1
  4. package/dist/betterauth.d.ts +67 -0
  5. package/dist/betterauth.d.ts.map +1 -0
  6. package/dist/betterauth.js +64 -0
  7. package/dist/betterauth.js.map +1 -0
  8. package/dist/browser.d.ts +87 -4
  9. package/dist/browser.d.ts.map +1 -1
  10. package/dist/browser.js +229 -8
  11. package/dist/browser.js.map +1 -1
  12. package/dist/client.d.ts +11 -22
  13. package/dist/client.d.ts.map +1 -1
  14. package/dist/client.js +39 -96
  15. package/dist/client.js.map +1 -1
  16. package/dist/index.d.ts +4 -4
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +3 -3
  19. package/dist/index.js.map +1 -1
  20. package/dist/nextauth.d.ts +12 -10
  21. package/dist/nextauth.d.ts.map +1 -1
  22. package/dist/nextauth.js +12 -11
  23. package/dist/nextauth.js.map +1 -1
  24. package/dist/passport.d.ts +44 -0
  25. package/dist/passport.d.ts.map +1 -0
  26. package/dist/passport.js +67 -0
  27. package/dist/passport.js.map +1 -0
  28. package/dist/pkce.d.ts +2 -2
  29. package/dist/pkce.js +2 -2
  30. package/dist/react.d.ts +8 -94
  31. package/dist/react.d.ts.map +1 -1
  32. package/dist/react.js +23 -454
  33. package/dist/react.js.map +1 -1
  34. package/dist/types.d.ts +1 -16
  35. package/dist/types.d.ts.map +1 -1
  36. package/dist/types.js +1 -1
  37. package/package.json +16 -7
  38. package/src/auth.ts +3 -3
  39. package/src/betterauth.ts +91 -0
  40. package/src/browser.ts +255 -11
  41. package/src/client.ts +47 -154
  42. package/src/index.ts +3 -4
  43. package/src/nextauth.ts +15 -13
  44. package/src/passport.ts +97 -0
  45. package/src/pkce.ts +2 -2
  46. package/src/react.ts +28 -635
  47. package/src/types.ts +1 -21
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Core types for the Hanzo IAM SDK.
3
- * Based on Casdoor data models.
3
+ * Hanzo IAM data models.
4
4
  */
5
5
  export {};
6
6
  //# sourceMappingURL=types.js.map
package/package.json CHANGED
@@ -1,18 +1,20 @@
1
1
  {
2
2
  "name": "@hanzo/iam",
3
- "version": "0.6.1",
4
- "description": "TypeScript SDK for Hanzo IAM OIDC auth, JWT validation, OAuth2 PKCE, user/org/project APIs",
3
+ "version": "0.7.0",
4
+ "description": "TypeScript SDK for Hanzo IAM \u2014 OIDC auth, JWT validation, OAuth2 PKCE, user/org/project APIs",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
10
  "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js"
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
12
13
  },
13
14
  "./auth": {
14
15
  "types": "./dist/auth.d.ts",
15
- "import": "./dist/auth.js"
16
+ "import": "./dist/auth.js",
17
+ "default": "./dist/auth.js"
16
18
  },
17
19
  "./browser": {
18
20
  "types": "./dist/browser.d.ts",
@@ -33,6 +35,14 @@
33
35
  "./nextauth": {
34
36
  "types": "./dist/nextauth.d.ts",
35
37
  "import": "./dist/nextauth.js"
38
+ },
39
+ "./passport": {
40
+ "types": "./dist/passport.d.ts",
41
+ "import": "./dist/passport.js"
42
+ },
43
+ "./betterauth": {
44
+ "types": "./dist/betterauth.d.ts",
45
+ "import": "./dist/betterauth.js"
36
46
  }
37
47
  },
38
48
  "files": [
@@ -45,8 +55,8 @@
45
55
  "build": "tsc",
46
56
  "dev": "tsc --watch",
47
57
  "clean": "rm -rf dist",
48
- "prepare": "npm run clean && npm run build",
49
- "prepublishOnly": "npm run clean && npm run build",
58
+ "prepare": "pnpm clean && pnpm build",
59
+ "prepublishOnly": "pnpm clean && pnpm build",
50
60
  "test": "node --test --import tsx src/**/*.test.ts"
51
61
  },
52
62
  "dependencies": {
@@ -68,7 +78,6 @@
68
78
  "keywords": [
69
79
  "hanzo",
70
80
  "iam",
71
- "casdoor",
72
81
  "oidc",
73
82
  "oauth2",
74
83
  "pkce",
package/src/auth.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * JWT validation using jose library + OIDC JWKS discovery.
3
3
  *
4
- * Validates access/ID tokens issued by Hanzo IAM (Casdoor).
4
+ * Validates access/ID tokens issued by Hanzo IAM.
5
5
  */
6
6
 
7
7
  import { createRemoteJWKSet, jwtVerify, type JWTPayload } from "jose";
@@ -109,7 +109,7 @@ export async function validateToken(
109
109
  return { ok: false, reason: "iam_token_expired" };
110
110
  }
111
111
  if (message.includes("audience")) {
112
- // Retry without audience check - some Casdoor configs don't set aud
112
+ // Retry without audience check - some IAM configs don't set aud
113
113
  try {
114
114
  const result = await jwtVerify(token, keySet, {
115
115
  issuer,
@@ -137,7 +137,7 @@ export async function validateToken(
137
137
  return { ok: false, reason: "iam_subject_missing" };
138
138
  }
139
139
 
140
- // Casdoor sub format is "org/username" - extract owner
140
+ // IAM sub format is "org/username" - extract owner
141
141
  const parts = sub.split("/");
142
142
  const owner = parts.length > 1 ? parts[0] : config.orgName ?? "unknown";
143
143
 
@@ -0,0 +1,91 @@
1
+ /**
2
+ * BetterAuth SSO provider configuration for IAM.
3
+ *
4
+ * Returns a provider config object compatible with BetterAuth's
5
+ * `socialProviders` or generic OAuth plugin.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { betterAuth } from "better-auth";
10
+ * import { iamProvider } from "@hanzo/iam/betterauth";
11
+ *
12
+ * export const auth = betterAuth({
13
+ * socialProviders: [
14
+ * iamProvider({
15
+ * serverUrl: process.env.IAM_SERVER_URL!,
16
+ * clientId: process.env.IAM_CLIENT_ID!,
17
+ * clientSecret: process.env.IAM_CLIENT_SECRET!,
18
+ * }),
19
+ * ],
20
+ * });
21
+ * ```
22
+ *
23
+ * @packageDocumentation
24
+ */
25
+
26
+ import type { IamConfig } from "./types.js";
27
+
28
+ export interface IamSocialProvider {
29
+ id: string;
30
+ name: string;
31
+ type: "oidc";
32
+ issuer: string;
33
+ clientId: string;
34
+ clientSecret?: string;
35
+ authorization: { url: string; params: { scope: string } };
36
+ token: { url: string };
37
+ userinfo: { url: string };
38
+ profile: (profile: Record<string, unknown>) => {
39
+ id: string;
40
+ name: string;
41
+ email: string;
42
+ image: string | null;
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Create a BetterAuth-compatible social provider for IAM.
48
+ *
49
+ * Works with BetterAuth's SSO plugin or generic OAuth integration.
50
+ * Uses standard OIDC endpoints.
51
+ */
52
+ export function iamProvider(
53
+ config: IamConfig & { redirectUri?: string },
54
+ ): IamSocialProvider {
55
+ const baseUrl = config.serverUrl.replace(/\/+$/, "");
56
+
57
+ return {
58
+ id: "iam",
59
+ name: "IAM",
60
+ type: "oidc",
61
+ issuer: baseUrl,
62
+ clientId: config.clientId,
63
+ clientSecret: config.clientSecret,
64
+ authorization: {
65
+ url: `${baseUrl}/oauth/authorize`,
66
+ params: { scope: "openid profile email" },
67
+ },
68
+ token: { url: `${baseUrl}/oauth/token` },
69
+ userinfo: { url: `${baseUrl}/oauth/userinfo` },
70
+ profile(profile: Record<string, unknown>) {
71
+ return {
72
+ id: (profile.sub as string) ?? (profile.id as string) ?? "",
73
+ name:
74
+ (profile.displayName as string) ??
75
+ (profile.name as string) ??
76
+ (profile.preferred_username as string) ??
77
+ "",
78
+ email: (profile.email as string) ?? "",
79
+ image: (profile.avatar as string) ?? (profile.picture as string) ?? null,
80
+ };
81
+ },
82
+ };
83
+ }
84
+
85
+ // Backwards-compatible aliases
86
+ /** @deprecated Use iamProvider instead */
87
+ export { iamProvider as hanzoIamProvider };
88
+ /** @deprecated Use iamProvider instead */
89
+ export { iamProvider as hanzoIamSocialProvider };
90
+ /** @deprecated Use IamSocialProvider instead */
91
+ export type { IamSocialProvider as HanzoIamSocialProvider };
package/src/browser.ts CHANGED
@@ -4,11 +4,11 @@
4
4
  * Provides PKCE-based login redirect, code exchange, token refresh,
5
5
  * popup signin, and silent signin for single-page applications.
6
6
  *
7
- * Adapted and modernized from casdoor-js-sdk.
7
+ * Adapted and modernized for Hanzo IAM.
8
8
  */
9
9
 
10
10
  import type { IamConfig, TokenResponse, OidcDiscovery } from "./types.js";
11
- import { generatePkceChallenge, generateState } from "./pkce.js";
11
+ import { generatePKCEChallenge, generateState } from "./pkce.js";
12
12
 
13
13
  // ---------------------------------------------------------------------------
14
14
  // Storage keys
@@ -26,7 +26,7 @@ const KEY_EXPIRES_AT = `${STORAGE_PREFIX}expires_at`;
26
26
  // Browser IAM SDK
27
27
  // ---------------------------------------------------------------------------
28
28
 
29
- export type BrowserIamConfig = IamConfig & {
29
+ export type IAMConfig = IamConfig & {
30
30
  /** OAuth2 redirect URI (e.g. "https://app.hanzo.bot/auth/callback"). */
31
31
  redirectUri: string;
32
32
  /** OAuth2 scopes (default: "openid profile email"). */
@@ -43,12 +43,12 @@ export type BrowserIamConfig = IamConfig & {
43
43
  proxyBaseUrl?: string;
44
44
  };
45
45
 
46
- export class BrowserIamSdk {
47
- private readonly config: BrowserIamConfig;
46
+ export class IAM {
47
+ private readonly config: IAMConfig;
48
48
  private readonly storage: Storage;
49
49
  private discoveryCache: OidcDiscovery | null = null;
50
50
 
51
- constructor(config: BrowserIamConfig) {
51
+ constructor(config: IAMConfig) {
52
52
  this.config = config;
53
53
  this.storage = config.storage ?? sessionStorage;
54
54
  }
@@ -64,7 +64,7 @@ export class BrowserIamSdk {
64
64
 
65
65
  // Try fetching the OIDC discovery document. If it fails (e.g. due to
66
66
  // CORS when the IAM server doesn't send Access-Control-Allow-Origin),
67
- // construct a fallback from well-known Casdoor/Hanzo IAM endpoint paths.
67
+ // construct a fallback from well-known Hanzo IAM endpoint paths.
68
68
  try {
69
69
  const res = await fetch(`${baseUrl}/.well-known/openid-configuration`, {
70
70
  headers: { Accept: "application/json" },
@@ -79,7 +79,7 @@ export class BrowserIamSdk {
79
79
 
80
80
  this.discoveryCache = {
81
81
  issuer: baseUrl,
82
- authorization_endpoint: `${baseUrl}/login/oauth/authorize`,
82
+ authorization_endpoint: `${baseUrl}/oauth/authorize`,
83
83
  token_endpoint: `${baseUrl}/oauth/token`,
84
84
  userinfo_endpoint: `${baseUrl}/oauth/userinfo`,
85
85
  jwks_uri: `${baseUrl}/.well-known/jwks`,
@@ -102,7 +102,7 @@ export class BrowserIamSdk {
102
102
  */
103
103
  async signinRedirect(params?: { additionalParams?: Record<string, string> }): Promise<void> {
104
104
  const discovery = await this.getDiscovery();
105
- const { codeVerifier, codeChallenge } = await generatePkceChallenge();
105
+ const { codeVerifier, codeChallenge } = await generatePKCEChallenge();
106
106
  const state = generateState();
107
107
 
108
108
  this.storage.setItem(KEY_STATE, state);
@@ -265,7 +265,7 @@ export class BrowserIamSdk {
265
265
  additionalParams?: Record<string, string>;
266
266
  }): Promise<TokenResponse> {
267
267
  const discovery = await this.getDiscovery();
268
- const { codeVerifier, codeChallenge } = await generatePkceChallenge();
268
+ const { codeVerifier, codeChallenge } = await generatePKCEChallenge();
269
269
  const state = generateState();
270
270
 
271
271
  this.storage.setItem(KEY_STATE, state);
@@ -335,7 +335,7 @@ export class BrowserIamSdk {
335
335
  */
336
336
  async signinSilent(timeoutMs = 5000): Promise<TokenResponse | null> {
337
337
  const discovery = await this.getDiscovery();
338
- const { codeVerifier, codeChallenge } = await generatePkceChallenge();
338
+ const { codeVerifier, codeChallenge } = await generatePKCEChallenge();
339
339
  const state = generateState();
340
340
 
341
341
  this.storage.setItem(KEY_STATE, state);
@@ -504,4 +504,248 @@ export class BrowserIamSdk {
504
504
  const org = this.config.orgName ?? "built-in";
505
505
  return `${base}/users/${org}/${username}`;
506
506
  }
507
+
508
+ // -----------------------------------------------------------------------
509
+ // Casdoor REST surface (signup, OTP, REST login, phone lookup)
510
+ //
511
+ // The OIDC layer covers redirect/PKCE, token exchange, refresh, userinfo.
512
+ // These methods cover the Casdoor-native endpoints that don't have an OIDC
513
+ // analogue: phone/email OTP, custom signup with verification codes, and
514
+ // direct REST login that returns an authorization code in one round-trip
515
+ // (used as the bridge between OTP collection and `exchangeCode`).
516
+ //
517
+ // All paths are gateway-canonical (`/login`, `/signup`,
518
+ // `/send-verification-code`, `/get-phone-user`) — point `serverUrl` at the
519
+ // gateway prefix (e.g. `https://api.dev.satschel.com/v1/iam`) and the
520
+ // gateway proxies to Casdoor's `/api/*` internally.
521
+ // -----------------------------------------------------------------------
522
+
523
+ /**
524
+ * Send a verification code to a phone or email destination.
525
+ *
526
+ * @param contact `{ phone, countryCode }` for SMS, `{ email }` for email.
527
+ * @param method Casdoor method: `login`, `signup`, `forget`, `mfaSetup`, etc.
528
+ */
529
+ async sendVerificationCode(
530
+ contact: { phone: string; countryCode: string } | { email: string },
531
+ method: "login" | "signup" | "forget" | "mfaSetup" = "login",
532
+ ): Promise<{ ok: boolean; error?: string }> {
533
+ const isPhone = "phone" in contact;
534
+ const dest = isPhone ? contact.phone : contact.email;
535
+ const params: Record<string, string> = {
536
+ applicationId: `admin/${this.config.appName ?? "app"}`,
537
+ dest,
538
+ type: isPhone ? "phone" : "email",
539
+ method,
540
+ captchaType: "none",
541
+ captchaToken: "",
542
+ };
543
+ if (isPhone) params.countryCode = contact.countryCode;
544
+
545
+ const url = `${this.config.serverUrl.replace(/\/+$/, "")}/send-verification-code`;
546
+ const res = await fetch(url, {
547
+ method: "POST",
548
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
549
+ body: new URLSearchParams(params).toString(),
550
+ });
551
+ const data = await res.json().catch(() => ({}));
552
+ if (data.status === "ok") return { ok: true };
553
+ const msg = (data.msg as string) || `send-verification-code failed (${res.status})`;
554
+ // Provider misconfig is treated as soft success in dev — Casdoor still
555
+ // generates the code and stores it for verification.
556
+ if (msg.includes("SMS provider") || msg.includes("provider")) return { ok: true };
557
+ return { ok: false, error: msg };
558
+ }
559
+
560
+ /**
561
+ * Look up whether a phone number is registered. Returns `{ exists: false }`
562
+ * on 404 or unknown numbers; `{ exists: true }` when Casdoor confirms a user.
563
+ */
564
+ async lookupPhoneUser(phone: string, countryCode: string): Promise<{ exists: boolean; error?: string }> {
565
+ const url = `${this.config.serverUrl.replace(/\/+$/, "")}/get-phone-user`;
566
+ const res = await fetch(url, {
567
+ method: "POST",
568
+ headers: { "Content-Type": "application/json" },
569
+ body: JSON.stringify({
570
+ application: this.config.appName ?? "app",
571
+ phone,
572
+ countryCode,
573
+ }),
574
+ });
575
+ if (res.status === 404) return { exists: false };
576
+ if (!res.ok) return { exists: false, error: `lookupPhoneUser failed (${res.status})` };
577
+ return { exists: true };
578
+ }
579
+
580
+ /**
581
+ * Casdoor REST signup. Returns the new user's id on success.
582
+ *
583
+ * Phone signup flow: send phoneCode via `sendVerificationCode`, then call
584
+ * this with the OTP in `phoneCode`. Casdoor verifies the code internally.
585
+ * Email signup flow: same with `email` + `emailCode`.
586
+ */
587
+ async signup(params: {
588
+ method: "email" | "phone";
589
+ name: string;
590
+ username?: string;
591
+ email?: string;
592
+ phone?: string;
593
+ countryCode?: string;
594
+ password?: string;
595
+ emailCode?: string;
596
+ phoneCode?: string;
597
+ }): Promise<{ id?: string; ok: boolean; error?: string }> {
598
+ const username = params.username ?? params.name;
599
+ const password = params.password ?? `Liq${Date.now()}!`;
600
+ const body: Record<string, unknown> = {
601
+ application: this.config.appName ?? "app",
602
+ organization: this.config.orgName ?? "built-in",
603
+ name: params.name,
604
+ username,
605
+ password,
606
+ confirm: password,
607
+ agreement: true,
608
+ };
609
+ if (params.method === "email") {
610
+ body.email = params.email;
611
+ if (params.emailCode) body.emailCode = params.emailCode;
612
+ } else {
613
+ body.phone = params.phone;
614
+ body.countryCode = params.countryCode;
615
+ if (params.phoneCode) body.phoneCode = params.phoneCode;
616
+ if (params.email) body.email = params.email;
617
+ if (params.emailCode) body.emailCode = params.emailCode;
618
+ }
619
+ const url = `${this.config.serverUrl.replace(/\/+$/, "")}/signup`;
620
+ const res = await fetch(url, {
621
+ method: "POST",
622
+ headers: { "Content-Type": "application/json" },
623
+ body: JSON.stringify(body),
624
+ });
625
+ const data = await res.json().catch(() => ({}));
626
+ if (data.status === "ok") return { ok: true, id: data.data2 || data.data };
627
+ return { ok: false, error: (data.msg as string) || `signup failed (${res.status})` };
628
+ }
629
+
630
+ /**
631
+ * REST login that returns an authorization code (Casdoor `/login`).
632
+ *
633
+ * Use this when you want the caller to drive the PKCE flow without a
634
+ * full redirect — collect credentials in your own UI, get a code back,
635
+ * then call `exchangeCodeForToken` to land tokens.
636
+ */
637
+ async loginWithCredentials(params: {
638
+ username: string;
639
+ password: string;
640
+ type?: "code" | "token";
641
+ redirectUri?: string;
642
+ }): Promise<{ code?: string; ok: boolean; error?: string }> {
643
+ const { codeVerifier, codeChallenge } = await generatePKCEChallenge();
644
+ this.storage.setItem(KEY_CODE_VERIFIER, codeVerifier);
645
+
646
+ const url = new URL(`${this.config.serverUrl.replace(/\/+$/, "")}/login`);
647
+ url.searchParams.set("code_challenge", codeChallenge);
648
+ url.searchParams.set("code_challenge_method", "S256");
649
+
650
+ const res = await fetch(url.toString(), {
651
+ method: "POST",
652
+ headers: { "Content-Type": "application/json" },
653
+ body: JSON.stringify({
654
+ application: this.config.appName ?? "app",
655
+ organization: this.config.orgName ?? "built-in",
656
+ username: params.username,
657
+ password: params.password,
658
+ type: params.type ?? "code",
659
+ clientId: this.config.clientId,
660
+ redirectUri: params.redirectUri ?? this.config.redirectUri,
661
+ codeChallenge,
662
+ codeChallengeMethod: "S256",
663
+ autoSignin: true,
664
+ }),
665
+ });
666
+ const data = await res.json().catch(() => ({}));
667
+ if (data.status === "ok" && data.data) return { ok: true, code: data.data as string };
668
+ return { ok: false, error: (data.msg as string) || `login failed (${res.status})` };
669
+ }
670
+
671
+ /**
672
+ * Exchange an authorization code for tokens using the stored PKCE verifier.
673
+ * Pairs with `loginWithCredentials` for a code → tokens round-trip.
674
+ */
675
+ async exchangeCodeForToken(code: string, redirectUri?: string): Promise<TokenResponse> {
676
+ const codeVerifier = this.storage.getItem(KEY_CODE_VERIFIER);
677
+ if (!codeVerifier) {
678
+ throw new Error("Missing PKCE verifier — call loginWithCredentials() first");
679
+ }
680
+ this.storage.removeItem(KEY_CODE_VERIFIER);
681
+
682
+ const discovery = await this.getDiscovery();
683
+ const tokenUrl = this.config.proxyBaseUrl
684
+ ? `${this.config.proxyBaseUrl.replace(/\/+$/, "")}/auth/token`
685
+ : discovery.token_endpoint;
686
+
687
+ const body = new URLSearchParams({
688
+ grant_type: "authorization_code",
689
+ client_id: this.config.clientId,
690
+ code,
691
+ redirect_uri: redirectUri ?? this.config.redirectUri,
692
+ code_verifier: codeVerifier,
693
+ });
694
+ const res = await fetch(tokenUrl, {
695
+ method: "POST",
696
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
697
+ body: body.toString(),
698
+ });
699
+ if (!res.ok) {
700
+ const err = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
701
+ throw new Error((err as Record<string, string>).error_description || (err as Record<string, string>).error || "Token exchange failed");
702
+ }
703
+ const tokens = (await res.json()) as TokenResponse;
704
+ this.storeTokens(tokens);
705
+ return tokens;
706
+ }
707
+
708
+ /**
709
+ * Phone OTP login: tries the numbered username variants Casdoor accepts
710
+ * (`{phone}`, `{countryCode}{phone}`), exchanges the resulting code for
711
+ * tokens. Returns the token response, or throws on failure.
712
+ */
713
+ async loginWithPhoneOTP(params: {
714
+ phone: string;
715
+ countryCode: string;
716
+ code: string;
717
+ redirectUri?: string;
718
+ }): Promise<TokenResponse> {
719
+ const usernames = [params.phone, `${params.countryCode}${params.phone}`];
720
+ let lastError = "";
721
+ for (const username of usernames) {
722
+ const result = await this.loginWithCredentials({
723
+ username,
724
+ password: params.code,
725
+ redirectUri: params.redirectUri,
726
+ });
727
+ if (result.ok && result.code) {
728
+ return this.exchangeCodeForToken(result.code, params.redirectUri);
729
+ }
730
+ lastError = result.error ?? lastError;
731
+ }
732
+ throw new Error(lastError || "Phone OTP login failed");
733
+ }
734
+
735
+ /**
736
+ * Logout via Casdoor REST `/logout` (clears server-side session) and
737
+ * the local storage.
738
+ */
739
+ async logout(): Promise<void> {
740
+ const token = this.storage.getItem(KEY_ACCESS_TOKEN);
741
+ try {
742
+ await fetch(`${this.config.serverUrl.replace(/\/+$/, "")}/oauth/logout`, {
743
+ method: "POST",
744
+ headers: token ? { Authorization: `Bearer ${token}` } : {},
745
+ });
746
+ } catch {
747
+ // best-effort — local cleanup is what matters
748
+ }
749
+ this.clearTokens();
750
+ }
507
751
  }