oidc-spa 8.1.10 → 8.1.12

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 (186) hide show
  1. package/backend.d.ts +27 -6
  2. package/backend.js +124 -139
  3. package/backend.js.map +1 -1
  4. package/core/Oidc.d.ts +28 -4
  5. package/core/createOidc.d.ts +12 -3
  6. package/core/createOidc.js +1 -1
  7. package/core/createOidc.js.map +1 -1
  8. package/core/earlyInit.d.ts +1 -0
  9. package/core/earlyInit.js +11 -4
  10. package/core/earlyInit.js.map +1 -1
  11. package/core/loginOrGoToAuthServer.js +8 -3
  12. package/core/loginOrGoToAuthServer.js.map +1 -1
  13. package/core/oidcClientTsUserToTokens.d.ts +1 -1
  14. package/core/oidcClientTsUserToTokens.js.map +1 -1
  15. package/core/requiredPostHydrationReplaceNavigationUrl.d.ts +6 -0
  16. package/core/requiredPostHydrationReplaceNavigationUrl.js +12 -0
  17. package/core/requiredPostHydrationReplaceNavigationUrl.js.map +1 -0
  18. package/entrypoint.d.ts +1 -0
  19. package/entrypoint.js +3 -1
  20. package/entrypoint.js.map +1 -1
  21. package/esm/angular.d.ts +14 -4
  22. package/esm/angular.js +155 -10
  23. package/esm/angular.js.map +1 -1
  24. package/esm/backend.d.ts +48 -0
  25. package/esm/backend.js +259 -0
  26. package/esm/backend.js.map +1 -0
  27. package/esm/core/Oidc.d.ts +28 -4
  28. package/esm/core/createOidc.d.ts +12 -3
  29. package/esm/core/createOidc.js +1 -1
  30. package/esm/core/createOidc.js.map +1 -1
  31. package/esm/core/earlyInit.d.ts +1 -0
  32. package/esm/core/earlyInit.js +11 -4
  33. package/esm/core/earlyInit.js.map +1 -1
  34. package/esm/core/loginOrGoToAuthServer.js +8 -3
  35. package/esm/core/loginOrGoToAuthServer.js.map +1 -1
  36. package/esm/core/oidcClientTsUserToTokens.d.ts +1 -1
  37. package/esm/core/oidcClientTsUserToTokens.js.map +1 -1
  38. package/esm/core/requiredPostHydrationReplaceNavigationUrl.d.ts +6 -0
  39. package/esm/core/requiredPostHydrationReplaceNavigationUrl.js +8 -0
  40. package/esm/core/requiredPostHydrationReplaceNavigationUrl.js.map +1 -0
  41. package/esm/entrypoint.d.ts +1 -0
  42. package/esm/entrypoint.js +1 -0
  43. package/esm/entrypoint.js.map +1 -1
  44. package/esm/mock/oidc.d.ts +1 -1
  45. package/esm/mock/oidc.js.map +1 -1
  46. package/esm/react/react.d.ts +1 -1
  47. package/esm/tanstack-start/react/accessTokenValidation_rfc9068.d.ts +12 -0
  48. package/esm/tanstack-start/react/accessTokenValidation_rfc9068.js +95 -0
  49. package/esm/tanstack-start/react/accessTokenValidation_rfc9068.js.map +1 -0
  50. package/esm/tanstack-start/react/apiBuilder.d.ts +27 -0
  51. package/esm/tanstack-start/react/apiBuilder.js +58 -0
  52. package/esm/tanstack-start/react/apiBuilder.js.map +1 -0
  53. package/esm/tanstack-start/react/createOidcSpaApi.d.ts +9 -0
  54. package/esm/tanstack-start/react/createOidcSpaApi.js +679 -0
  55. package/esm/tanstack-start/react/createOidcSpaApi.js.map +1 -0
  56. package/esm/tanstack-start/react/index.d.ts +3 -0
  57. package/esm/tanstack-start/react/index.js +4 -0
  58. package/esm/tanstack-start/react/index.js.map +1 -0
  59. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError.d.ts +4 -0
  60. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError.js +8 -0
  61. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError.js.map +1 -0
  62. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/enableUnifiedClientRetryForSsrLoaders.d.ts +4 -0
  63. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/enableUnifiedClientRetryForSsrLoaders.js +86 -0
  64. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/enableUnifiedClientRetryForSsrLoaders.js.map +1 -0
  65. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/entrypoint.d.ts +1 -0
  66. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/entrypoint.js +13 -0
  67. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/entrypoint.js.map +1 -0
  68. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/index.d.ts +2 -0
  69. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/index.js +3 -0
  70. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/index.js.map +1 -0
  71. package/esm/tanstack-start/react/types.d.ts +355 -0
  72. package/esm/tanstack-start/react/types.js +2 -0
  73. package/esm/tanstack-start/react/types.js.map +1 -0
  74. package/esm/tanstack-start/react/withHandlingOidcPostLoginNavigation.d.ts +2 -0
  75. package/esm/tanstack-start/react/withHandlingOidcPostLoginNavigation.js +25 -0
  76. package/esm/tanstack-start/react/withHandlingOidcPostLoginNavigation.js.map +1 -0
  77. package/esm/tools/GetterOrDirectValue.d.ts +1 -0
  78. package/esm/tools/GetterOrDirectValue.js +2 -0
  79. package/esm/tools/GetterOrDirectValue.js.map +1 -0
  80. package/esm/tools/ZodSchemaLike.d.ts +3 -0
  81. package/esm/tools/ZodSchemaLike.js +2 -0
  82. package/esm/tools/ZodSchemaLike.js.map +1 -0
  83. package/esm/tools/inferIsViteDev.d.ts +1 -0
  84. package/esm/tools/inferIsViteDev.js +6 -0
  85. package/esm/tools/inferIsViteDev.js.map +1 -0
  86. package/esm/tools/infer_import_meta_env_BASE_URL.d.ts +1 -0
  87. package/esm/tools/infer_import_meta_env_BASE_URL.js +15 -0
  88. package/esm/tools/infer_import_meta_env_BASE_URL.js.map +1 -0
  89. package/esm/tools/tsafe/uncapitalize.d.ts +2 -0
  90. package/esm/tools/tsafe/uncapitalize.js +5 -0
  91. package/esm/tools/tsafe/uncapitalize.js.map +1 -0
  92. package/esm/vendor/backend/evt.d.ts +2 -0
  93. package/esm/vendor/backend/evt.js +3286 -0
  94. package/esm/vendor/backend/jose.d.ts +1 -0
  95. package/esm/vendor/backend/jose.js +3546 -0
  96. package/esm/vendor/backend/tsafe.d.ts +5 -0
  97. package/esm/vendor/backend/tsafe.js +68 -0
  98. package/esm/vendor/backend/zod.d.ts +1 -0
  99. package/esm/vendor/backend/zod.js +4023 -0
  100. package/esm/vendor/frontend/worker-timers.js +261 -1
  101. package/mock/oidc.d.ts +1 -1
  102. package/mock/oidc.js.map +1 -1
  103. package/package.json +40 -4
  104. package/react/react.d.ts +1 -1
  105. package/src/angular.ts +224 -9
  106. package/src/backend.ts +201 -166
  107. package/src/core/Oidc.ts +41 -11
  108. package/src/core/createOidc.ts +12 -3
  109. package/src/core/earlyInit.ts +19 -4
  110. package/src/core/loginOrGoToAuthServer.ts +11 -3
  111. package/src/core/oidcClientTsUserToTokens.ts +2 -2
  112. package/src/core/requiredPostHydrationReplaceNavigationUrl.ts +11 -0
  113. package/src/entrypoint.ts +1 -0
  114. package/src/mock/oidc.ts +2 -2
  115. package/src/react/react.tsx +1 -1
  116. package/src/tanstack-start/react/accessTokenValidation_rfc9068.ts +135 -0
  117. package/src/tanstack-start/react/apiBuilder.ts +151 -0
  118. package/src/tanstack-start/react/createOidcSpaApi.tsx +1011 -0
  119. package/src/tanstack-start/react/index.ts +5 -0
  120. package/src/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError.ts +8 -0
  121. package/src/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/enableUnifiedClientRetryForSsrLoaders.tsx +127 -0
  122. package/src/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/entrypoint.ts +15 -0
  123. package/src/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/index.ts +2 -0
  124. package/src/tanstack-start/react/types.tsx +415 -0
  125. package/src/tanstack-start/react/withHandlingOidcPostLoginNavigation.tsx +35 -0
  126. package/src/tools/GetterOrDirectValue.ts +1 -0
  127. package/src/tools/ZodSchemaLike.ts +3 -0
  128. package/src/tools/getThisCodebaseRootDirPath_cjs.ts +19 -0
  129. package/src/tools/inferIsViteDev.ts +6 -0
  130. package/src/tools/infer_import_meta_env_BASE_URL.ts +19 -0
  131. package/src/tools/tsafe/uncapitalize.ts +4 -0
  132. package/src/vendor/backend/jose.ts +1 -0
  133. package/src/vendor/build-runtime/babel.ts +6 -0
  134. package/src/vendor/build-runtime/magic-string.ts +3 -0
  135. package/src/vite-plugin/detectProjectType.ts +20 -0
  136. package/src/vite-plugin/excludeModuleExportFromOptimizedDeps.ts +20 -0
  137. package/src/vite-plugin/handleClientEntrypoint.ts +260 -0
  138. package/src/vite-plugin/index.ts +1 -0
  139. package/src/vite-plugin/transformCreateFileRoute.ts +240 -0
  140. package/src/vite-plugin/vite-plugin.ts +54 -0
  141. package/tools/GetterOrDirectValue.d.ts +1 -0
  142. package/tools/GetterOrDirectValue.js +3 -0
  143. package/tools/GetterOrDirectValue.js.map +1 -0
  144. package/tools/ZodSchemaLike.d.ts +3 -0
  145. package/tools/ZodSchemaLike.js +3 -0
  146. package/tools/ZodSchemaLike.js.map +1 -0
  147. package/tools/getThisCodebaseRootDirPath_cjs.d.ts +2 -0
  148. package/tools/getThisCodebaseRootDirPath_cjs.js +53 -0
  149. package/tools/getThisCodebaseRootDirPath_cjs.js.map +1 -0
  150. package/tools/tsafe/uncapitalize.d.ts +2 -0
  151. package/tools/tsafe/uncapitalize.js +8 -0
  152. package/tools/tsafe/uncapitalize.js.map +1 -0
  153. package/vendor/backend/jose.d.ts +1 -0
  154. package/vendor/backend/jose.js +3 -0
  155. package/vendor/build-runtime/babel.d.ts +6 -0
  156. package/vendor/build-runtime/babel.js +3 -0
  157. package/vendor/build-runtime/magic-string.d.ts +2 -0
  158. package/vendor/build-runtime/magic-string.js +2 -0
  159. package/vendor/frontend/oidc-client-ts.js +0 -2
  160. package/vite-plugin/detectProjectType.d.ts +10 -0
  161. package/vite-plugin/detectProjectType.js +15 -0
  162. package/vite-plugin/detectProjectType.js.map +1 -0
  163. package/vite-plugin/excludeModuleExportFromOptimizedDeps.d.ts +4 -0
  164. package/vite-plugin/excludeModuleExportFromOptimizedDeps.js +50 -0
  165. package/vite-plugin/excludeModuleExportFromOptimizedDeps.js.map +1 -0
  166. package/vite-plugin/handleClientEntrypoint.d.ts +10 -0
  167. package/vite-plugin/handleClientEntrypoint.js +211 -0
  168. package/vite-plugin/handleClientEntrypoint.js.map +1 -0
  169. package/vite-plugin/index.d.ts +1 -0
  170. package/vite-plugin/index.js +6 -0
  171. package/vite-plugin/index.js.map +1 -0
  172. package/vite-plugin/transformCreateFileRoute.d.ts +10 -0
  173. package/vite-plugin/transformCreateFileRoute.js +173 -0
  174. package/vite-plugin/transformCreateFileRoute.js.map +1 -0
  175. package/vite-plugin/vite-plugin.d.ts +5 -0
  176. package/vite-plugin/vite-plugin.js +46 -0
  177. package/vite-plugin/vite-plugin.js.map +1 -0
  178. package/src/vendor/backend/jsonwebtoken.ts +0 -1
  179. package/src/vendor/backend/node-fetch.ts +0 -2
  180. package/src/vendor/backend/node-jose.ts +0 -1
  181. package/vendor/backend/jsonwebtoken.d.ts +0 -1
  182. package/vendor/backend/jsonwebtoken.js +0 -3
  183. package/vendor/backend/node-fetch.d.ts +0 -2
  184. package/vendor/backend/node-fetch.js +0 -2
  185. package/vendor/backend/node-jose.d.ts +0 -1
  186. package/vendor/backend/node-jose.js +0 -3
