@multiplatform.one/keycloak 0.7.14 → 0.7.16

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 (155) hide show
  1. package/package.json +28 -28
  2. package/routes/index.d.ts +22 -0
  3. package/routes/index.js +22 -0
  4. package/src/Authenticated.tsx +27 -17
  5. package/src/authConfig.ts +3 -9
  6. package/src/hooks/index.ts +0 -3
  7. package/src/hooks/useTokensFromQuery/index.ts +1 -0
  8. package/src/hooks/useTokensFromState.ts +1 -1
  9. package/src/index.ts +3 -0
  10. package/src/{@types/coreJsPure.d.ts → keycloak/context.ts} +6 -11
  11. package/{lib/@types/expoKeycloakAuth.d.d.mts → src/keycloak/index.ts} +4 -7
  12. package/src/keycloak/keycloak.native.ts +148 -0
  13. package/src/keycloak/keycloak.ts +175 -0
  14. package/src/provider/AfterAuth.tsx +63 -0
  15. package/src/provider/{keycloakProvider.native.tsx → AuthProvider/AuthProvider.native.tsx} +8 -16
  16. package/src/provider/{keycloakProvider.tsx → AuthProvider/AuthProvider.tsx} +81 -94
  17. package/{lib/@types/expoKeycloakAuth.d.d.ts → src/provider/AuthProvider/index.ts} +4 -7
  18. package/src/provider/KeycloakProvider.tsx +53 -0
  19. package/src/{hooks/useCurrentRouteName/index.native.ts → provider/index.ts} +6 -11
  20. package/src/routes.ts +163 -0
  21. package/src/session/index.ts +22 -0
  22. package/src/session/session.native.ts +31 -0
  23. package/src/session/session.ts +68 -0
  24. package/src/{state/index.ts → state.ts} +5 -4
  25. package/src/{util.ts → token.ts} +25 -11
  26. package/src/types.ts +4 -1
  27. package/lib/@types/coreJsPure.d.d.mts +0 -2
  28. package/lib/@types/coreJsPure.d.d.ts +0 -2
  29. package/lib/@types/coreJsPure.d.js +0 -1
  30. package/lib/@types/coreJsPure.d.mjs +0 -0
  31. package/lib/@types/expoKeycloakAuth.d.js +0 -1
  32. package/lib/@types/expoKeycloakAuth.d.mjs +0 -0
  33. package/lib/Authenticated.d.mts +0 -33
  34. package/lib/Authenticated.d.ts +0 -33
  35. package/lib/Authenticated.js +0 -19
  36. package/lib/Authenticated.mjs +0 -20
  37. package/lib/authConfig.d.mts +0 -14
  38. package/lib/authConfig.d.ts +0 -14
  39. package/lib/authConfig.js +0 -8
  40. package/lib/authConfig.mjs +0 -9
  41. package/lib/chunk-2GUOEPFY.mjs +0 -0
  42. package/lib/chunk-3ZPHNEJL.js +0 -11
  43. package/lib/chunk-64PPU7Q3.mjs +0 -13
  44. package/lib/chunk-6NDWOV55.js +0 -1
  45. package/lib/chunk-7MTPH6XK.mjs +0 -26
  46. package/lib/chunk-A7UBOIAL.js +0 -13
  47. package/lib/chunk-AD6VPMID.mjs +0 -20
  48. package/lib/chunk-AUUZ6BI7.js +0 -78
  49. package/lib/chunk-AYKQVWMR.mjs +0 -0
  50. package/lib/chunk-BVB33X7V.mjs +0 -265
  51. package/lib/chunk-C2FNSVJO.js +0 -17
  52. package/lib/chunk-J4CCMILN.mjs +0 -41
  53. package/lib/chunk-K33RKJZX.js +0 -443
  54. package/lib/chunk-KLLABHIC.js +0 -13
  55. package/lib/chunk-L5HMOY4M.mjs +0 -18
  56. package/lib/chunk-MZ6E62HK.js +0 -33
  57. package/lib/chunk-NWRANDZ6.js +0 -98
  58. package/lib/chunk-NXTVYIBR.mjs +0 -11
  59. package/lib/chunk-OYWAYMFN.js +0 -17
  60. package/lib/chunk-RPUOO7AV.mjs +0 -10
  61. package/lib/chunk-RYM7KERK.mjs +0 -52
  62. package/lib/chunk-UBVYEZI3.js +0 -1
  63. package/lib/chunk-UHTKOFS6.mjs +0 -84
  64. package/lib/chunk-UL6L5ONI.js +0 -460
  65. package/lib/chunk-UOKDJT5L.mjs +0 -16
  66. package/lib/chunk-W5DJLFTQ.js +0 -56
  67. package/lib/chunk-WT5W6BSZ.js +0 -161
  68. package/lib/chunk-XEO3YXBM.js +0 -22
  69. package/lib/chunk-XO4W2SMN.mjs +0 -50
  70. package/lib/chunk-XVPWAAZ4.mjs +0 -76
  71. package/lib/chunk-Y4XMF3R6.mjs +0 -13
  72. package/lib/chunk-YGNNHTFE.js +0 -12
  73. package/lib/hooks/index.d.mts +0 -9
  74. package/lib/hooks/index.d.ts +0 -9
  75. package/lib/hooks/index.js +0 -23
  76. package/lib/hooks/index.mjs +0 -34
  77. package/lib/hooks/useAuthConfig.d.mts +0 -6
  78. package/lib/hooks/useAuthConfig.d.ts +0 -6
  79. package/lib/hooks/useAuthConfig.js +0 -8
  80. package/lib/hooks/useAuthConfig.mjs +0 -8
  81. package/lib/hooks/useCurrentRouteName/index.d.mts +0 -3
  82. package/lib/hooks/useCurrentRouteName/index.d.ts +0 -3
  83. package/lib/hooks/useCurrentRouteName/index.js +0 -7
  84. package/lib/hooks/useCurrentRouteName/index.mjs +0 -7
  85. package/lib/hooks/useCurrentRouteName/index.native.d.mts +0 -3
  86. package/lib/hooks/useCurrentRouteName/index.native.d.ts +0 -3
  87. package/lib/hooks/useCurrentRouteName/index.native.js +0 -14
  88. package/lib/hooks/useCurrentRouteName/index.native.mjs +0 -14
  89. package/lib/hooks/useKeycloak/index.d.mts +0 -46
  90. package/lib/hooks/useKeycloak/index.d.ts +0 -46
  91. package/lib/hooks/useKeycloak/index.js +0 -11
  92. package/lib/hooks/useKeycloak/index.mjs +0 -12
  93. package/lib/hooks/useKeycloak/useKeycloak.d.mts +0 -2
  94. package/lib/hooks/useKeycloak/useKeycloak.d.ts +0 -2
  95. package/lib/hooks/useKeycloak/useKeycloak.js +0 -10
  96. package/lib/hooks/useKeycloak/useKeycloak.mjs +0 -11
  97. package/lib/hooks/useKeycloak/useKeycloak.native.d.mts +0 -20
  98. package/lib/hooks/useKeycloak/useKeycloak.native.d.ts +0 -20
  99. package/lib/hooks/useKeycloak/useKeycloak.native.js +0 -80
  100. package/lib/hooks/useKeycloak/useKeycloak.native.mjs +0 -69
  101. package/lib/hooks/useLogin.d.mts +0 -3
  102. package/lib/hooks/useLogin.d.ts +0 -3
  103. package/lib/hooks/useLogin.js +0 -11
  104. package/lib/hooks/useLogin.mjs +0 -11
  105. package/lib/hooks/useTokensFromQuery/index.d.mts +0 -3
  106. package/lib/hooks/useTokensFromQuery/index.d.ts +0 -3
  107. package/lib/hooks/useTokensFromQuery/index.js +0 -7
  108. package/lib/hooks/useTokensFromQuery/index.mjs +0 -7
  109. package/lib/hooks/useTokensFromQuery/index.native.d.mts +0 -3
  110. package/lib/hooks/useTokensFromQuery/index.native.d.ts +0 -3
  111. package/lib/hooks/useTokensFromQuery/index.native.js +0 -10
  112. package/lib/hooks/useTokensFromQuery/index.native.mjs +0 -7
  113. package/lib/hooks/useTokensFromState.d.mts +0 -3
  114. package/lib/hooks/useTokensFromState.d.ts +0 -3
  115. package/lib/hooks/useTokensFromState.js +0 -9
  116. package/lib/hooks/useTokensFromState.mjs +0 -9
  117. package/lib/index.d.mts +0 -13
  118. package/lib/index.d.ts +0 -13
  119. package/lib/index.js +0 -34
  120. package/lib/index.mjs +0 -56
  121. package/lib/provider/afterAuth.d.mts +0 -29
  122. package/lib/provider/afterAuth.d.ts +0 -29
  123. package/lib/provider/afterAuth.js +0 -18
  124. package/lib/provider/afterAuth.mjs +0 -18
  125. package/lib/provider/index.d.mts +0 -39
  126. package/lib/provider/index.d.ts +0 -39
  127. package/lib/provider/index.js +0 -22
  128. package/lib/provider/index.mjs +0 -25
  129. package/lib/provider/keycloakProvider.d.mts +0 -42
  130. package/lib/provider/keycloakProvider.d.ts +0 -42
  131. package/lib/provider/keycloakProvider.js +0 -20
  132. package/lib/provider/keycloakProvider.mjs +0 -21
  133. package/lib/provider/keycloakProvider.native.d.mts +0 -29
  134. package/lib/provider/keycloakProvider.native.d.ts +0 -29
  135. package/lib/provider/keycloakProvider.native.js +0 -87
  136. package/lib/provider/keycloakProvider.native.mjs +0 -30
  137. package/lib/state/index.d.mts +0 -11
  138. package/lib/state/index.d.ts +0 -11
  139. package/lib/state/index.js +0 -7
  140. package/lib/state/index.mjs +0 -7
  141. package/lib/types.d.mts +0 -17
  142. package/lib/types.d.ts +0 -17
  143. package/lib/types.js +0 -8
  144. package/lib/types.mjs +0 -7
  145. package/lib/util.d.mts +0 -4
  146. package/lib/util.d.ts +0 -4
  147. package/lib/util.js +0 -8
  148. package/lib/util.mjs +0 -9
  149. package/src/hooks/useCurrentRouteName/index.ts +0 -34
  150. package/src/hooks/useKeycloak/index.ts +0 -47
  151. package/src/hooks/useKeycloak/useKeycloak.native.ts +0 -95
  152. package/src/hooks/useKeycloak/useKeycloak.ts +0 -106
  153. package/src/hooks/useLogin.ts +0 -47
  154. package/src/provider/afterAuth.tsx +0 -65
  155. package/src/provider/index.tsx +0 -117
