@multiplatform.one/keycloak 7.34.3 → 7.35.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 +120 -70
- package/dist/cjs/index.native.cjs +283 -148
- package/dist/esm/index.js +78 -28
- package/dist/esm/index.native.js +270 -135
- package/package.json +9 -9
- package/src/betterAuth/expoAuthFlow.deadline.spec.ts +230 -0
- package/src/betterAuth/expoAuthFlow.native.ts +67 -27
- package/src/keycloak/base.ts +3 -2
- package/src/keycloak/context.ts +2 -2
- package/src/keycloak/index.ts +26 -13
- package/src/keycloak/login.error.spec.tsx +85 -0
- package/src/provider/KeycloakProvider.loading.spec.tsx +37 -0
- package/src/provider/KeycloakProvider.tsx +16 -9
- package/src/provider/authProvider/index.native.tsx +170 -108
- package/src/provider/authProvider/nonblocking.native.spec.tsx +303 -0
- package/src/session/authError.ts +30 -0
- package/src/session/index.native.ts +6 -1
- package/src/session/index.ts +11 -4
- package/types/betterAuth/expoAuthFlow.native.d.ts +3 -1
- package/types/betterAuth/expoAuthFlow.native.d.ts.map +1 -1
- package/types/keycloak/base.d.ts +1 -1
- package/types/keycloak/base.d.ts.map +1 -1
- package/types/keycloak/context.d.ts +2 -2
- package/types/keycloak/context.d.ts.map +1 -1
- package/types/keycloak/index.d.ts +1 -1
- package/types/keycloak/index.d.ts.map +1 -1
- package/types/keycloak/index.native.d.ts +1 -1
- package/types/keycloak/index.native.d.ts.map +1 -1
- package/types/keycloak/index.webext.d.ts +1 -1
- package/types/keycloak/index.webext.d.ts.map +1 -1
- package/types/provider/KeycloakProvider.d.ts +3 -2
- package/types/provider/KeycloakProvider.d.ts.map +1 -1
- package/types/provider/authProvider/index.native.d.ts +1 -1
- package/types/provider/authProvider/index.native.d.ts.map +1 -1
- package/types/session/authError.d.ts +7 -0
- package/types/session/authError.d.ts.map +1 -0
- package/types/session/index.d.ts +2 -0
- package/types/session/index.d.ts.map +1 -1
- package/types/session/index.native.d.ts +1 -0
- package/types/session/index.native.d.ts.map +1 -1
package/dist/esm/index.native.js
CHANGED
|
@@ -482,8 +482,9 @@ var BaseKeycloak = class {
|
|
|
482
482
|
this._clear();
|
|
483
483
|
if (this._keycloakClient) {
|
|
484
484
|
await this._keycloakClient.login(options);
|
|
485
|
-
} else {
|
|
486
|
-
await this._login
|
|
485
|
+
} else if (this._login) {
|
|
486
|
+
await this._login(options);
|
|
487
|
+
return;
|
|
487
488
|
}
|
|
488
489
|
this._sync();
|
|
489
490
|
}
|
|
@@ -673,6 +674,32 @@ async function requestAccessToken(providerId, send, userId) {
|
|
|
673
674
|
return second;
|
|
674
675
|
}
|
|
675
676
|
|
|
677
|
+
// src/session/authError.ts
|
|
678
|
+
import { useSyncExternalStore } from "react";
|
|
679
|
+
var error;
|
|
680
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
681
|
+
var AuthTimeoutError = class extends Error {
|
|
682
|
+
constructor(timeoutMs = 1e4) {
|
|
683
|
+
super(`Authentication request timed out after ${timeoutMs}ms`);
|
|
684
|
+
this.name = "AuthTimeoutError";
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
function setAuthError(next) {
|
|
688
|
+
if (error === next) return;
|
|
689
|
+
error = next;
|
|
690
|
+
for (const listener of listeners) listener();
|
|
691
|
+
}
|
|
692
|
+
function getAuthError() {
|
|
693
|
+
return error;
|
|
694
|
+
}
|
|
695
|
+
function subscribe(listener) {
|
|
696
|
+
listeners.add(listener);
|
|
697
|
+
return () => listeners.delete(listener);
|
|
698
|
+
}
|
|
699
|
+
function useAuthError() {
|
|
700
|
+
return useSyncExternalStore(subscribe, getAuthError, getAuthError);
|
|
701
|
+
}
|
|
702
|
+
|
|
676
703
|
// src/betterAuth/expoAuthFlow.native.ts
|
|
677
704
|
try {
|
|
678
705
|
WebBrowser.maybeCompleteAuthSession?.();
|
|
@@ -813,24 +840,50 @@ var activeFlow = null;
|
|
|
813
840
|
function getActiveExpoAuthFlow() {
|
|
814
841
|
return activeFlow;
|
|
815
842
|
}
|
|
816
|
-
function createExpoAuthFlow(baseURL, scheme) {
|
|
843
|
+
function createExpoAuthFlow(baseURL, scheme, options) {
|
|
817
844
|
const base = baseURL.replace(/\/$/, "");
|
|
818
845
|
const origin = () => Linking.createURL("/", scheme ? { scheme } : void 0);
|
|
819
846
|
async function authFetch(path, init) {
|
|
820
|
-
const
|
|
821
|
-
const
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
"x-skip-oauth-proxy": "true",
|
|
829
|
-
...init?.headers
|
|
830
|
-
}
|
|
847
|
+
const controller = new AbortController();
|
|
848
|
+
const timeoutMs = options?.timeoutMs ?? 1e4;
|
|
849
|
+
let timer;
|
|
850
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
851
|
+
timer = setTimeout(() => {
|
|
852
|
+
reject(new AuthTimeoutError(timeoutMs));
|
|
853
|
+
controller.abort();
|
|
854
|
+
}, timeoutMs);
|
|
831
855
|
});
|
|
832
|
-
|
|
833
|
-
|
|
856
|
+
try {
|
|
857
|
+
const buffered = await Promise.race([
|
|
858
|
+
(async () => {
|
|
859
|
+
const cookie = cookieHeader();
|
|
860
|
+
const response = await fetch(`${base}/api/auth${path}`, {
|
|
861
|
+
...init,
|
|
862
|
+
signal: controller.signal,
|
|
863
|
+
credentials: "omit",
|
|
864
|
+
headers: {
|
|
865
|
+
"Content-Type": "application/json",
|
|
866
|
+
...cookie ? { cookie } : {},
|
|
867
|
+
"expo-origin": origin(),
|
|
868
|
+
"x-skip-oauth-proxy": "true",
|
|
869
|
+
...init?.headers
|
|
870
|
+
}
|
|
871
|
+
});
|
|
872
|
+
const text = await response.text();
|
|
873
|
+
return { response, text };
|
|
874
|
+
})(),
|
|
875
|
+
deadline
|
|
876
|
+
]);
|
|
877
|
+
absorbSetCookie(buffered.response.headers.get("set-cookie"));
|
|
878
|
+
return {
|
|
879
|
+
status: buffered.response.status,
|
|
880
|
+
ok: buffered.response.ok,
|
|
881
|
+
text: buffered.text,
|
|
882
|
+
json: () => buffered.text.trim() ? JSON.parse(buffered.text) : null
|
|
883
|
+
};
|
|
884
|
+
} finally {
|
|
885
|
+
clearTimeout(timer);
|
|
886
|
+
}
|
|
834
887
|
}
|
|
835
888
|
const flow = {
|
|
836
889
|
async signIn(provider, callbackURL) {
|
|
@@ -840,10 +893,10 @@ function createExpoAuthFlow(baseURL, scheme) {
|
|
|
840
893
|
body: JSON.stringify({ provider, callbackURL: to })
|
|
841
894
|
});
|
|
842
895
|
if (!res.ok) {
|
|
843
|
-
const body =
|
|
896
|
+
const body = res.text;
|
|
844
897
|
throw new Error(`sign-in failed (${res.status}): ${body.slice(0, 200)}`);
|
|
845
898
|
}
|
|
846
|
-
const data =
|
|
899
|
+
const data = res.json();
|
|
847
900
|
if (!data?.url) throw new Error("sign-in response had no authorization url");
|
|
848
901
|
const params = new URLSearchParams({ authorizationURL: data.url });
|
|
849
902
|
const oauthState = getOAuthState();
|
|
@@ -862,28 +915,31 @@ function createExpoAuthFlow(baseURL, scheme) {
|
|
|
862
915
|
postLogoutRedirectUri || Linking.createURL("/"),
|
|
863
916
|
"signed-out"
|
|
864
917
|
);
|
|
918
|
+
let missingSso = false;
|
|
865
919
|
try {
|
|
866
920
|
const res = await authFetch(
|
|
867
921
|
`/sign-out/sso?mode=json&callbackURL=${encodeURIComponent(to)}`,
|
|
868
922
|
{ method: "GET" }
|
|
869
923
|
);
|
|
924
|
+
missingSso = res.status === 404 || res.status === 405;
|
|
870
925
|
if (!res.ok) throw new Error(`sign-out/sso failed (${res.status})`);
|
|
871
|
-
const data =
|
|
926
|
+
const data = res.json();
|
|
872
927
|
if (data?.redirect && data.url) {
|
|
873
|
-
await openAuthBrowser(data.url, to.split("?")[0], { timeoutMs: 12e4 })
|
|
874
|
-
() => void 0
|
|
875
|
-
);
|
|
928
|
+
await openAuthBrowser(data.url, to.split("?")[0], { timeoutMs: 12e4 });
|
|
876
929
|
}
|
|
877
|
-
} catch {
|
|
878
|
-
await authFetch("/sign-out", { method: "POST", body: "{}" })
|
|
930
|
+
} catch (error2) {
|
|
931
|
+
const fallback = await authFetch("/sign-out", { method: "POST", body: "{}" });
|
|
932
|
+
if (!fallback.ok) throw new Error(`sign-out failed (${fallback.status})`);
|
|
933
|
+
if (!missingSso) throw error2;
|
|
879
934
|
} finally {
|
|
880
935
|
writeJar({});
|
|
881
936
|
}
|
|
882
937
|
},
|
|
883
938
|
async getSession() {
|
|
884
939
|
const res = await authFetch("/get-session");
|
|
885
|
-
if (
|
|
886
|
-
|
|
940
|
+
if (res.status === 401) return null;
|
|
941
|
+
if (!res.ok) throw new Error(`get-session failed (${res.status})`);
|
|
942
|
+
const data = res.json();
|
|
887
943
|
return data && Object.keys(data).length ? data : null;
|
|
888
944
|
},
|
|
889
945
|
async getAccessToken(providerId) {
|
|
@@ -893,7 +949,15 @@ function createExpoAuthFlow(baseURL, scheme) {
|
|
|
893
949
|
method: "POST",
|
|
894
950
|
body: JSON.stringify(body)
|
|
895
951
|
});
|
|
896
|
-
|
|
952
|
+
if (response.status >= 500) {
|
|
953
|
+
throw new Error(`get-access-token failed (${response.status})`);
|
|
954
|
+
}
|
|
955
|
+
try {
|
|
956
|
+
payload = response.json();
|
|
957
|
+
} catch (error2) {
|
|
958
|
+
if (response.ok) throw error2;
|
|
959
|
+
payload = null;
|
|
960
|
+
}
|
|
897
961
|
return { status: response.status, body: payload };
|
|
898
962
|
});
|
|
899
963
|
if (res.status < 200 || res.status >= 300) return null;
|
|
@@ -1014,139 +1078,200 @@ import { useEffect as useEffect3, useMemo, useState } from "react";
|
|
|
1014
1078
|
import { AppState as AppState2 } from "react-native";
|
|
1015
1079
|
import * as Linking2 from "expo-linking";
|
|
1016
1080
|
|
|
1017
|
-
// src/Loading.tsx
|
|
1018
|
-
import { ActivityIndicator, Text as Text2, View } from "react-native";
|
|
1019
|
-
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
1020
|
-
function Loading({ loadingComponent }) {
|
|
1021
|
-
const { debug } = useAuthConfig();
|
|
1022
|
-
const LoadingComponent = loadingComponent;
|
|
1023
|
-
if (typeof LoadingComponent === "undefined") {
|
|
1024
|
-
return /* @__PURE__ */ jsxs(View, { style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: [
|
|
1025
|
-
/* @__PURE__ */ jsx3(ActivityIndicator, {}),
|
|
1026
|
-
debug ? /* @__PURE__ */ jsx3(Text2, { children: "loading" }) : null
|
|
1027
|
-
] });
|
|
1028
|
-
}
|
|
1029
|
-
return /* @__PURE__ */ jsx3(LoadingComponent, {});
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
1081
|
// src/session/index.native.ts
|
|
1033
|
-
import { useSyncExternalStore } from "react";
|
|
1082
|
+
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
1034
1083
|
var state = { session: null, status: "loading" };
|
|
1035
|
-
var
|
|
1084
|
+
var listeners2 = /* @__PURE__ */ new Set();
|
|
1036
1085
|
function setNativeSession(session, status) {
|
|
1037
1086
|
state = {
|
|
1038
1087
|
session,
|
|
1039
1088
|
status: status ?? (session?.user ? "authenticated" : "unauthenticated")
|
|
1040
1089
|
};
|
|
1041
|
-
for (const l of
|
|
1090
|
+
for (const l of listeners2) l();
|
|
1042
1091
|
}
|
|
1043
|
-
function
|
|
1044
|
-
|
|
1045
|
-
return () =>
|
|
1092
|
+
function subscribe2(listener) {
|
|
1093
|
+
listeners2.add(listener);
|
|
1094
|
+
return () => listeners2.delete(listener);
|
|
1046
1095
|
}
|
|
1047
1096
|
async function getSession() {
|
|
1048
1097
|
return state.session;
|
|
1049
1098
|
}
|
|
1050
1099
|
function useSession(_options) {
|
|
1051
|
-
|
|
1052
|
-
|
|
1100
|
+
const session = useSyncExternalStore2(
|
|
1101
|
+
subscribe2,
|
|
1053
1102
|
() => state,
|
|
1054
1103
|
() => state
|
|
1055
1104
|
);
|
|
1105
|
+
const error2 = useAuthError();
|
|
1106
|
+
return { ...session, error: error2 };
|
|
1056
1107
|
}
|
|
1057
1108
|
|
|
1058
1109
|
// src/provider/authProvider/index.native.tsx
|
|
1059
|
-
import { Fragment as Fragment3, jsx as
|
|
1110
|
+
import { Fragment as Fragment3, jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
1111
|
+
function createController(config, disabled, notify) {
|
|
1112
|
+
const flow = disabled ? null : createExpoAuthFlow(
|
|
1113
|
+
rewriteLoopbackHostForNative(config.betterAuthBaseUrl || "http://localhost:8000"),
|
|
1114
|
+
config.expoScheme
|
|
1115
|
+
);
|
|
1116
|
+
let active = true;
|
|
1117
|
+
let sequence = 0;
|
|
1118
|
+
let interactive = false;
|
|
1119
|
+
let session = null;
|
|
1120
|
+
const current = (request) => active && request === sequence;
|
|
1121
|
+
const controller = {
|
|
1122
|
+
keycloak: makeKeycloak(null),
|
|
1123
|
+
loading: !disabled,
|
|
1124
|
+
start() {
|
|
1125
|
+
active = true;
|
|
1126
|
+
if (!flow) {
|
|
1127
|
+
publish(null);
|
|
1128
|
+
} else if (!interactive) {
|
|
1129
|
+
void refresh().catch(() => void 0);
|
|
1130
|
+
}
|
|
1131
|
+
},
|
|
1132
|
+
stop() {
|
|
1133
|
+
active = false;
|
|
1134
|
+
sequence++;
|
|
1135
|
+
interactive = false;
|
|
1136
|
+
},
|
|
1137
|
+
refresh
|
|
1138
|
+
};
|
|
1139
|
+
function makeKeycloak(next) {
|
|
1140
|
+
const keycloak = new Keycloak(config, void 0, void 0, void 0, login, logout);
|
|
1141
|
+
if (next?.user) {
|
|
1142
|
+
keycloak.authenticated = true;
|
|
1143
|
+
keycloak.subject = next.user.id;
|
|
1144
|
+
keycloak.email = next.user.email ?? void 0;
|
|
1145
|
+
keycloak.username = next.user.name ?? void 0;
|
|
1146
|
+
}
|
|
1147
|
+
return keycloak;
|
|
1148
|
+
}
|
|
1149
|
+
function publish(next, error2) {
|
|
1150
|
+
session = next;
|
|
1151
|
+
controller.keycloak = makeKeycloak(next);
|
|
1152
|
+
controller.loading = false;
|
|
1153
|
+
setAuthError(error2);
|
|
1154
|
+
setNativeSession(next);
|
|
1155
|
+
notify();
|
|
1156
|
+
}
|
|
1157
|
+
function begin() {
|
|
1158
|
+
const request = ++sequence;
|
|
1159
|
+
controller.loading = true;
|
|
1160
|
+
setAuthError();
|
|
1161
|
+
setNativeSession(session, "loading");
|
|
1162
|
+
notify();
|
|
1163
|
+
return request;
|
|
1164
|
+
}
|
|
1165
|
+
async function probe(request) {
|
|
1166
|
+
const next = await flow.getSession();
|
|
1167
|
+
if (!current(request)) return;
|
|
1168
|
+
publish(
|
|
1169
|
+
next?.user ? {
|
|
1170
|
+
user: {
|
|
1171
|
+
id: next.user.id,
|
|
1172
|
+
name: next.user.name ?? null,
|
|
1173
|
+
email: next.user.email ?? null
|
|
1174
|
+
}
|
|
1175
|
+
} : null
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
1178
|
+
function fail(request, cause) {
|
|
1179
|
+
const error2 = cause instanceof Error ? cause : new Error(String(cause));
|
|
1180
|
+
if (current(request)) publish(null, error2);
|
|
1181
|
+
throw error2;
|
|
1182
|
+
}
|
|
1183
|
+
async function refresh() {
|
|
1184
|
+
if (!active || !flow || interactive) return;
|
|
1185
|
+
const request = begin();
|
|
1186
|
+
try {
|
|
1187
|
+
await probe(request);
|
|
1188
|
+
} catch (error2) {
|
|
1189
|
+
fail(request, error2);
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
async function login(options) {
|
|
1193
|
+
if (!active || !flow) return void 0;
|
|
1194
|
+
interactive = true;
|
|
1195
|
+
const request = begin();
|
|
1196
|
+
try {
|
|
1197
|
+
await flow.signIn("keycloak", options.redirectUri || Linking2.createURL("/"));
|
|
1198
|
+
if (!current(request)) return void 0;
|
|
1199
|
+
clearKeycloakBearerToken();
|
|
1200
|
+
await probe(request);
|
|
1201
|
+
} catch (error2) {
|
|
1202
|
+
fail(request, error2);
|
|
1203
|
+
} finally {
|
|
1204
|
+
if (current(request)) interactive = false;
|
|
1205
|
+
}
|
|
1206
|
+
return void 0;
|
|
1207
|
+
}
|
|
1208
|
+
async function logout(options) {
|
|
1209
|
+
if (!active || !flow) return void 0;
|
|
1210
|
+
interactive = true;
|
|
1211
|
+
const request = ++sequence;
|
|
1212
|
+
clearKeycloakBearerToken();
|
|
1213
|
+
publish(null);
|
|
1214
|
+
try {
|
|
1215
|
+
const redirectUri = options.redirectUri?.includes("://") ? options.redirectUri : Linking2.createURL("/");
|
|
1216
|
+
await flow.signOut(redirectUri);
|
|
1217
|
+
} catch (error2) {
|
|
1218
|
+
fail(request, error2);
|
|
1219
|
+
} finally {
|
|
1220
|
+
if (current(request)) {
|
|
1221
|
+
clearKeycloakBearerToken();
|
|
1222
|
+
interactive = false;
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
return void 0;
|
|
1226
|
+
}
|
|
1227
|
+
return controller;
|
|
1228
|
+
}
|
|
1060
1229
|
function AuthProvider({
|
|
1061
1230
|
children,
|
|
1062
1231
|
disabled,
|
|
1063
1232
|
keycloakConfig,
|
|
1064
|
-
loadingComponent
|
|
1233
|
+
loadingComponent: LoadingComponent
|
|
1065
1234
|
}) {
|
|
1066
|
-
const [
|
|
1067
|
-
const
|
|
1068
|
-
const
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1235
|
+
const [, setRevision] = useState(0);
|
|
1236
|
+
const { url, realm, clientId, publicClientId, betterAuthBaseUrl, expoScheme } = keycloakConfig;
|
|
1237
|
+
const scopes = JSON.stringify(keycloakConfig.scopes);
|
|
1238
|
+
const controller = useMemo(
|
|
1239
|
+
() => createController(
|
|
1240
|
+
{
|
|
1241
|
+
url,
|
|
1242
|
+
realm,
|
|
1243
|
+
clientId,
|
|
1244
|
+
publicClientId,
|
|
1245
|
+
betterAuthBaseUrl,
|
|
1246
|
+
expoScheme,
|
|
1247
|
+
scopes: scopes ? JSON.parse(scopes) : void 0
|
|
1248
|
+
},
|
|
1249
|
+
disabled,
|
|
1250
|
+
() => setRevision((revision) => revision + 1)
|
|
1251
|
+
),
|
|
1252
|
+
[url, realm, clientId, publicClientId, betterAuthBaseUrl, expoScheme, scopes, disabled]
|
|
1077
1253
|
);
|
|
1078
1254
|
useEffect3(() => {
|
|
1079
|
-
if (disabled
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
let alive = true;
|
|
1084
|
-
const refresh = async () => {
|
|
1085
|
-
let session = null;
|
|
1086
|
-
try {
|
|
1087
|
-
session = await flow.getSession();
|
|
1088
|
-
} catch (err) {
|
|
1089
|
-
console.error("[keycloak] native session check failed:", err);
|
|
1090
|
-
}
|
|
1091
|
-
const _keycloak = new Keycloak(
|
|
1092
|
-
keycloakConfig,
|
|
1093
|
-
void 0,
|
|
1094
|
-
void 0,
|
|
1095
|
-
void 0,
|
|
1096
|
-
async (options) => {
|
|
1097
|
-
await flow.signIn("keycloak", options.redirectUri || Linking2.createURL("/"));
|
|
1098
|
-
clearKeycloakBearerToken();
|
|
1099
|
-
await refresh();
|
|
1100
|
-
return void 0;
|
|
1101
|
-
},
|
|
1102
|
-
async (options) => {
|
|
1103
|
-
const redirectUri = options.redirectUri && options.redirectUri.includes("://") ? options.redirectUri : Linking2.createURL("/");
|
|
1104
|
-
await flow.signOut(redirectUri);
|
|
1105
|
-
clearKeycloakBearerToken();
|
|
1106
|
-
await refresh();
|
|
1107
|
-
return void 0;
|
|
1108
|
-
}
|
|
1109
|
-
);
|
|
1110
|
-
if (session?.user) {
|
|
1111
|
-
_keycloak.authenticated = true;
|
|
1112
|
-
_keycloak.email = session.user.email || void 0;
|
|
1113
|
-
_keycloak.username = session.user.name || void 0;
|
|
1114
|
-
_keycloak.subject = session.user.id;
|
|
1115
|
-
}
|
|
1116
|
-
if (!alive) return;
|
|
1117
|
-
setNativeSession(
|
|
1118
|
-
session?.user ? {
|
|
1119
|
-
user: {
|
|
1120
|
-
id: session.user.id,
|
|
1121
|
-
name: session.user.name ?? null,
|
|
1122
|
-
email: session.user.email ?? null
|
|
1123
|
-
}
|
|
1124
|
-
} : null
|
|
1125
|
-
);
|
|
1126
|
-
setKeycloak(_keycloak);
|
|
1127
|
-
};
|
|
1128
|
-
refresh().finally(() => {
|
|
1129
|
-
if (alive) setIsLoading(false);
|
|
1255
|
+
if (disabled) return;
|
|
1256
|
+
controller.start();
|
|
1257
|
+
const appSub = AppState2.addEventListener("change", (next) => {
|
|
1258
|
+
if (next === "active") void controller.refresh().catch(() => void 0);
|
|
1130
1259
|
});
|
|
1131
|
-
const onAppState = (next) => {
|
|
1132
|
-
if (next === "active") refresh().catch(() => void 0);
|
|
1133
|
-
};
|
|
1134
|
-
const appSub = AppState2.addEventListener("change", onAppState);
|
|
1135
1260
|
return () => {
|
|
1136
|
-
|
|
1261
|
+
controller.stop();
|
|
1137
1262
|
appSub.remove();
|
|
1138
1263
|
};
|
|
1139
|
-
}, [
|
|
1140
|
-
if (disabled) return /* @__PURE__ */
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1264
|
+
}, [controller, disabled]);
|
|
1265
|
+
if (disabled) return /* @__PURE__ */ jsx3(Fragment3, { children });
|
|
1266
|
+
return /* @__PURE__ */ jsx3(KeycloakConfigContext.Provider, { value: controller.keycloak.config, children: /* @__PURE__ */ jsxs(KeycloakContext.Provider, { value: controller.keycloak, children: [
|
|
1267
|
+
/* @__PURE__ */ jsx3(AfterAuth, { children }),
|
|
1268
|
+
controller.loading && LoadingComponent ? /* @__PURE__ */ jsx3(LoadingComponent, {}) : null
|
|
1269
|
+
] }) });
|
|
1145
1270
|
}
|
|
1146
1271
|
|
|
1147
1272
|
// src/provider/KeycloakProvider.tsx
|
|
1148
1273
|
import { useMemo as useMemo2 } from "react";
|
|
1149
|
-
import { jsx as
|
|
1274
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
1150
1275
|
function KeycloakProvider({
|
|
1151
1276
|
baseUrl,
|
|
1152
1277
|
betterAuthBaseUrl,
|
|
@@ -1154,6 +1279,7 @@ function KeycloakProvider({
|
|
|
1154
1279
|
clientId,
|
|
1155
1280
|
expoScheme,
|
|
1156
1281
|
loginRedirectUri,
|
|
1282
|
+
loadingComponent,
|
|
1157
1283
|
debug,
|
|
1158
1284
|
disabled,
|
|
1159
1285
|
iframeSso,
|
|
@@ -1164,18 +1290,23 @@ function KeycloakProvider({
|
|
|
1164
1290
|
() => ({ debug, disabled, iframeSso, loginRedirectUri }),
|
|
1165
1291
|
[debug, disabled, iframeSso, loginRedirectUri]
|
|
1166
1292
|
);
|
|
1167
|
-
|
|
1293
|
+
const keycloakConfig = useMemo2(
|
|
1294
|
+
() => ({
|
|
1295
|
+
clientId: clientId || "app",
|
|
1296
|
+
publicClientId,
|
|
1297
|
+
realm: realm || "main",
|
|
1298
|
+
url: baseUrl ?? "",
|
|
1299
|
+
betterAuthBaseUrl,
|
|
1300
|
+
expoScheme
|
|
1301
|
+
}),
|
|
1302
|
+
[clientId, publicClientId, realm, baseUrl, betterAuthBaseUrl, expoScheme]
|
|
1303
|
+
);
|
|
1304
|
+
return /* @__PURE__ */ jsx4(AuthConfigContext.Provider, { value: authConfig, children: /* @__PURE__ */ jsx4(
|
|
1168
1305
|
AuthProvider,
|
|
1169
1306
|
{
|
|
1170
1307
|
disabled,
|
|
1171
|
-
keycloakConfig
|
|
1172
|
-
|
|
1173
|
-
publicClientId,
|
|
1174
|
-
realm: realm || "main",
|
|
1175
|
-
url: baseUrl ?? "",
|
|
1176
|
-
betterAuthBaseUrl,
|
|
1177
|
-
expoScheme
|
|
1178
|
-
},
|
|
1308
|
+
keycloakConfig,
|
|
1309
|
+
loadingComponent,
|
|
1179
1310
|
children
|
|
1180
1311
|
}
|
|
1181
1312
|
) });
|
|
@@ -1184,6 +1315,7 @@ export {
|
|
|
1184
1315
|
AfterAuth,
|
|
1185
1316
|
AuthConfigContext,
|
|
1186
1317
|
AuthProvider,
|
|
1318
|
+
AuthTimeoutError,
|
|
1187
1319
|
Authenticated,
|
|
1188
1320
|
BaseKeycloak,
|
|
1189
1321
|
Keycloak,
|
|
@@ -1191,14 +1323,17 @@ export {
|
|
|
1191
1323
|
KeycloakProvider,
|
|
1192
1324
|
defaultAuthConfig,
|
|
1193
1325
|
getAllWalletAddresses,
|
|
1326
|
+
getAuthError,
|
|
1194
1327
|
getKeycloakBearerToken,
|
|
1195
1328
|
getSession,
|
|
1196
1329
|
getWalletAddresses,
|
|
1197
1330
|
getWalletsFromToken,
|
|
1198
1331
|
hasWallets,
|
|
1199
1332
|
isTokenExpired,
|
|
1333
|
+
setAuthError,
|
|
1200
1334
|
setNativeSession,
|
|
1201
1335
|
useAuthConfig,
|
|
1336
|
+
useAuthError,
|
|
1202
1337
|
useKeycloak,
|
|
1203
1338
|
useSession,
|
|
1204
1339
|
useTokensFromQuery,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplatform.one/keycloak",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.35.0",
|
|
4
4
|
"description": "keycloak client for multiplatform.one ecosystem",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"auth",
|
|
@@ -57,16 +57,16 @@
|
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@better-auth/expo": "~1.6.33",
|
|
60
|
-
"@multiplatform.one/keycloak-js": "^7.
|
|
61
|
-
"@multiplatform.one/store": "^7.
|
|
60
|
+
"@multiplatform.one/keycloak-js": "^7.35.0",
|
|
61
|
+
"@multiplatform.one/store": "^7.35.0",
|
|
62
62
|
"better-auth": "~1.6.33",
|
|
63
63
|
"jwt-decode": "^4.0.0"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@multiplatform.one/config": "7.
|
|
67
|
-
"@multiplatform.one/logger": "7.
|
|
68
|
-
"@multiplatform.one/platform": "7.
|
|
69
|
-
"@multiplatform.one/test-utils": "7.
|
|
66
|
+
"@multiplatform.one/config": "7.35.0",
|
|
67
|
+
"@multiplatform.one/logger": "7.35.0",
|
|
68
|
+
"@multiplatform.one/platform": "7.35.0",
|
|
69
|
+
"@multiplatform.one/test-utils": "7.35.0",
|
|
70
70
|
"@tamagui/build": "2.7.6",
|
|
71
71
|
"@testing-library/jest-dom": "^7.0.1",
|
|
72
72
|
"@testing-library/react": "^16.3.3",
|
|
@@ -80,8 +80,8 @@
|
|
|
80
80
|
"vitest": "^4.1.5"
|
|
81
81
|
},
|
|
82
82
|
"peerDependencies": {
|
|
83
|
-
"@multiplatform.one/logger": "^7.
|
|
84
|
-
"@multiplatform.one/platform": "^7.
|
|
83
|
+
"@multiplatform.one/logger": "^7.35.0",
|
|
84
|
+
"@multiplatform.one/platform": "^7.35.0",
|
|
85
85
|
"react": "^19.1.0",
|
|
86
86
|
"react-native": ">=0.83.0"
|
|
87
87
|
},
|