@@ -0,0 +1,1011 @@
1
+ import { useState, useEffect, type ReactNode, createContext, useContext } from "react";
2
+ import type {
3
+ CreateValidateAndGetAccessTokenClaims,
4
+ OidcSpaApi,
5
+ CreateOidcComponent,
6
+ GetOidc,
7
+ ParamsOfBootstrap,
8
+ OidcServerContext
9
+ } from "./types";
10
+ import type { ZodSchemaLike } from "../../tools/ZodSchemaLike";
11
+ import type { Oidc as Oidc_core } from "../../core";
12
+ import { OidcInitializationError } from "../../core/OidcInitializationError";
13
+ import { Deferred } from "../../tools/Deferred";
14
+ import { isBrowser } from "../../tools/isBrowser";
15
+ import { assert, type Equals, is } from "../../tools/tsafe/assert";
16
+ import { infer_import_meta_env_BASE_URL } from "../../tools/infer_import_meta_env_BASE_URL";
17
+ import { createObjectThatThrowsIfAccessed } from "../../tools/createObjectThatThrowsIfAccessed";
18
+ import { createStatefulEvt } from "../../tools/StatefulEvt";
19
+ import { id } from "../../tools/tsafe/id";
20
+ import { typeGuard } from "../../tools/tsafe/typeGuard";
21
+ import type { GetterOrDirectValue } from "../../tools/GetterOrDirectValue";
22
+ import { createServerFn, createMiddleware } from "@tanstack/react-start";
23
+ // @ts-expect-error: Since our module is not labeled as ESM we don't have the types here.
24
+ import { getRequest, setResponseHeader, setResponseStatus } from "@tanstack/react-start/server";
25
+ import { toFullyQualifiedUrl } from "../../tools/toFullyQualifiedUrl";
26
+ import { UnifiedClientRetryForSsrLoadersError } from "./rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError";
27
+
28
+ export function createOidcSpaApi<
29
+ AutoLogin extends boolean,
30
+ DecodedIdToken extends Record<string, unknown>,
31
+ AccessTokenClaims extends Record<string, unknown> | undefined
32
+ >(params: {
33
+ autoLogin: AutoLogin;
34
+ decodedIdTokenSchema:
35
+ | ZodSchemaLike<Oidc_core.Tokens.DecodedIdToken_OidcCoreSpec, DecodedIdToken>
36
+ | undefined;
37
+ decodedIdToken_mock: DecodedIdToken | undefined;
38
+ createValidateAndGetAccessTokenClaims:
39
+ | CreateValidateAndGetAccessTokenClaims<AccessTokenClaims>
40
+ | undefined;
41
+ }): OidcSpaApi<AutoLogin, DecodedIdToken, AccessTokenClaims> {
42
+ const {
43
+ autoLogin,
44
+ decodedIdTokenSchema,
45
+ decodedIdToken_mock,
46
+ createValidateAndGetAccessTokenClaims
47
+ } = params;
48
+
49
+ const dParamsOfBootstrap = new Deferred<
50
+ ParamsOfBootstrap<AutoLogin, DecodedIdToken, AccessTokenClaims>
51
+ >();
52
+
53
+ const dOidcCoreOrInitializationError = new Deferred<
54
+ Oidc_core<DecodedIdToken> | OidcInitializationError
55
+ >();
56
+
57
+ const evtAutoLogoutState = createStatefulEvt<
58
+ CreateOidcComponent.Oidc.LoggedIn<unknown>["autoLogoutState"]
59
+ >(() => ({
60
+ shouldDisplayWarning: false
61
+ }));
62
+
63
+ dOidcCoreOrInitializationError.pr.then(oidcCoreOrInitializationError => {
64
+ const { hasResolved, value: paramsOfBootstrap } = dParamsOfBootstrap.getState();
65
+
66
+ assert(hasResolved);
67
+
68
+ if (paramsOfBootstrap.implementation === "mock") {
69
+ return;
70
+ }
71
+ assert<Equals<typeof paramsOfBootstrap.implementation, "real">>;
72
+
73
+ const { startCountdownSecondsBeforeAutoLogout = 45 } = paramsOfBootstrap;
74
+
75
+ if (
76
+ oidcCoreOrInitializationError === undefined ||
77
+ oidcCoreOrInitializationError instanceof OidcInitializationError
78
+ ) {
79
+ return;
80
+ }
81
+
82
+ const oidcCore = oidcCoreOrInitializationError;
83
+
84
+ if (!oidcCore.isUserLoggedIn) {
85
+ return;
86
+ }
87
+
88
+ oidcCore.subscribeToAutoLogoutCountdown(({ secondsLeft }) => {
89
+ const newState: CreateOidcComponent.Oidc.LoggedIn<unknown>["autoLogoutState"] = (() => {
90
+ if (secondsLeft === undefined) {
91
+ return {
92
+ shouldDisplayWarning: false
93
+ };
94
+ }
95
+
96
+ if (secondsLeft > startCountdownSecondsBeforeAutoLogout) {
97
+ return {
98
+ shouldDisplayWarning: false
99
+ };
100
+ }
101
+
102
+ return {
103
+ shouldDisplayWarning: true,
104
+ secondsLeftBeforeAutoLogout: secondsLeft
105
+ };
106
+ })();
107
+
108
+ if (!newState.shouldDisplayWarning && !evtAutoLogoutState.current.shouldDisplayWarning) {
109
+ return;
110
+ }
111
+
112
+ evtAutoLogoutState.current = newState;
113
+ });
114
+ });
115
+
116
+ function useOidc(): CreateOidcComponent.Oidc<DecodedIdToken> {
117
+ const { hasResolved, value: oidcCore } = dOidcCoreOrInitializationError.getState();
118
+
119
+ assert(hasResolved);
120
+ assert(!(oidcCore instanceof OidcInitializationError));
121
+
122
+ const [, reRenderIfDecodedIdTokenChanged] = useState<DecodedIdToken | undefined>(() => {
123
+ if (!oidcCore.isUserLoggedIn) {
124
+ return undefined;
125
+ }
126
+ return oidcCore.getDecodedIdToken();
127
+ });
128
+
129
+ const [evtIsDecodedIdTokenUsed] = useState(() => createStatefulEvt<boolean>(() => false));
130
+
131
+ useEffect(() => {
132
+ if (!oidcCore.isUserLoggedIn) {
133
+ return;
134
+ }
135
+
136
+ let isActive = true;
137
+
138
+ let unsubscribe: (() => void) | undefined = undefined;
139
+
140
+ (async () => {
141
+ if (!evtIsDecodedIdTokenUsed.current) {
142
+ const dDecodedIdTokenUsed = new Deferred<void>();
143
+
144
+ const { unsubscribe: unsubscribe_scope } = evtIsDecodedIdTokenUsed.subscribe(() => {
145
+ unsubscribe_scope();
146
+ dDecodedIdTokenUsed.resolve();
147
+ });
148
+ unsubscribe = unsubscribe_scope;
149
+
150
+ await dDecodedIdTokenUsed.pr;
151
+
152
+ if (!isActive) {
153
+ return;
154
+ }
155
+ }
156
+
157
+ reRenderIfDecodedIdTokenChanged(oidcCore.getDecodedIdToken());
158
+
159
+ unsubscribe = oidcCore.subscribeToTokensChange(() => {
160
+ reRenderIfDecodedIdTokenChanged(oidcCore.getDecodedIdToken());
161
+ }).unsubscribe;
162
+ })();
163
+
164
+ return () => {
165
+ isActive = false;
166
+ unsubscribe?.();
167
+ };
168
+ }, []);
169
+
170
+ const [evtIsAutoLogoutStateUsed] = useState(() => createStatefulEvt<boolean>(() => false));
171
+
172
+ const [, reRenderIfAutoLogoutStateChanged] = useState(() => evtAutoLogoutState.current);
173
+
174
+ useEffect(() => {
175
+ let isActive = true;
176
+ let unsubscribe: (() => void) | undefined = undefined;
177
+
178
+ (async () => {
179
+ if (!evtIsAutoLogoutStateUsed.current) {
180
+ const dAutoLogoutStateUsed = new Deferred<void>();
181
+
182
+ const { unsubscribe: unsubscribe_scope } = evtIsAutoLogoutStateUsed.subscribe(() => {
183
+ unsubscribe_scope();
184
+ dAutoLogoutStateUsed.resolve();
185
+ });
186
+ unsubscribe = unsubscribe_scope;
187
+
188
+ await dAutoLogoutStateUsed.pr;
189
+
190
+ if (!isActive) {
191
+ return;
192
+ }
193
+ }
194
+
195
+ reRenderIfAutoLogoutStateChanged(evtAutoLogoutState.current);
196
+
197
+ unsubscribe = evtAutoLogoutState.subscribe(reRenderIfAutoLogoutStateChanged).unsubscribe;
198
+ })();
199
+
200
+ return () => {
201
+ isActive = false;
202
+ unsubscribe?.();
203
+ };
204
+ }, []);
205
+
206
+ if (!oidcCore.isUserLoggedIn) {
207
+ return id<CreateOidcComponent.Oidc.NotLoggedIn>({
208
+ isUserLoggedIn: false,
209
+ initializationError: oidcCore.initializationError,
210
+ issuerUri: oidcCore.params.issuerUri,
211
+ clientId: oidcCore.params.clientId,
212
+ autoLogoutState: { shouldDisplayWarning: false },
213
+ login: params =>
214
+ oidcCore.login({
215
+ doesCurrentHrefRequiresAuth: false,
216
+ ...params
217
+ })
218
+ });
219
+ }
220
+
221
+ return id<CreateOidcComponent.Oidc.LoggedIn<DecodedIdToken>>({
222
+ isUserLoggedIn: true,
223
+ get decodedIdToken() {
224
+ evtIsDecodedIdTokenUsed.current = true;
225
+ return oidcCore.getDecodedIdToken();
226
+ },
227
+ logout: oidcCore.logout,
228
+ renewTokens: oidcCore.renewTokens,
229
+ goToAuthServer: oidcCore.goToAuthServer,
230
+ backFromAuthServer: oidcCore.backFromAuthServer,
231
+ isNewBrowserSession: oidcCore.isNewBrowserSession,
232
+ get autoLogoutState() {
233
+ evtIsAutoLogoutStateUsed.current = true;
234
+ return evtAutoLogoutState.current;
235
+ },
236
+ issuerUri: oidcCore.params.issuerUri,
237
+ clientId: oidcCore.params.clientId
238
+ });
239
+ }
240
+
241
+ const context_isFreeOfSsrHydrationConcern = createContext<boolean>(false);
242
+
243
+ function createOidcComponent<Props extends Record<string, unknown>>(params: {
244
+ assert?: "user logged in" | "user not logged in";
245
+ pendingComponent?: (props: NoInfer<Props>) => ReactNode;
246
+ component: (props: Props) => ReactNode;
247
+ }): ((props: Props) => ReactNode) & {
248
+ useOidc: () => CreateOidcComponent.Oidc<DecodedIdToken>;
249
+ } {
250
+ const {
251
+ assert: assert_params,
252
+ pendingComponent: PendingComponent,
253
+ component: Component
254
+ } = params;
255
+
256
+ const checkAssertion =
257
+ assert_params === undefined
258
+ ? undefined
259
+ : (params: { isUserLoggedIn: boolean }): void => {
260
+ const { isUserLoggedIn } = params;
261
+
262
+ switch (assert_params) {
263
+ case "user not logged in":
264
+ if (isUserLoggedIn) {
265
+ throw new Error(
266
+ [
267
+ "oidc-spa: Asserted the user should not be logged in",
268
+ "but they are. Check your control flow."
269
+ ].join(" ")
270
+ );
271
+ }
272
+ break;
273
+ case "user logged in":
274
+ if (!isUserLoggedIn) {
275
+ throw new Error(
276
+ [
277
+ "oidc-spa: Asserted the user should be logged in",
278
+ "but they arn't. Check your control flow."
279
+ ].join(" ")
280
+ );
281
+ }
282
+ break;
283
+ default:
284
+ assert<Equals<typeof assert_params, never>>;
285
+ }
286
+ };
287
+
288
+ function ComponentWithOidc(props: Props) {
289
+ const renderFallback = () =>
290
+ PendingComponent === undefined ? null : <PendingComponent {...props} />;
291
+
292
+ if (!isBrowser) {
293
+ return renderFallback();
294
+ }
295
+
296
+ // NOTE: When the user assert that the user is logged in or not, they know.
297
+ // if they knows it means that they learned it somewhere so we are post SSR.
298
+ // Additionally, in autoLogin mode, the typedef don't allow this param to be provided.
299
+ const isFreeOfSsrHydrationConcern =
300
+ useContext(context_isFreeOfSsrHydrationConcern) || assert_params !== undefined;
301
+
302
+ const [oidcCore, setOidcCore] = useState<Oidc_core<DecodedIdToken> | undefined>(() => {
303
+ if (!isFreeOfSsrHydrationConcern) {
304
+ return undefined;
305
+ }
306
+
307
+ const { hasResolved, value: oidcCore } = dOidcCoreOrInitializationError.getState();
308
+
309
+ if (!hasResolved) {
310
+ return undefined;
311
+ }
312
+
313
+ if (oidcCore instanceof OidcInitializationError) {
314
+ return undefined;
315
+ }
316
+
317
+ checkAssertion?.({
318
+ isUserLoggedIn: oidcCore.isUserLoggedIn
319
+ });
320
+
321
+ return oidcCore;
322
+ });
323
+
324
+ useEffect(() => {
325
+ if (oidcCore !== undefined) {
326
+ return;
327
+ }
328
+
329
+ let isActive = true;
330
+
331
+ dOidcCoreOrInitializationError.pr.then(oidcCore => {
332
+ if (!isActive) {
333
+ return;
334
+ }
335
+
336
+ if (oidcCore instanceof OidcInitializationError) {
337
+ return;
338
+ }
339
+
340
+ checkAssertion?.({
341
+ isUserLoggedIn: oidcCore.isUserLoggedIn
342
+ });
343
+
344
+ setOidcCore(oidcCore);
345
+ });
346
+
347
+ return () => {
348
+ isActive = false;
349
+ };
350
+ }, []);
351
+
352
+ if (oidcCore === undefined) {
353
+ return PendingComponent === undefined ? null : <PendingComponent {...props} />;
354
+ }
355
+
356
+ return (
357
+ <context_isFreeOfSsrHydrationConcern.Provider value={true}>
358
+ <Component {...props} />
359
+ </context_isFreeOfSsrHydrationConcern.Provider>
360
+ );
361
+ }
362
+
363
+ ComponentWithOidc.displayName = `${
364
+ (Component as any).displayName ?? Component.name ?? "Component"
365
+ }WithOidc`;
366
+
367
+ ComponentWithOidc.useOidc = useOidc;
368
+
369
+ return ComponentWithOidc;
370
+ }
371
+
372
+ async function getOidc(params?: {
373
+ assert?: "user logged in" | "user not logged in";
374
+ }): Promise<GetOidc.Oidc<DecodedIdToken>> {
375
+ if (!isBrowser) {
376
+ throw new UnifiedClientRetryForSsrLoadersError(
377
+ [
378
+ "oidc-spa: getOidc() can't be used on the server",
379
+ "if you use it in a loader, make sure to mark the route",
380
+ "as `ssr: false`."
381
+ ].join(" ")
382
+ );
383
+ }
384
+
385
+ const oidcCore = await dOidcCoreOrInitializationError.pr;
386
+
387
+ if (oidcCore instanceof OidcInitializationError) {
388
+ return new Promise<never>(() => {});
389
+ }
390
+
391
+ if (params?.assert === "user logged in" && !oidcCore.isUserLoggedIn) {
392
+ throw new Error(
393
+ [
394
+ "oidc-spa: Called getOidc({ assert: 'user logged in' })",
395
+ "but the user is not currently logged in."
396
+ ].join(" ")
397
+ );
398
+ }
399
+ if (params?.assert === "user not logged in" && oidcCore.isUserLoggedIn) {
400
+ throw new Error(
401
+ [
402
+ "oidc-spa: Called getOidc({ assert: 'user not logged in' })",
403
+ "but the user is currently logged in."
404
+ ].join(" ")
405
+ );
406
+ }
407
+
408
+ return oidcCore.isUserLoggedIn
409
+ ? id<GetOidc.Oidc.LoggedIn<DecodedIdToken>>({
410
+ issuerUri: oidcCore.params.issuerUri,
411
+ clientId: oidcCore.params.clientId,
412
+ isUserLoggedIn: true,
413
+ getAccessToken: async () => {
414
+ const { accessToken } = await oidcCore.getTokens();
415
+ return accessToken;
416
+ },
417
+ getDecodedIdToken: oidcCore.getDecodedIdToken,
418
+ logout: oidcCore.logout,
419
+ renewTokens: oidcCore.renewTokens,
420
+ goToAuthServer: oidcCore.goToAuthServer,
421
+ backFromAuthServer: oidcCore.backFromAuthServer,
422
+ isNewBrowserSession: oidcCore.isNewBrowserSession,
423
+ subscribeToAutoLogoutState: next => {
424
+ next(evtAutoLogoutState.current);
425
+
426
+ const { unsubscribe } = evtAutoLogoutState.subscribe(next);
427
+
428
+ return { unsubscribeFromAutoLogoutState: unsubscribe };
429
+ }
430
+ })
431
+ : id<GetOidc.Oidc.NotLoggedIn>({
432
+ issuerUri: oidcCore.params.issuerUri,
433
+ clientId: oidcCore.params.clientId,
434
+ isUserLoggedIn: false,
435
+ initializationError: oidcCore.initializationError,
436
+ login: oidcCore.login
437
+ });
438
+ }
439
+
440
+ let hasBootstrapBeenCalled = false;
441
+
442
+ const prModuleCore = !isBrowser ? undefined : import("../../core");
443
+
444
+ const bootstrapOidc = (
445
+ getParamsOfBootstrapOrDirectValue: GetterOrDirectValue<
446
+ { process: { env: Record<string, string> } },
447
+ ParamsOfBootstrap<AutoLogin, DecodedIdToken, AccessTokenClaims>
448
+ >
449
+ ) => {
450
+ if (hasBootstrapBeenCalled) {
451
+ return;
452
+ }
453
+
454
+ hasBootstrapBeenCalled = true;
455
+
456
+ (async () => {
457
+ const getParamsOfBootstrap =
458
+ typeof getParamsOfBootstrapOrDirectValue === "function"
459
+ ? getParamsOfBootstrapOrDirectValue
460
+ : () => getParamsOfBootstrapOrDirectValue;
461
+
462
+ if (!isBrowser) {
463
+ const missingEnvNames = new Set<string>();
464
+
465
+ const env_proxy = new Proxy<Record<string, string>>(
466
+ {},
467
+ {
468
+ get: (...[, envName]) => {
469
+ assert(typeof envName === "string");
470
+
471
+ const value = process.env[envName];
472
+
473
+ if (value === undefined) {
474
+ missingEnvNames.add(envName);
475
+ return "";
476
+ }
477
+
478
+ return value;
479
+ },
480
+ has: (...[, envName]) => {
481
+ assert(typeof envName === "string");
482
+ return true;
483
+ }
484
+ }
485
+ );
486
+
487
+ const paramsOfBootstrap = getParamsOfBootstrap({ process: { env: env_proxy } });
488
+
489
+ if (
490
+ paramsOfBootstrap.implementation === "real" &&
491
+ (!paramsOfBootstrap.issuerUri || !paramsOfBootstrap.clientId)
492
+ ) {
493
+ throw new Error(
494
+ [
495
+ "oidc-spa: Incorrect configuration provided:\n",
496
+ JSON.stringify(paramsOfBootstrap, null, 2),
497
+ ...(missingEnvNames.size === 0
498
+ ? []
499
+ : [
500
+ "\nYou probably forgot to define the environnement variables:",
501
+ Array.from(missingEnvNames).join(", ")
502
+ ])
503
+ ].join(" ")
504
+ );
505
+ }
506
+
507
+ dParamsOfBootstrap.resolve(paramsOfBootstrap);
508
+ return;
509
+ }
510
+
511
+ assert(prModuleCore !== undefined);
512
+
513
+ const paramsOfBootstrap = await (async () => {
514
+ let envNamesToPullFromServer = new Set<string>();
515
+
516
+ const env: Record<string, string> = {};
517
+
518
+ const env_proxy = new Proxy(env, {
519
+ get: (...[, envName]) => {
520
+ assert(typeof envName === "string");
521
+
522
+ if (envName in env) {
523
+ return env[envName];
524
+ }
525
+
526
+ envNamesToPullFromServer.add(envName);
527
+
528
+ return "oidc_spa_probe";
529
+ },
530
+ has: (...[, envName]) => {
531
+ assert(typeof envName === "string");
532
+
533
+ if (envName in env) {
534
+ return true;
535
+ }
536
+
537
+ envNamesToPullFromServer.add(envName);
538
+
539
+ return true;
540
+ }
541
+ });
542
+
543
+ let result:
544
+ | {
545
+ hasThrown: false;
546
+ paramsOfBootstrap: ParamsOfBootstrap<
547
+ AutoLogin,
548
+ DecodedIdToken,
549
+ AccessTokenClaims
550
+ >;
551
+ }
552
+ | {
553
+ hasThrown: true;
554
+ error: unknown;
555
+ }
556
+ | undefined = undefined;
557
+
558
+ while (true) {
559
+ envNamesToPullFromServer = new Set();
560
+
561
+ result = undefined;
562
+
563
+ try {
564
+ const paramsOfBootstrap = getParamsOfBootstrap({ process: { env: env_proxy } });
565
+ result = {
566
+ hasThrown: false,
567
+ paramsOfBootstrap
568
+ };
569
+ } catch (error) {
570
+ result = {
571
+ hasThrown: true,
572
+ error
573
+ };
574
+ }
575
+
576
+ if (envNamesToPullFromServer.size === 0) {
577
+ break;
578
+ }
579
+
580
+ Object.entries(
581
+ await fetchServerEnvVariableValues({
582
+ data: {
583
+ envVarNames: Array.from(envNamesToPullFromServer)
584
+ }
585
+ })
586
+ ).forEach(([envName, value]) => {
587
+ env[envName] = value;
588
+ });
589
+ }
590
+
591
+ if (result.hasThrown) {
592
+ throw new Error(
593
+ [
594
+ "oidc-spa: The function argument passed to bootstrapOidc",
595
+ "has thrown when invoked."
596
+ ].join(" "),
597
+ //@ts-expect-error
598
+ { cause: result.error }
599
+ );
600
+ }
601
+
602
+ return result.paramsOfBootstrap;
603
+ })();
604
+
605
+ dParamsOfBootstrap.resolve(paramsOfBootstrap);
606
+
607
+ switch (paramsOfBootstrap.implementation) {
608
+ case "mock":
609
+ {
610
+ const { createMockOidc } = await import("../../mock/oidc");
611
+
612
+ const oidcCore = await createMockOidc({
613
+ homeUrl: infer_import_meta_env_BASE_URL(),
614
+ // NOTE: The `as false` is lying here, it's just to preserve some level of type-safety.
615
+ autoLogin: autoLogin as false,
616
+ // NOTE: Same here, the nullish coalescing is lying.
617
+ isUserInitiallyLoggedIn: paramsOfBootstrap.isUserInitiallyLoggedIn!,
618
+ mockedParams: {
619
+ clientId: paramsOfBootstrap.clientId_mock,
620
+ issuerUri: paramsOfBootstrap.issuerUri_mock
621
+ },
622
+ mockedTokens: {
623
+ decodedIdToken:
624
+ paramsOfBootstrap.decodedIdToken_mock ??
625
+ decodedIdToken_mock ??
626
+ createObjectThatThrowsIfAccessed<DecodedIdToken>({
627
+ debugMessage: [
628
+ "oidc-spa: You didn't provide any mock for the decodedIdToken",
629
+ "Either provide a default one by specifying decodedIdToken_mock",
630
+ "as parameter of .withExpectedDecodedIdTokenShape() or",
631
+ "specify decodedIdToken_mock when calling bootstrapOidc()"
632
+ ].join(" ")
633
+ })
634
+ }
635
+ });
636
+
637
+ dOidcCoreOrInitializationError.resolve(oidcCore);
638
+ }
639
+ break;
640
+ case "real":
641
+ {
642
+ const { createOidc } = await prModuleCore;
643
+
644
+ const homeUrl = infer_import_meta_env_BASE_URL();
645
+
646
+ let oidcCoreOrInitializationError:
647
+ | Oidc_core<DecodedIdToken>
648
+ | OidcInitializationError;
649
+
650
+ try {
651
+ oidcCoreOrInitializationError = await createOidc({
652
+ homeUrl,
653
+ autoLogin,
654
+ decodedIdTokenSchema,
655
+ issuerUri: paramsOfBootstrap.issuerUri,
656
+ clientId: paramsOfBootstrap.clientId,
657
+ idleSessionLifetimeInSeconds:
658
+ paramsOfBootstrap.idleSessionLifetimeInSeconds,
659
+ scopes: paramsOfBootstrap.scopes,
660
+ transformUrlBeforeRedirect: paramsOfBootstrap.transformUrlBeforeRedirect,
661
+ extraQueryParams: paramsOfBootstrap.extraQueryParams,
662
+ extraTokenParams: paramsOfBootstrap.extraTokenParams,
663
+ noIframe: paramsOfBootstrap.noIframe,
664
+ debugLogs: paramsOfBootstrap.debugLogs,
665
+ __unsafe_clientSecret: paramsOfBootstrap.__unsafe_clientSecret,
666
+ __metadata: paramsOfBootstrap.__metadata
667
+ });
668
+ } catch (error) {
669
+ if (!(error instanceof OidcInitializationError)) {
670
+ throw error;
671
+ }
672
+ dOidcCoreOrInitializationError.resolve(error);
673
+ return;
674
+ }
675
+
676
+ dOidcCoreOrInitializationError.resolve(oidcCoreOrInitializationError);
677
+ }
678
+ break;
679
+ }
680
+ })();
681
+ };
682
+
683
+ async function enforceLogin(loaderContext: {
684
+ cause: "preload" | string;
685
+ location: {
686
+ href: string;
687
+ };
688
+ }): Promise<void | never> {
689
+ if (!isBrowser) {
690
+ throw new UnifiedClientRetryForSsrLoadersError(
691
+ [
692
+ "oidc-spa: enforceLogin cannot be used on the server",
693
+ "make sure to mark any route that uses it as ssr: false"
694
+ ].join(" ")
695
+ );
696
+ }
697
+
698
+ const { cause } = loaderContext;
699
+
700
+ const redirectUrl = (() => {
701
+ if (loaderContext.location?.href !== undefined) {
702
+ return toFullyQualifiedUrl({
703
+ urlish: loaderContext.location.href,
704
+ doAssertNoQueryParams: false
705
+ });
706
+ }
707
+
708
+ return location.href;
709
+ })();
710
+
711
+ const oidc = await getOidc();
712
+
713
+ if (!oidc.isUserLoggedIn) {
714
+ if (cause === "preload") {
715
+ throw new Error(
716
+ [
717
+ "oidc-spa: User is not yet logged in.",
718
+ "This is not an error, this is an expected case.",
719
+ "It's only TanStack Router using exception as control flow."
720
+ ].join(" ")
721
+ );
722
+ }
723
+ const doesCurrentHrefRequiresAuth =
724
+ location.href.replace(/\/$/, "") === redirectUrl.replace(/\/$/, "");
725
+
726
+ await oidc.login({
727
+ redirectUrl,
728
+ doesCurrentHrefRequiresAuth
729
+ });
730
+ }
731
+ }
732
+
733
+ enforceLogin.__isOidcSpaEnforceLogin = true;
734
+
735
+ function OidcInitializationGate(props: {
736
+ renderFallback: (props: {
737
+ initializationError: OidcInitializationError | undefined;
738
+ }) => ReactNode;
739
+ children: ReactNode;
740
+ }): ReactNode {
741
+ const { renderFallback, children } = props;
742
+
743
+ const [oidcCoreOrInitializationError, setOidcCoreOrInitializationError] = useState<
744
+ Oidc_core<DecodedIdToken> | OidcInitializationError | undefined
745
+ >(undefined);
746
+
747
+ useEffect(() => {
748
+ let isActive = true;
749
+
750
+ dOidcCoreOrInitializationError.pr.then(oidcCoreOrInitializationError => {
751
+ if (!isActive) {
752
+ return;
753
+ }
754
+ setOidcCoreOrInitializationError(oidcCoreOrInitializationError);
755
+ });
756
+
757
+ return () => {
758
+ isActive = false;
759
+ };
760
+ }, []);
761
+
762
+ if (
763
+ oidcCoreOrInitializationError === undefined ||
764
+ oidcCoreOrInitializationError instanceof OidcInitializationError
765
+ ) {
766
+ return renderFallback({ initializationError: oidcCoreOrInitializationError });
767
+ }
768
+
769
+ return (
770
+ <context_isFreeOfSsrHydrationConcern.Provider value={true}>
771
+ {children}
772
+ </context_isFreeOfSsrHydrationConcern.Provider>
773
+ );
774
+ }
775
+
776
+ const prValidateAndGetAccessTokenClaims =
777
+ createValidateAndGetAccessTokenClaims === undefined
778
+ ? undefined
779
+ : dParamsOfBootstrap.pr.then(paramsOfBootstrap =>
780
+ createValidateAndGetAccessTokenClaims({
781
+ // @ts-expect-error
782
+ paramsOfBootstrap
783
+ })
784
+ );
785
+
786
+ function createFunctionMiddlewareServerFn(params?: {
787
+ assert?: "user logged in";
788
+ hasRequiredClaims?: (params: { accessTokenClaims: AccessTokenClaims }) => Promise<boolean>;
789
+ }) {
790
+ return async (options: {
791
+ next: (options: { context: { oidc: OidcServerContext<AccessTokenClaims> } }) => any;
792
+ }): Promise<any> => {
793
+ const { next } = options;
794
+
795
+ const unauthorized = (params: {
796
+ errorMessage: string;
797
+ wwwAuthenticateHeaderErrorDescription: string;
798
+ }) => {
799
+ const { errorMessage, wwwAuthenticateHeaderErrorDescription } = params;
800
+
801
+ setResponseHeader(
802
+ "WWW-Authenticate",
803
+ `Bearer error="invalid_token", error_description="${wwwAuthenticateHeaderErrorDescription}"`
804
+ );
805
+ setResponseStatus(401, "Unauthorized");
806
+
807
+ return new Error(`oidc-spa: ${errorMessage}`);
808
+ };
809
+
810
+ const { headers } = getRequest();
811
+
812
+ const authorizationHeaderValue = headers.get("Authorization");
813
+
814
+ if (authorizationHeaderValue === null) {
815
+ if (params?.assert === "user logged in") {
816
+ const errorMessage = [
817
+ "Asserted user logged in for that serverFn request",
818
+ "but no access token was attached to the request"
819
+ ].join(" ");
820
+
821
+ throw unauthorized({
822
+ errorMessage,
823
+ wwwAuthenticateHeaderErrorDescription: errorMessage
824
+ });
825
+ }
826
+
827
+ return next({
828
+ context: {
829
+ oidc: id<OidcServerContext<AccessTokenClaims>>(
830
+ id<OidcServerContext.NotLoggedIn>({
831
+ isUserLoggedIn: false
832
+ })
833
+ )
834
+ }
835
+ });
836
+ }
837
+
838
+ const accessToken = (() => {
839
+ const prefix = "Bearer ";
840
+
841
+ if (!authorizationHeaderValue.startsWith(prefix)) {
842
+ return undefined;
843
+ }
844
+
845
+ return authorizationHeaderValue.slice(prefix.length);
846
+ })();
847
+
848
+ if (accessToken === undefined) {
849
+ const errorMessage =
850
+ "Missing well formed Authorization header with Bearer <access_token>";
851
+
852
+ throw unauthorized({
853
+ errorMessage,
854
+ wwwAuthenticateHeaderErrorDescription: errorMessage
855
+ });
856
+ }
857
+
858
+ assert(prValidateAndGetAccessTokenClaims !== undefined);
859
+
860
+ const { validateAndGetAccessTokenClaims } = await prValidateAndGetAccessTokenClaims;
861
+
862
+ const resultOfValidate = await validateAndGetAccessTokenClaims({ accessToken });
863
+
864
+ if (!resultOfValidate.isValid) {
865
+ const { errorMessage, wwwAuthenticateHeaderErrorDescription } = resultOfValidate;
866
+
867
+ throw unauthorized({
868
+ errorMessage,
869
+ wwwAuthenticateHeaderErrorDescription
870
+ });
871
+ }
872
+
873
+ const { accessTokenClaims } = resultOfValidate;
874
+
875
+ assert(is<Exclude<AccessTokenClaims, undefined>>(accessTokenClaims));
876
+
877
+ check_required_claims: {
878
+ const getHasRequiredClaims = params?.hasRequiredClaims;
879
+
880
+ if (getHasRequiredClaims === undefined) {
881
+ break check_required_claims;
882
+ }
883
+
884
+ const accessedClaimNames = new Set<string>();
885
+
886
+ const accessTokenClaims_proxy = new Proxy(accessTokenClaims, {
887
+ get(...args) {
888
+ const [, claimName] = args;
889
+
890
+ record_claim_access: {
891
+ if (typeof claimName !== "string") {
892
+ break record_claim_access;
893
+ }
894
+
895
+ accessedClaimNames.add(claimName);
896
+ }
897
+
898
+ return Reflect.get(...args);
899
+ }
900
+ });
901
+
902
+ const hasRequiredClaims = await getHasRequiredClaims({
903
+ accessTokenClaims: accessTokenClaims_proxy
904
+ });
905
+
906
+ if (hasRequiredClaims) {
907
+ break check_required_claims;
908
+ }
909
+
910
+ const errorMessage = [
911
+ "Missing or invalid required access token claim.",
912
+ `Related to claims: ${Array.from(accessedClaimNames).join(" and/or ")}`
913
+ ].join(" ");
914
+
915
+ throw unauthorized({
916
+ errorMessage,
917
+ wwwAuthenticateHeaderErrorDescription: errorMessage
918
+ });
919
+ }
920
+
921
+ return next({
922
+ context: {
923
+ oidc: id<OidcServerContext<AccessTokenClaims>>(
924
+ id<OidcServerContext.LoggedIn<AccessTokenClaims>>({
925
+ isUserLoggedIn: true,
926
+ accessToken,
927
+ accessTokenClaims
928
+ })
929
+ )
930
+ }
931
+ });
932
+ };
933
+ }
934
+
935
+ function oidcRequestMiddleware(params?: {
936
+ assert?: "user logged in";
937
+ hasRequiredClaims?: (params: { accessTokenClaims: AccessTokenClaims }) => Promise<boolean>;
938
+ }) {
939
+ return createMiddleware({ type: "request" }).server<{
940
+ oidc: OidcServerContext<AccessTokenClaims>;
941
+ }>(createFunctionMiddlewareServerFn(params));
942
+ }
943
+
944
+ function oidcFnMiddleware(params?: {
945
+ assert?: "user logged in";
946
+ hasRequiredClaims?: (params: { accessTokenClaims: AccessTokenClaims }) => Promise<boolean>;
947
+ }) {
948
+ return createMiddleware({ type: "function" })
949
+ .client(async ({ next }) => {
950
+ const oidc = await getOidc();
951
+
952
+ if (params?.assert === "user logged in" && !oidc.isUserLoggedIn) {
953
+ throw new Error(
954
+ [
955
+ "oidc-spa: You used oidcFnMiddleware({ assert: 'user logged in' })",
956
+ "but the server function the middleware was attached to was called",
957
+ "while the user is not logged in."
958
+ ].join(" ")
959
+ );
960
+ }
961
+
962
+ if (!oidc.isUserLoggedIn) {
963
+ return next();
964
+ }
965
+
966
+ return next({
967
+ headers: {
968
+ Authorization: `Bearer ${await oidc.getAccessToken()}`
969
+ }
970
+ });
971
+ })
972
+ .server<{
973
+ oidc: OidcServerContext<AccessTokenClaims>;
974
+ }>(createFunctionMiddlewareServerFn(params));
975
+ }
976
+
977
+ // @ts-expect-error
978
+ return {
979
+ createOidcComponent,
980
+ getOidc,
981
+ bootstrapOidc,
982
+ enforceLogin,
983
+ OidcInitializationGate,
984
+ oidcFnMiddleware,
985
+ oidcRequestMiddleware
986
+ };
987
+ }
988
+
989
+ const fetchServerEnvVariableValues = createServerFn({ method: "GET" })
990
+ .inputValidator((data: { envVarNames: string[] }) => {
991
+ if (typeof data !== "object" || data === null) {
992
+ throw new Error("Expected an object");
993
+ }
994
+
995
+ const { envVarNames } = data as Record<string, unknown>;
996
+
997
+ assert(
998
+ typeGuard<string[]>(
999
+ envVarNames,
1000
+ Array.isArray(envVarNames) && envVarNames.every(name => typeof name === "string")
1001
+ )
1002
+ );
1003
+
1004
+ return { envVarNames };
1005
+ })
1006
+ .handler(async ({ data }) => {
1007
+ const { envVarNames } = data;
1008
+ return Object.fromEntries(
1009
+ envVarNames.map(envVarName => [envVarName, process.env[envVarName] ?? ""])
1010
+ );
1011
+ });