@@ -0,0 +1,63 @@
1
+ /**
2
+ * File: /src/provider/AfterAuth.tsx
3
+ * Project: @multiplatform.one/keycloak
4
+ * File Created: 10-01-2024 12:41:33
5
+ * Author: Clay Risser
6
+ * -----
7
+ * BitSpur (c) Copyright 2021 - 2024
8
+ *
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ */
21
+
22
+ import React, { useEffect } from 'react';
23
+ import type { PropsWithChildren } from 'react';
24
+ import { useAuthConfig } from '../hooks';
25
+ import { useAuthState, persist } from '../state';
26
+ import { useKeycloak } from '../keycloak';
27
+
28
+ export interface AfterAuthProps extends PropsWithChildren {}
29
+
30
+ const logger = console;
31
+
32
+ export function AfterAuth({ children }: AfterAuthProps) {
33
+ const authConfig = useAuthConfig();
34
+ const authState = useAuthState();
35
+ const keycloak = useKeycloak();
36
+
37
+ useEffect(() => {
38
+ if (!persist || !keycloak?.authenticated) return;
39
+ if (keycloak.token) {
40
+ authState.setToken(keycloak.token);
41
+ if (keycloak.idToken) authState.setIdToken(keycloak.idToken);
42
+ if (keycloak.refreshToken) authState.setRefreshToken(keycloak.refreshToken);
43
+ }
44
+ }, [keycloak?.authenticated, keycloak?.token, keycloak?.idToken, keycloak?.refreshToken]);
45
+
46
+ useEffect(() => {
47
+ if (authConfig.debug && keycloak?.token) logger.debug('token', keycloak.token);
48
+ }, [keycloak?.token]);
49
+
50
+ useEffect(() => {
51
+ if (authConfig.debug && keycloak?.idToken) logger.debug('idToken', keycloak.idToken);
52
+ }, [keycloak?.idToken]);
53
+
54
+ useEffect(() => {
55
+ if (authConfig.debug && keycloak?.refreshToken) logger.debug('refreshToken', keycloak.refreshToken);
56
+ }, [keycloak?.refreshToken]);
57
+
58
+ useEffect(() => {
59
+ if (keycloak?.authenticated) logger.debug('authenticated', keycloak.authenticated);
60
+ }, [keycloak?.authenticated]);
61
+
62
+ return <>{children}</>;
63
+ }
@@ -1,10 +1,10 @@
1
1
  /**
2
- * File: /src/provider/keycloakProvider.native.tsx
2
+ * File: /src/provider/AuthProvider/AuthProvider.native.tsx
3
3
  * Project: @multiplatform.one/keycloak
4
- * File Created: 22-06-2023 10:07:56
4
+ * File Created: 09-01-2024 11:29:20
5
5
  * Author: Clay Risser
6
6
  * -----
7
- * BitSpur (c) Copyright 2021 - 2023
7
+ * BitSpur (c) Copyright 2021 - 2024
8
8
  *
9
9
  * Licensed under the Apache License, Version 2.0 (the "License");
10
10
  * you may not use this file except in compliance with the License.
@@ -20,22 +20,14 @@
20
20
  */
