@multiplatform.one/keycloak 6.6.0 → 7.0.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/dist/cjs/index.cjs +129 -55
- package/dist/cjs/index.native.cjs +239 -130
- package/dist/esm/index.js +131 -57
- package/dist/esm/index.native.js +239 -130
- package/package.json +16 -11
- package/src/betterAuth/client.ts +3 -1
- package/src/betterAuth/expoAuthFlow.native.spec.ts +307 -0
- package/src/betterAuth/expoAuthFlow.native.ts +189 -55
- package/src/frappeToken.native.spec.ts +104 -0
- package/src/frappeToken.native.ts +46 -2
- package/src/frappeToken.spec.ts +141 -0
- package/src/frappeToken.ts +106 -14
- package/src/index.ts +1 -1
- package/src/keycloak/index.ts +24 -7
- package/src/keycloak/index.webext.ts +16 -0
- package/src/oauth/authorizationUrl.spec.ts +83 -0
- package/src/oauth/authorizationUrl.ts +74 -0
- package/src/oauth/callback.spec.ts +72 -0
- package/src/oauth/callback.ts +46 -0
- package/src/oauth/callbackPage.spec.ts +61 -0
- package/src/oauth/callbackPage.ts +57 -0
- package/src/oauth/endpoints.spec.ts +193 -0
- package/src/oauth/endpoints.ts +135 -0
- package/src/oauth/errors.ts +18 -0
- package/src/oauth/form.spec.ts +35 -0
- package/src/oauth/form.ts +30 -0
- package/src/oauth/idToken.spec.ts +191 -0
- package/src/oauth/idToken.ts +153 -0
- package/src/oauth/index.ts +10 -0
- package/src/oauth/jwt.ts +90 -0
- package/src/oauth/loopbackFlow.spec.ts +226 -0
- package/src/oauth/loopbackFlow.ts +114 -0
- package/src/oauth/pkce.spec.ts +60 -0
- package/src/oauth/pkce.ts +80 -0
- package/src/oauth/tokenExchange.spec.ts +331 -0
- package/src/oauth/tokenExchange.ts +232 -0
- package/src/one.ts +30 -3
- package/src/provider/AfterAuth.tsx +7 -0
- package/src/provider/authProvider/index.native.tsx +37 -4
- package/src/session/index.ts +2 -2
- package/src/state.ts +5 -2
- package/types/betterAuth/client.d.ts +2 -791
- package/types/betterAuth/client.d.ts.map +1 -1
- package/types/betterAuth/expoAuthFlow.native.d.ts +50 -3
- package/types/betterAuth/expoAuthFlow.native.d.ts.map +1 -1
- package/types/frappeToken.d.ts +14 -1
- package/types/frappeToken.d.ts.map +1 -1
- package/types/frappeToken.native.d.ts +16 -2
- package/types/frappeToken.native.d.ts.map +1 -1
- package/types/index.d.ts +1 -1
- package/types/index.d.ts.map +1 -1
- package/types/keycloak/index.d.ts.map +1 -1
- package/types/keycloak/index.webext.d.ts.map +1 -1
- package/types/oauth/authorizationUrl.d.ts +32 -0
- package/types/oauth/authorizationUrl.d.ts.map +1 -0
- package/types/oauth/callback.d.ts +26 -0
- package/types/oauth/callback.d.ts.map +1 -0
- package/types/oauth/callbackPage.d.ts +34 -0
- package/types/oauth/callbackPage.d.ts.map +1 -0
- package/types/oauth/endpoints.d.ts +68 -0
- package/types/oauth/endpoints.d.ts.map +1 -0
- package/types/oauth/errors.d.ts +17 -0
- package/types/oauth/errors.d.ts.map +1 -0
- package/types/oauth/form.d.ts +16 -0
- package/types/oauth/form.d.ts.map +1 -0
- package/types/oauth/idToken.d.ts +83 -0
- package/types/oauth/idToken.d.ts.map +1 -0
- package/types/oauth/index.d.ts +11 -0
- package/types/oauth/index.d.ts.map +1 -0
- package/types/oauth/jwt.d.ts +31 -0
- package/types/oauth/jwt.d.ts.map +1 -0
- package/types/oauth/loopbackFlow.d.ts +64 -0
- package/types/oauth/loopbackFlow.d.ts.map +1 -0
- package/types/oauth/pkce.d.ts +49 -0
- package/types/oauth/pkce.d.ts.map +1 -0
- package/types/oauth/tokenExchange.d.ts +89 -0
- package/types/oauth/tokenExchange.d.ts.map +1 -0
- package/types/one.d.ts +7 -0
- package/types/one.d.ts.map +1 -1
- package/types/provider/AfterAuth.d.ts.map +1 -1
- package/types/provider/authProvider/index.native.d.ts.map +1 -1
- package/types/state.d.ts.map +1 -1
|
@@ -12,9 +12,14 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { useEffect, useMemo, useState } from "react";
|
|
15
|
+
import { AppState, type AppStateStatus } from "react-native";
|
|
15
16
|
import * as Linking from "expo-linking";
|
|
16
17
|
import { Loading } from "../../Loading";
|
|
17
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
createExpoAuthFlow,
|
|
20
|
+
rewriteLoopbackHostForNative,
|
|
21
|
+
} from "../../betterAuth/expoAuthFlow.native";
|
|
22
|
+
import { clearKeycloakBearerToken } from "../../frappeToken.native";
|
|
18
23
|
import { KeycloakConfigContext } from "../../keycloak/config";
|
|
19
24
|
import { Keycloak } from "../../keycloak/index";
|
|
20
25
|
import type { KeycloakLoginOptions, KeycloakLogoutOptions } from "../../keycloak/base";
|
|
@@ -35,8 +40,12 @@ export function AuthProvider({
|
|
|
35
40
|
// Resolve the Better Auth server base URL from keycloak config.
|
|
36
41
|
// On native, the keycloakConfig.url is the Keycloak server — the Better Auth
|
|
37
42
|
// server is the app backend (CreateApp wires BETTER_AUTH_BASE_URL/BASE_URL).
|
|
43
|
+
// Loopback hosts are rewritten for the device (127.0.0.1 / 10.0.2.2): see
|
|
44
|
+
// rewriteLoopbackHostForNative.
|
|
38
45
|
const serverBaseUrl = useMemo(() => {
|
|
39
|
-
return
|
|
46
|
+
return rewriteLoopbackHostForNative(
|
|
47
|
+
keycloakConfig.betterAuthBaseUrl || "http://localhost:8000",
|
|
48
|
+
);
|
|
40
49
|
}, [keycloakConfig]);
|
|
41
50
|
|
|
42
51
|
const scheme = useMemo(() => keycloakConfig.expoScheme, [keycloakConfig]);
|
|
@@ -72,11 +81,24 @@ export function AuthProvider({
|
|
|
72
81
|
// can only receive exp:// redirects (Linking.createURL derives
|
|
73
82
|
// exp://<host>/--/ there; the bare app scheme in dev builds).
|
|
74
83
|
await flow.signIn("keycloak", options.redirectUri || Linking.createURL("/"));
|
|
84
|
+
// Drop any signed-out cooldown/stale token so the first Frappe
|
|
85
|
+
// request after sign-in fetches a fresh Bearer token.
|
|
86
|
+
clearKeycloakBearerToken();
|
|
75
87
|
await refresh();
|
|
76
88
|
return undefined;
|
|
77
89
|
},
|
|
78
|
-
async (
|
|
79
|
-
|
|
90
|
+
async (options: KeycloakLogoutOptions) => {
|
|
91
|
+
// Single sign-out: ends the Better Auth session AND rides the
|
|
92
|
+
// Keycloak end-session endpoint through the system browser (see
|
|
93
|
+
// expoAuthFlow.signOut). Only custom-scheme URLs make sense as the
|
|
94
|
+
// post-logout return on native; web-style paths fall back to the
|
|
95
|
+
// app's own runtime URL.
|
|
96
|
+
const redirectUri =
|
|
97
|
+
options.redirectUri && options.redirectUri.includes("://")
|
|
98
|
+
? options.redirectUri
|
|
99
|
+
: Linking.createURL("/");
|
|
100
|
+
await flow.signOut(redirectUri);
|
|
101
|
+
clearKeycloakBearerToken();
|
|
80
102
|
await refresh();
|
|
81
103
|
return undefined;
|
|
82
104
|
},
|
|
@@ -105,8 +127,19 @@ export function AuthProvider({
|
|
|
105
127
|
refresh().finally(() => {
|
|
106
128
|
if (alive) setIsLoading(false);
|
|
107
129
|
});
|
|
130
|
+
|
|
131
|
+
// Re-probe when the app returns to the foreground: covers a completed
|
|
132
|
+
// ASWebAuthenticationSession whose Linking event arrived after dismiss,
|
|
133
|
+
// and a user who abandoned the end-session page (local jar already
|
|
134
|
+
// empty; this just refreshes the header).
|
|
135
|
+
const onAppState = (next: AppStateStatus) => {
|
|
136
|
+
if (next === "active") refresh().catch(() => undefined);
|
|
137
|
+
};
|
|
138
|
+
const appSub = AppState.addEventListener("change", onAppState);
|
|
139
|
+
|
|
108
140
|
return () => {
|
|
109
141
|
alive = false;
|
|
142
|
+
appSub.remove();
|
|
110
143
|
};
|
|
111
144
|
}, [disabled, flow, keycloakConfig]);
|
|
112
145
|
|
package/src/session/index.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Replaces the previous next-auth/react useSession.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { isBrowser
|
|
9
|
+
import { isBrowser } from "@multiplatform.one/platform";
|
|
10
10
|
import { getAuthClient } from "../betterAuth/client";
|
|
11
11
|
|
|
12
12
|
export interface Session {
|
|
@@ -37,7 +37,7 @@ let useSession = <R extends boolean = false>(
|
|
|
37
37
|
return { session: null, status: "unauthenticated" };
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
if (isBrowser
|
|
40
|
+
if (isBrowser) {
|
|
41
41
|
useSession = <R extends boolean = false>(
|
|
42
42
|
_options?: Record<string, unknown>,
|
|
43
43
|
): SessionContextValue<R> => {
|
package/src/state.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { createStore, useStore } from "@multiplatform.one/store";
|
|
2
|
-
import { isBrowser, isIframe, isServer
|
|
2
|
+
import { isBrowser, isIframe, isServer } from "@multiplatform.one/platform";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// Browsers keep the session in a Better Auth cookie, so nothing to persist.
|
|
5
|
+
// Everywhere else (iframes fed tokens by a parent, native, and the GNOME/GJS
|
|
6
|
+
// target) the tokens are the only session there is.
|
|
7
|
+
export const persist = isIframe || (!isBrowser && !isServer);
|
|
5
8
|
|
|
6
9
|
export interface AuthTokenState {
|
|
7
10
|
idToken: string;
|