@multiplatform.one/keycloak 6.0.4 → 6.3.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 (85) hide show
  1. package/README.md +58 -0
  2. package/dist/cjs/index.cjs +46 -6
  3. package/dist/cjs/index.native.cjs +748 -0
  4. package/dist/esm/index.js +45 -5
  5. package/dist/esm/index.native.js +715 -0
  6. package/package.json +23 -17
  7. package/src/Authenticated.tsx +3 -1
  8. package/src/Loading.tsx +10 -2
  9. package/src/betterAuth/expoAuthFlow.native.ts +238 -0
  10. package/src/frappeToken.native.ts +45 -0
  11. package/src/frappeToken.ts +59 -0
  12. package/src/index.ts +1 -0
  13. package/src/provider/KeycloakProvider.tsx +11 -0
  14. package/src/provider/authProvider/index.native.tsx +72 -64
  15. package/src/session/index.native.ts +32 -7
  16. package/types/Authenticated.d.ts +9 -0
  17. package/types/Authenticated.d.ts.map +1 -0
  18. package/types/Loading.d.ts +6 -0
  19. package/types/Loading.d.ts.map +1 -0
  20. package/types/authConfig.d.ts +10 -0
  21. package/types/authConfig.d.ts.map +1 -0
  22. package/types/betterAuth/client.d.ts +798 -0
  23. package/types/betterAuth/client.d.ts.map +1 -0
  24. package/types/betterAuth/expoAuthFlow.native.d.ts +31 -0
  25. package/types/betterAuth/expoAuthFlow.native.d.ts.map +1 -0
  26. package/types/betterAuth/expoClient.d.ts +803 -0
  27. package/types/betterAuth/expoClient.d.ts.map +1 -0
  28. package/types/betterAuth/index.d.ts +3 -0
  29. package/types/betterAuth/index.d.ts.map +1 -0
  30. package/types/frappeToken.d.ts +19 -0
  31. package/types/frappeToken.d.ts.map +1 -0
  32. package/types/frappeToken.native.d.ts +15 -0
  33. package/types/frappeToken.native.d.ts.map +1 -0
  34. package/types/hooks/index.d.ts +4 -0
  35. package/types/hooks/index.d.ts.map +1 -0
  36. package/types/hooks/useAuthConfig.d.ts +2 -0
  37. package/types/hooks/useAuthConfig.d.ts.map +1 -0
  38. package/types/hooks/useTokensFromQuery/index.d.ts +2 -0
  39. package/types/hooks/useTokensFromQuery/index.d.ts.map +1 -0
  40. package/types/hooks/useTokensFromQuery/index.native.d.ts +2 -0
  41. package/types/hooks/useTokensFromQuery/index.native.d.ts.map +1 -0
  42. package/types/hooks/useTokensFromState.d.ts +2 -0
  43. package/types/hooks/useTokensFromState.d.ts.map +1 -0
  44. package/types/index.d.ts +10 -0
  45. package/types/index.d.ts.map +1 -0
  46. package/types/keycloak/base.d.ts +50 -0
  47. package/types/keycloak/base.d.ts.map +1 -0
  48. package/types/keycloak/config.d.ts +12 -0
  49. package/types/keycloak/config.d.ts.map +1 -0
  50. package/types/keycloak/context.d.ts +3 -0
  51. package/types/keycloak/context.d.ts.map +1 -0
  52. package/types/keycloak/index.d.ts +20 -0
  53. package/types/keycloak/index.d.ts.map +1 -0
  54. package/types/keycloak/index.native.d.ts +7 -0
  55. package/types/keycloak/index.native.d.ts.map +1 -0
  56. package/types/keycloak/index.webext.d.ts +19 -0
  57. package/types/keycloak/index.webext.d.ts.map +1 -0
  58. package/types/one.d.ts +28 -0
  59. package/types/one.d.ts.map +1 -0
  60. package/types/provider/AfterAuth.d.ts +6 -0
  61. package/types/provider/AfterAuth.d.ts.map +1 -0
  62. package/types/provider/KeycloakProvider.d.ts +17 -0
  63. package/types/provider/KeycloakProvider.d.ts.map +1 -0
  64. package/types/provider/authProvider/index.d.ts +13 -0
  65. package/types/provider/authProvider/index.d.ts.map +1 -0
  66. package/types/provider/authProvider/index.native.d.ts +15 -0
  67. package/types/provider/authProvider/index.native.d.ts.map +1 -0
  68. package/types/provider/authProvider/index.webext.d.ts +14 -0
  69. package/types/provider/authProvider/index.webext.d.ts.map +1 -0
  70. package/types/provider/authProvider/shared.d.ts +38 -0
  71. package/types/provider/authProvider/shared.d.ts.map +1 -0
  72. package/types/provider/index.d.ts +4 -0
  73. package/types/provider/index.d.ts.map +1 -0
  74. package/types/session/index.d.ts +29 -0
  75. package/types/session/index.d.ts.map +1 -0
  76. package/types/session/index.native.d.ts +13 -0
  77. package/types/session/index.native.d.ts.map +1 -0
  78. package/types/session/index.webext.d.ts +11 -0
  79. package/types/session/index.webext.d.ts.map +1 -0
  80. package/types/state.d.ts +18 -0
  81. package/types/state.d.ts.map +1 -0
  82. package/types/token.d.ts +129 -0
  83. package/types/token.d.ts.map +1 -0
  84. package/types/types.d.ts +19 -0
  85. package/types/types.d.ts.map +1 -0
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # @multiplatform.one/keycloak
2
+
3
+ Keycloak authentication for the multiplatform.one ecosystem — a
4
+ [Better Auth](https://better-auth.com)–powered client with a `useKeycloak()`
5
+ hook, session hooks, route guards, and a server config factory for
6
+ [One](https://onestack.dev) apps.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ pnpm add @multiplatform.one/keycloak
12
+ ```
13
+
14
+ Peers: `react`, `@multiplatform.one/logger`, `@multiplatform.one/platform`.
15
+
16
+ ## What it owns
17
+
18
+ - **`KeycloakProvider`** — auth context (`debug`, `disabled`, `iframeSso`,
19
+ `loginRedirectUri`, …); usually mounted for you by
20
+ `createApp({ keycloak: true })` from `@multiplatform.one/core`
21
+ - **`useKeycloak()`** — the Keycloak client (login/logout, tokens); returns
22
+ `null` when auth is disabled
23
+ - **`useSession()`**, `useAuthConfig()`, `useTokensFromQuery`,
24
+ `useTokensFromState`
25
+ - **`Authenticated`** / `withAuthenticated` — render children only when
26
+ signed in
27
+ - **Token helpers** — `isTokenExpired`, `validOrRefreshableToken`,
28
+ `getKeycloakBearerToken`, wallet-claim readers (`getWalletsFromToken`,
29
+ `getWalletAddresses`, `hasWallets`)
30
+ - **`@multiplatform.one/keycloak/one`** — `createAuth()` Better Auth server
31
+ factory (stateless JWE sessions, Keycloak OAuth, Expo support)
32
+
33
+ ## What it must not do
34
+
35
+ - No UI beyond the guard components — login screens belong to apps
36
+ - No Frappe logic besides bearer-token bridging (`getKeycloakBearerToken`)
37
+
38
+ ## Usage
39
+
40
+ ```tsx
41
+ import { Authenticated, useKeycloak } from "@multiplatform.one/keycloak";
42
+
43
+ export function AccountMenu() {
44
+ const keycloak = useKeycloak();
45
+ if (!keycloak) return null; // auth disabled
46
+ return (
47
+ <Authenticated>
48
+ <button onClick={() => keycloak.logout()}>Sign out</button>
49
+ </Authenticated>
50
+ );
51
+ }
52
+ ```
53
+
54
+ Uses the patched adapter from `@multiplatform.one/keycloak-js` under the hood.
55
+
56
+ ## License
57
+
58
+ Apache-2.0
@@ -40,6 +40,7 @@ __export(index_exports, {
40
40
  KeycloakProvider: () => KeycloakProvider,
41
41
  defaultAuthConfig: () => defaultAuthConfig,
42
42
  getAllWalletAddresses: () => getAllWalletAddresses,
43
+ getKeycloakBearerToken: () => getKeycloakBearerToken,
43
44
  getWalletAddresses: () => getWalletAddresses,
44
45
  getWalletsFromToken: () => getWalletsFromToken,
45
46
  hasWallets: () => hasWallets,
@@ -57,7 +58,7 @@ module.exports = __toCommonJS(index_exports);
57
58
  // src/Authenticated.tsx
58
59
  var import_platform6 = require("@multiplatform.one/platform");
59
60
  var import_react8 = require("react");
60
- var import_tamagui = require("tamagui");
61
+ var import_react_native = require("react-native");
61
62
 
62
63
  // src/hooks/useAuthConfig.ts
63
64
  var import_react2 = require("react");
@@ -434,11 +435,11 @@ function Authenticated({
434
435
  if (disabled) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
435
436
  if (typeof keycloak === "undefined") {
436
437
  const LoadingComponent = loadingComponent;
437
- return LoadingComponent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoadingComponent, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tamagui.Text, { children: authConfig.debug ? "loading" : null });
438
+ return LoadingComponent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoadingComponent, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { children: authConfig.debug ? "loading" : null });
438
439
  }
439
440
  if (keycloak === null || keycloak.authenticated) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
440
441
  const LoggedOutComponent = loggedOutComponent;
441
- return LoggedOutComponent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoggedOutComponent, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tamagui.Text, { children: authConfig.debug ? "not authenticated" : null });
442
+ return LoggedOutComponent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoggedOutComponent, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { children: authConfig.debug ? "not authenticated" : null });
442
443
  }
443
444
  function withAuthenticated(Component, options = {}) {
444
445
  return (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Authenticated, { ...options, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props }) });
@@ -506,13 +507,16 @@ var import_logger2 = require("@multiplatform.one/logger");
506
507
  var import_react10 = require("react");
507
508
 
508
509
  // src/Loading.tsx
509
- var import_tamagui2 = require("tamagui");
510
+ var import_react_native2 = require("react-native");
510
511
  var import_jsx_runtime3 = require("react/jsx-runtime");
511
512
  function Loading({ loadingComponent }) {
512
513
  const { debug } = useAuthConfig();
513
514
  const LoadingComponent = loadingComponent;
514
515
  if (typeof LoadingComponent === "undefined") {
515
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_tamagui2.Text, { children: debug ? "loading" : null });
516
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native2.View, { style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: [
517
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native2.ActivityIndicator, {}),
518
+ debug ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native2.Text, { children: "loading" }) : null
519
+ ] });
516
520
  }
517
521
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LoadingComponent, {});
518
522
  }
@@ -859,8 +863,10 @@ var import_react11 = require("react");
859
863
  var import_jsx_runtime5 = require("react/jsx-runtime");
860
864
  function KeycloakProvider({
861
865
  baseUrl,
866
+ betterAuthBaseUrl,
862
867
  children,
863
868
  clientId,
869
+ expoScheme,
864
870
  loginRedirectUri,
865
871
  debug,
866
872
  disabled,
@@ -880,9 +886,43 @@ function KeycloakProvider({
880
886
  clientId: clientId || "app",
881
887
  publicClientId,
882
888
  realm: realm || "main",
883
- url: baseUrl ?? ""
889
+ url: baseUrl ?? "",
890
+ betterAuthBaseUrl,
891
+ expoScheme
884
892
  },
885
893
  children
886
894
  }
887
895
  ) });
888
896
  }
897
+
898
+ // src/frappeToken.ts
899
+ var cached;
900
+ async function getKeycloakBearerToken() {
901
+ if (typeof window === "undefined") return void 0;
902
+ if (cached && cached.expiresAt - 6e4 > Date.now()) return cached.token;
903
+ try {
904
+ const res = await fetch(`${window.location.origin}/api/auth/get-access-token`, {
905
+ method: "POST",
906
+ credentials: "include",
907
+ headers: { "Content-Type": "application/json" },
908
+ body: JSON.stringify({ providerId: "keycloak" })
909
+ });
910
+ if (!res.ok) {
911
+ cached = void 0;
912
+ return void 0;
913
+ }
914
+ const data = await res.json().catch(() => null);
915
+ if (!data?.accessToken) {
916
+ cached = void 0;
917
+ return void 0;
918
+ }
919
+ cached = {
920
+ token: data.accessToken,
921
+ expiresAt: data.accessTokenExpiresAt ? new Date(data.accessTokenExpiresAt).getTime() : Date.now() + 6e4
922
+ };
923
+ return cached.token;
924
+ } catch {
925
+ cached = void 0;
926
+ return void 0;
927
+ }
928
+ }