21
21
 
22
22
  import React from 'react';
23
- import type { FC } from 'react';
24
- import type { KeycloakConfig } from '@bitspur/keycloak-js';
25
- import type { KeycloakProviderProps } from './keycloakProvider';
26
- import { AfterAuth } from './afterAuth';
23
+ import type { AuthProviderProps } from './AuthProvider';
24
+ import { AfterAuth } from '../AfterAuth';
27
25
  import { KeycloakProvider as ExpoKeycloakProvider } from 'expo-keycloak-auth';
28
26
 
29
- export const KeycloakProvider: FC<KeycloakProviderProps> = ({ children, keycloakConfig }: KeycloakProviderProps) => {
30
- const clonedKeycloakConfig = {
31
- ...(keycloakConfig as Omit<KeycloakConfig, 'baseUrl'>),
32
- url: keycloakConfig.url,
33
- };
34
- // @ts-ignore
35
- delete keycloakConfig.baseUrl;
27
+ export function AuthProvider({ children, keycloakConfig }: AuthProviderProps) {
36
28
  return (
37
- <ExpoKeycloakProvider {...clonedKeycloakConfig}>
29
+ <ExpoKeycloakProvider {...keycloakConfig}>
38
30
  <AfterAuth>{children}</AfterAuth>
39
31
  </ExpoKeycloakProvider>
40
32
  );
41
- };
33
+ }
@@ -1,10 +1,10 @@
1
1
  /**
2
- * File: /src/provider/keycloakProvider.tsx
2
+ * File: /src/provider/AuthProvider/AuthProvider.tsx
3
3
  * Project: @multiplatform.one/keycloak
4
- * File Created: 22-06-2023 10:07:56
4
+ * File Created: 09-01-2024 11:29:20
5
5
  * Author: Clay Risser
6
6
  * -----
7
- * BitSpur (c) Copyright 2021 - 2023
7
+ * BitSpur (c) Copyright 2021 - 2024
8
8
  *
9
9
  * Licensed under the Apache License, Version 2.0 (the "License");
10
10
  * you may not use this file except in compliance with the License.
@@ -19,62 +19,56 @@
19
19
  * limitations under the License.
20
20
  */
21
21
 
22
- import Keycloak from '@bitspur/keycloak-js';
23
- import React, { useMemo, useEffect, useState, useCallback } from 'react';
24
- import type { AuthClientEvent, AuthClientError, AuthClientTokens } from '@bitspur/react-keycloak-core';
25
- import type { KeycloakInitOptions, KeycloakConfig } from '@bitspur/keycloak-js';
26
- import type { ReactNode, ComponentType } from 'react';
27
- import { AfterAuth } from './afterAuth';
22
+ import KeycloakClient from 'keycloak-js';
23
+ import React, { useEffect, useMemo, useState } from 'react';
24
+ import type { KeycloakConfig, KeycloakInitOptions } from 'keycloak-js';
25
+ import type { PropsWithChildren } from 'react';
26
+ import type { SessionProviderProps } from 'next-auth/react';
27
+ import { AfterAuth } from '../AfterAuth';
28
+ import { Keycloak } from '../../keycloak';
29
+ import { KeycloakContext } from '../../keycloak/context';
28
30
  import { MultiPlatform } from 'multiplatform.one';
29
- import { ReactKeycloakProvider } from '@bitspur/react-keycloak-web';
30
- import { SSRKeycloakProvider, SSRCookies } from '@bitspur/react-keycloak-ssr';
31
- import { useAuthConfig } from '../hooks/useAuthConfig';
32
- import { useAuthState } from '../state';
31
+ import { SessionProvider } from 'next-auth/react';
32
+ import { persist, useAuthState } from '../../state';
33
+ import { useAuthConfig } from '../../hooks';
33
34
  import { useRouter } from 'next/router';
34
- import { validToken } from '../util';
35
+ import { validToken } from '../../token';
35
36
 
36
- export interface KeycloakProviderProps {
37
- children: ReactNode;
38
- cookies?: unknown;
39
- keycloakConfig: KeycloakConfig;
37
+ export interface AuthProviderProps extends PropsWithChildren {
38
+ keycloakConfig?: KeycloakConfig;
40
39
  keycloakInitOptions?: KeycloakInitOptions;
41
- loadingComponent?: ComponentType;
42
- onEvent?: (eventType: AuthClientEvent, error?: AuthClientError) => void;
43
- onTokens?: (tokens: AuthClientTokens) => void;
40
+ sessionProvider?: Omit<SessionProviderProps, 'children'>;
44
41
  }
45
42
 
46
43
  const logger = console;
47
44
 
48
- export function KeycloakProvider({
49
- children,
50
- cookies,
51
- keycloakConfig,
52
- keycloakInitOptions,
53
- loadingComponent,
54
- onEvent,
55
- onTokens,
56
- }: KeycloakProviderProps) {
57
- const { debug, ensureFreshness, persist, messageHandlerKeys, ssr } = useAuthConfig();
58
- const authState = useAuthState();
59
- const LoadingComponent = loadingComponent || (() => <>{debug ? 'authenticating' : null}</>);
45
+ export function AuthProvider({ children, sessionProvider, keycloakInitOptions, keycloakConfig }: AuthProviderProps) {
46
+ const { debug, messageHandlerKeys } = useAuthConfig();
60
47
  const { query } = MultiPlatform.isNext ? useRouter() : { query: {} };
61
- const [refreshToken, setRefreshToken] = useState<string | boolean>(
48
+ const authState = useAuthState();
49
+ const [keycloak, setKeycloak] = useState<Keycloak>();
50
+ const [refreshToken, setRefreshToken] = useState<string | boolean | undefined>(
62
51
  validToken(
63
- (ensureFreshness &&
64
- (('refreshToken' in query && (query.refreshToken?.toString() || true)) ||
65
- (persist && authState.refreshToken))) ||
66
- false,
52
+ MultiPlatform.isIframe
53
+ ? ('refreshToken' in query && (query.refreshToken?.toString() || true)) ||
54
+ (persist && authState.refreshToken) ||
55
+ false
56
+ : undefined,
67
57
  ),
68
58
  );
69
- const [idToken, setIdToken] = useState<string | boolean>(
59
+ const [token, setToken] = useState<string | boolean | undefined>(
70
60
  validToken(
71
- ('idToken' in query && (query.idToken?.toString() || true)) || (persist && authState.idToken) || false,
61
+ MultiPlatform.isIframe
62
+ ? ('token' in query && (query.token?.toString() || true)) || (persist && authState.token) || false
63
+ : undefined,
72
64
  refreshToken,
73
65
  ),
74
66
  );
75
- const [token, setToken] = useState<string | boolean>(
67
+ const [idToken, setIdToken] = useState<string | boolean | undefined>(
76
68
  validToken(
77
- ('token' in query && (query.token?.toString() || true)) || (persist && authState.token) || false,
69
+ MultiPlatform.isIframe
70
+ ? ('idToken' in query && (query.idToken?.toString() || true)) || (persist && authState.idToken) || false
71
+ : undefined,
78
72
  refreshToken,
79
73
  ),
80
74
  );
@@ -188,28 +182,20 @@ export function KeycloakProvider({
188
182
  };
189
183
  }, []);
190
184
 
191
- const handleEvent = useCallback((eventType: AuthClientEvent, error?: AuthClientError) => {
192
- if (error) {
193
- if (typeof error === 'string') throw new Error(error);
194
- const err: Error & { errorDescription?: string } = new Error(error.error);
195
- err.errorDescription = error.error_description;
196
- throw err;
197
- }
198
- if (onEvent) onEvent(eventType, error);
199
- }, []);
200
-
201
- const keycloak = useMemo(
185
+ const keycloakClient = useMemo(
202
186
  () =>
203
- typeof window !== 'undefined' &&
204
- new Keycloak({
205
- url: keycloakConfig.url,
206
- realm: keycloakConfig.realm,
207
- clientId: keycloakConfig.clientId,
208
- }),
209
- [keycloakInitOptions, token, refreshToken, idToken],
187
+ MultiPlatform.isIframe && keycloakConfig
188
+ ? new KeycloakClient({
189
+ url: keycloakConfig.url,
190
+ realm: keycloakConfig.realm,
191
+ clientId: keycloakConfig.clientId,
192
+ })
193
+ : undefined,
194
+ [keycloakInitOptions, keycloakConfig, token, refreshToken, idToken],
210
195
  );
211
196
 
212
197
  const initOptions = useMemo(() => {
198
+ if (!MultiPlatform.isIframe) return;
213
199
  const initOptions = {
214
200
  ...defaultKeycloakInitOptions,
215
201
  ...keycloakInitOptions,
@@ -227,45 +213,46 @@ export function KeycloakProvider({
227
213
  initOptions.onLoad = undefined;
228
214
  }
229
215
  return initOptions;
230
- }, [keycloakInitOptions, token, refreshToken, idToken]);
216
+ }, [keycloakInitOptions, token, idToken, refreshToken]);
217
+
218
+ useEffect(() => {
219
+ function onError() {
220
+ if (keycloakClient && initOptions) setKeycloak(new Keycloak(keycloakClient));
221
+ }
222
+ function onUpdate() {
223
+ if (keycloakClient && initOptions) setKeycloak(new Keycloak(keycloakClient));
224
+ }
225
+ if (keycloakClient && initOptions) {
226
+ (async () => {
227
+ keycloakClient.onAuthError = onError;
228
+ keycloakClient.onAuthLogout = onUpdate;
229
+ keycloakClient.onAuthRefreshError = onError;
230
+ keycloakClient.onAuthRefreshSuccess = onUpdate;
231
+ keycloakClient.onAuthSuccess = onUpdate;
232
+ keycloakClient.onReady = onUpdate;
233
+ keycloakClient.onTokenExpired = async () => {
234
+ try {
235
+ await keycloakClient.updateToken(5);
236
+ } catch (err) {
237
+ setKeycloak(new Keycloak());
238
+ }
239
+ };
240
+ const authenticated = await keycloakClient.init(initOptions);
241
+ setKeycloak(new Keycloak(authenticated ? keycloakClient : undefined));
242
+ })();
243
+ }
244
+ }, []);
231
245
 
232
- if (token === true || idToken === true || refreshToken === true) return <LoadingComponent />;
233
- if (cookies && ssr) {
234
- return (
235
- // @ts-ignore
236
- <SSRKeycloakProvider
237
- LoadingComponent={<LoadingComponent />}
238
- autoRefreshToken={initOptions.checkLoginIframe}
239
- initOptions={initOptions}
240
- onEvent={handleEvent}
241
- onTokens={onTokens}
242
- persistor={SSRCookies(cookies)}
243
- keycloakConfig={{
244
- clientId: keycloakConfig.clientId,
245
- realm: keycloakConfig.realm,
246
- url: keycloakConfig.url,
247
- }}
248
- >
249
- <AfterAuth>{children}</AfterAuth>
250
- </SSRKeycloakProvider>
251
- );
252
- }
253
- if (!keycloak) return <LoadingComponent />;
254
246
  return (
255
- <ReactKeycloakProvider
256
- LoadingComponent={<LoadingComponent />}
257
- authClient={keycloak}
258
- autoRefreshToken={initOptions.checkLoginIframe}
259
- initOptions={initOptions}
260
- onEvent={handleEvent}
261
- onTokens={onTokens}
262
- >
263
- <AfterAuth>{children}</AfterAuth>
264
- </ReactKeycloakProvider>
247
+ <SessionProvider {...sessionProvider}>
248
+ <KeycloakContext.Provider value={keycloak}>
249
+ <AfterAuth>{children}</AfterAuth>
250
+ </KeycloakContext.Provider>
251
+ </SessionProvider>
265
252
  );
266
253
  }
267
254
 
268
- export const defaultKeycloakInitOptions: KeycloakInitOptions = {
255
+ const defaultKeycloakInitOptions: KeycloakInitOptions = {
269
256
  checkLoginIframe: true,
270
257
  checkLoginIframeInterval: 5,
271
258
  enableLogging: false,
@@ -1,10 +1,10 @@
1
1
  /*
2
- * File: /src/@types/expoKeycloakAuth.d.ts
2
+ * File: /src/provider/AuthProvider/index.ts
3
3
  * Project: @multiplatform.one/keycloak
4
- * File Created: 22-06-2023 10:07:56
4
+ * File Created: 10-01-2024 13:43:20
5
5
  * Author: Clay Risser
6
6
  * -----
7
- * BitSpur (c) Copyright 2021 - 2023
7
+ * BitSpur (c) Copyright 2021 - 2024
8
8
  *
9
9
  * Licensed under the Apache License, Version 2.0 (the "License");
10
10
  * you may not use this file except in compliance with the License.
@@ -19,7 +19,4 @@
19
19
  * limitations under the License.
20
20
  */
21
21
 
22
- declare module 'expo-keycloak-auth' {
23
- export function useKeycloak(): any;
24
- export const KeycloakProvider: any;
25
- }
22
+ export * from './AuthProvider';
@@ -0,0 +1,53 @@
1
+ /**
2
+ * File: /src/provider/KeycloakProvider.tsx
3
+ * Project: @multiplatform.one/keycloak
4
+ * File Created: 10-01-2024 13:56:05
5
+ * Author: Clay Risser
6
+ * -----
7
+ * BitSpur (c) Copyright 2021 - 2024
8
+ *
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ */
21
+
22
+ import React, { useMemo } from 'react';
23
+ import type { AuthConfig } from '../authConfig';
24
+ import type { PropsWithChildren } from 'react';
25
+ import type { Session } from 'next-auth';
26
+ import { AuthConfigContext } from '../authConfig';
27
+ import { AuthProvider } from './AuthProvider';
28
+
29
+ export interface KeycloakProviderProps extends PropsWithChildren, AuthConfig {
30
+ baseUrl?: string;
31
+ clientId?: string;
32
+ realm?: string;
33
+ session?: Session;
34
+ }
35
+
36
+ export function KeycloakProvider({ children, debug, realm, clientId, baseUrl, session }: KeycloakProviderProps) {
37
+ const authConfig = useMemo(() => ({ debug }), [debug]);
38
+
39
+ return (
40
+ <AuthConfigContext.Provider value={authConfig}>
41
+ <AuthProvider
42
+ sessionProvider={{ session }}
43
+ keycloakConfig={{
44
+ realm: realm || 'main',
45
+ clientId: clientId || 'app',
46
+ url: baseUrl,
47
+ }}
48
+ >
49
+ {children}
50
+ </AuthProvider>
51
+ </AuthConfigContext.Provider>
52
+ );
53
+ }
@@ -1,10 +1,10 @@
1
1
  /*
2
- * File: /src/hooks/useCurrentRouteName/index.native.ts
2
+ * File: /src/provider/index.ts
3
3
  * Project: @multiplatform.one/keycloak
4
- * File Created: 22-06-2023 10:07:56
4
+ * File Created: 09-01-2024 11:29:13
5
5
  * Author: Clay Risser
6
6
  * -----
7
- * BitSpur (c) Copyright 2021 - 2023
7
+ * BitSpur (c) Copyright 2021 - 2024
8
8
  *
9
9
  * Licensed under the Apache License, Version 2.0 (the "License");
10
10
  * you may not use this file except in compliance with the License.
@@ -19,11 +19,6 @@
19
19
  * limitations under the License.
20
20
  */
21
21
 
22
- import { MultiPlatform } from 'multiplatform.one';
23
- import { useRoute } from '@react-navigation/native';
24
-
25
- export function useCurrentRouteName() {
26
- if (MultiPlatform.isStorybook) return null;
27
- const route = useRoute();
28
- return route.name;
29
- }
22
+ export * from './AfterAuth';
23
+ export * from './AuthProvider';
24
+ export * from './KeycloakProvider';
package/src/routes.ts ADDED
@@ -0,0 +1,163 @@
1
+ /*
2
+ * File: /src/routes.ts
3
+ * Project: @multiplatform.one/keycloak
4
+ * File Created: 09-01-2024 11:32:46
5
+ * Author: Clay Risser
6
+ * -----
7
+ * BitSpur (c) Copyright 2021 - 2024
8
+ *
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ */
21
+
22
+ import type { AccessTokenParsed } from './token';
23
+ import type { AuthOptions, CallbacksOptions } from 'next-auth';
24
+ import type { JWT } from 'next-auth/jwt';
25
+ import type { OAuthUserConfig } from 'next-auth/providers';
26
+ import type { Session } from './session';
27
+ import { getServerSession } from 'next-auth';
28
+ import { jwtDecode } from 'jwt-decode';
29
+
30
+ const KeycloakProvider = require('next-auth/providers/keycloak').default;
31
+ const NextAuth = require('next-auth').default;
32
+ const NextResponse = require('next/server').NextResponse;
33
+
34
+ const logger = console;
35
+ let _nextAuth: AuthOptions | undefined;
36
+
37
+ export function createAuthHandler(options: CreateAuthHandlerOptions = {}) {
38
+ const handler = NextAuth(createAuthOptions(options));
39
+ return {
40
+ GET: handler,
41
+ POST: handler,
42
+ };
43
+ }
44
+
45
+ export function createLogoutHandler(options: CreateAuthHandlerOptions = {}) {
46
+ return {
47
+ async GET() {
48
+ const idToken = ((await getServerSession(createAuthOptions(options))) as Session)?.idToken;
49
+ if (idToken) {
50
+ try {
51
+ await fetch(
52
+ `${process.env.KEYCLOAK_BASE_URL}/realms/${
53
+ process.env.KEYCLOAK_REALM || 'master'
54
+ }/protocol/openid-connect/logout?id_token_hint=${idToken}&post_logout_redirect_uri=${encodeURIComponent(
55
+ process.env.NEXTAUTH_URL || '',
56
+ )}`,
57
+ { method: 'GET' },
58
+ );
59
+ } catch (err) {
60
+ logger.error(err);
61
+ return new NextResponse(null, { status: 500 });
62
+ }
63
+ }
64
+ return new NextResponse();
65
+ },
66
+ };
67
+ }
68
+
69
+ function createAuthOptions(options: CreateAuthHandlerOptions = {}) {
70
+ if (_nextAuth) return _nextAuth;
71
+ _nextAuth = {
72
+ ...options.nextAuth,
73
+ providers: [
74
+ KeycloakProvider({
75
+ clientId: process.env.KEYCLOAK_CLIENT_ID || '',
76
+ clientSecret: process.env.KEYCLOAK_CLIENT_SECRET || '',
77
+ issuer: `${process.env.KEYCLOAK_BASE_URL}/realms/${process.env.KEYCLOAK_REALM || 'master'}`,
78
+ ...options.keycloakProvider,
79
+ }),
80
+ ...(options.nextAuth?.providers || []),
81
+ ],
82
+ callbacks: {
83
+ ...options.nextAuth?.callbacks,
84
+ async jwt(params) {
85
+ if (typeof options.nextAuth?.callbacks?.jwt === 'function') {
86
+ return options.nextAuth?.callbacks.jwt(params);
87
+ }
88
+ const { token, account } = params;
89
+ if (account) {
90
+ const decoded = jwtDecode(account.access_token || '') as AccessTokenParsed;
91
+ token.decoded = decoded;
92
+ token.accessToken = account.access_token;
93
+ token.idToken = account.id_token;
94
+ token.expiresAt = account.expires_at;
95
+ token.refreshToken = account.refresh_token;
96
+ token.roles = decoded.realm_access?.roles;
97
+ return token;
98
+ } else if (Math.floor(Date.now() / 1000) < Number(token.expiresAt)) {
99
+ return token;
100
+ } else {
101
+ try {
102
+ return refreshAccessToken(token as NextToken);
103
+ } catch (err) {
104
+ return { ...token, err };
105
+ }
106
+ }
107
+ },
108
+ async session(params) {
109
+ if (typeof options.nextAuth?.callbacks?.session === 'function') {
110
+ return options.nextAuth.callbacks.session(params);
111
+ }
112
+ const { session: nextSession, token: nextToken } = params;
113
+ const session = nextSession as Session;
114
+ const token = nextToken as NextToken;
115
+ if (token.accessToken) session.accessToken = token.accessToken;
116
+ if (token.idToken) session.idToken = token.idToken;
117
+ session.err = token.err;
118
+ return session;
119
+ },
120
+ } as CallbacksOptions,
121
+ } as AuthOptions;
122
+ return _nextAuth;
123
+ }
124
+
125
+ async function refreshAccessToken(nextToken: NextToken) {
126
+ const res = await fetch(process.env.REFRESH_TOKEN_URL || '', {
127
+ method: 'POST',
128
+ headers: {
129
+ 'Content-Type': 'application/x-www-form-urlencoded',
130
+ },
131
+ body: new URLSearchParams({
132
+ client_id: process.env.KEYCLOAK_CLIENT_ID || '',
133
+ client_secret: process.env.KEYCLOAK_CLIENT_SECRET || '',
134
+ grant_type: 'refresh_token',
135
+ refresh_token: nextToken.refreshToken,
136
+ }),
137
+ });
138
+ const refreshToken = await res.json();
139
+ if (!res.ok) throw refreshToken;
140
+ return {
141
+ ...nextToken,
142
+ accessToken: refreshToken.access_token,
143
+ decoded: jwtDecode(refreshToken.access_token),
144
+ expiresAt: Math.floor(Date.now() / 1000) + Number(refreshToken.expires_in),
145
+ idToken: refreshToken.id_token,
146
+ refreshToken: refreshToken.refresh_token,
147
+ };
148
+ }
149
+
150
+ export interface CreateAuthHandlerOptions {
151
+ keycloakProvider?: Partial<OAuthUserConfig<any>>;
152
+ nextAuth?: AuthOptions;
153
+ }
154
+
155
+ export interface NextToken extends JWT {
156
+ accessToken?: string;
157
+ decoded: AccessTokenParsed;
158
+ err?: Error;
159
+ expiresAt: number;
160
+ idToken?: string;
161
+ refreshToken: string;
162
+ roles: string[];
163
+ }
@@ -0,0 +1,22 @@
1
+ /*
2
+ * File: /src/session/index.ts
3
+ * Project: @multiplatform.one/keycloak
4
+ * File Created: 11-01-2024 02:47:42
5
+ * Author: Clay Risser
6
+ * -----
7
+ * BitSpur (c) Copyright 2021 - 2024
8
+ *
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ */
21
+
22
+ export * from './session';
@@ -0,0 +1,31 @@
1
+ /*
2
+ * File: /src/session/session.native.ts
3
+ * Project: @multiplatform.one/keycloak
4
+ * File Created: 10-01-2024 02:31:26
5
+ * Author: Clay Risser
6
+ * -----
7
+ * BitSpur (c) Copyright 2021 - 2024
8
+ *
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ */
21
+
22
+ import type { SessionContextValue } from './session';
23
+ import type { UseSessionOptions } from 'next-auth/react';
24
+
25
+ export async function getSession() {
26
+ return null;
27
+ }
28
+
29
+ export function useSession<R extends boolean>(_options?: UseSessionOptions<R>): SessionContextValue<R> {
30
+ return {};
31
+ }