@multiplatform.one/keycloak 1.0.2 → 1.0.3

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 (169) hide show
  1. package/package.json +32 -34
  2. package/routes/index.d.ts +1 -1
  3. package/routes/index.js +1 -1
  4. package/src/Authenticated.tsx +12 -13
  5. package/src/apollo.ts +1 -1
  6. package/src/authConfig.ts +2 -0
  7. package/src/hooks/useTokensFromQuery/index.ts +2 -0
  8. package/src/hooks/useTokensFromState.ts +2 -2
  9. package/{lib/@types/expoKeycloakAuth.d.d.mts → src/keycloak/config.ts} +17 -6
  10. package/src/keycloak/context.ts +3 -1
  11. package/src/keycloak/index.ts +1 -0
  12. package/src/keycloak/keycloak.native.ts +49 -15
  13. package/src/keycloak/keycloak.ts +66 -11
  14. package/src/provider/AfterAuth.tsx +2 -0
  15. package/src/provider/AuthProvider/AuthProvider.native.tsx +159 -6
  16. package/src/provider/AuthProvider/AuthProvider.tsx +66 -43
  17. package/src/provider/KeycloakProvider.tsx +12 -2
  18. package/src/routes.ts +19 -0
  19. package/src/session/session.ts +4 -15
  20. package/src/token.ts +13 -5
  21. package/lib/@types/expoKeycloakAuth.d.d.ts +0 -25
  22. package/lib/@types/expoKeycloakAuth.d.js +0 -1
  23. package/lib/@types/expoKeycloakAuth.d.mjs +0 -0
  24. package/lib/Authenticated.d.mts +0 -32
  25. package/lib/Authenticated.d.ts +0 -32
  26. package/lib/Authenticated.js +0 -20
  27. package/lib/Authenticated.mjs +0 -20
  28. package/lib/apollo.d.mts +0 -7
  29. package/lib/apollo.d.ts +0 -7
  30. package/lib/apollo.js +0 -15
  31. package/lib/apollo.mjs +0 -15
  32. package/lib/authConfig.d.mts +0 -12
  33. package/lib/authConfig.d.ts +0 -12
  34. package/lib/authConfig.js +0 -9
  35. package/lib/authConfig.mjs +0 -9
  36. package/lib/chunk-2L5TXBDK.mjs +0 -7
  37. package/lib/chunk-2MYOFYAK.mjs +0 -53
  38. package/lib/chunk-2VDDEPLF.js +0 -27
  39. package/lib/chunk-2VGMJ7WP.js +0 -34
  40. package/lib/chunk-32AVT4GA.js +0 -9
  41. package/lib/chunk-3ZTSLDX7.js +0 -13
  42. package/lib/chunk-6APOOEW6.js +0 -28
  43. package/lib/chunk-6F4PWJZI.js +0 -1
  44. package/lib/chunk-6FRYV4MK.mjs +0 -27
  45. package/lib/chunk-6WBHOY7M.js +0 -50
  46. package/lib/chunk-74FSREBY.js +0 -161
  47. package/lib/chunk-A2V2S4HP.js +0 -22
  48. package/lib/chunk-BUZONXAW.js +0 -1
  49. package/lib/chunk-C6TOWKPW.mjs +0 -245
  50. package/lib/chunk-DNEUOHZQ.mjs +0 -28
  51. package/lib/chunk-EGCPD3BX.js +0 -51
  52. package/lib/chunk-HH32BME2.mjs +0 -0
  53. package/lib/chunk-HTWZLBA4.mjs +0 -13
  54. package/lib/chunk-I5FNGKQ6.js +0 -16
  55. package/lib/chunk-IGSEESI3.mjs +0 -51
  56. package/lib/chunk-JAFUI2JQ.mjs +0 -9
  57. package/lib/chunk-JPQI72HR.mjs +0 -0
  58. package/lib/chunk-KWNIT4G4.mjs +0 -34
  59. package/lib/chunk-L3HTVJ4B.mjs +0 -13
  60. package/lib/chunk-MDAAMGTE.js +0 -1
  61. package/lib/chunk-NQMFZ6RW.mjs +0 -50
  62. package/lib/chunk-OAUYHIWG.mjs +0 -0
  63. package/lib/chunk-OBB23GPX.mjs +0 -0
  64. package/lib/chunk-OYWXU5N7.mjs +0 -161
  65. package/lib/chunk-P57PW2II.js +0 -11
  66. package/lib/chunk-TUJRPTZE.js +0 -13
  67. package/lib/chunk-UESWAK47.mjs +0 -0
  68. package/lib/chunk-UKSHA3X3.mjs +0 -16
  69. package/lib/chunk-VS4M7GMO.js +0 -1
  70. package/lib/chunk-W4LGQZMF.js +0 -245
  71. package/lib/chunk-WBQAMGXK.mjs +0 -0
  72. package/lib/chunk-WMH347OL.mjs +0 -22
  73. package/lib/chunk-WS4IMGVL.js +0 -1
  74. package/lib/chunk-YACGLW5Q.js +0 -7
  75. package/lib/chunk-YYYDFAI4.js +0 -53
  76. package/lib/chunk-ZCBD6HWK.js +0 -1
  77. package/lib/chunk-ZFXKCRJC.mjs +0 -11
  78. package/lib/hooks/index.d.mts +0 -5
  79. package/lib/hooks/index.d.ts +0 -5
  80. package/lib/hooks/index.js +0 -19
  81. package/lib/hooks/index.mjs +0 -19
  82. package/lib/hooks/useAuthConfig.d.mts +0 -6
  83. package/lib/hooks/useAuthConfig.d.ts +0 -6
  84. package/lib/hooks/useAuthConfig.js +0 -8
  85. package/lib/hooks/useAuthConfig.mjs +0 -8
  86. package/lib/hooks/useTokensFromQuery/index.d.mts +0 -3
  87. package/lib/hooks/useTokensFromQuery/index.d.ts +0 -3
  88. package/lib/hooks/useTokensFromQuery/index.js +0 -7
  89. package/lib/hooks/useTokensFromQuery/index.mjs +0 -7
  90. package/lib/hooks/useTokensFromQuery/index.native.d.mts +0 -3
  91. package/lib/hooks/useTokensFromQuery/index.native.d.ts +0 -3
  92. package/lib/hooks/useTokensFromQuery/index.native.js +0 -7
  93. package/lib/hooks/useTokensFromQuery/index.native.mjs +0 -7
  94. package/lib/hooks/useTokensFromState.d.mts +0 -3
  95. package/lib/hooks/useTokensFromState.d.ts +0 -3
  96. package/lib/hooks/useTokensFromState.js +0 -9
  97. package/lib/hooks/useTokensFromState.mjs +0 -9
  98. package/lib/index.d.mts +0 -18
  99. package/lib/index.d.ts +0 -18
  100. package/lib/index.js +0 -70
  101. package/lib/index.mjs +0 -70
  102. package/lib/keycloak/context.d.mts +0 -12
  103. package/lib/keycloak/context.d.ts +0 -12
  104. package/lib/keycloak/context.js +0 -7
  105. package/lib/keycloak/context.mjs +0 -7
  106. package/lib/keycloak/index.d.mts +0 -7
  107. package/lib/keycloak/index.d.ts +0 -7
  108. package/lib/keycloak/index.js +0 -14
  109. package/lib/keycloak/index.mjs +0 -14
  110. package/lib/keycloak/keycloak.d.mts +0 -37
  111. package/lib/keycloak/keycloak.d.ts +0 -37
  112. package/lib/keycloak/keycloak.js +0 -13
  113. package/lib/keycloak/keycloak.mjs +0 -13
  114. package/lib/keycloak/keycloak.native.d.mts +0 -33
  115. package/lib/keycloak/keycloak.native.d.ts +0 -33
  116. package/lib/keycloak/keycloak.native.js +0 -134
  117. package/lib/keycloak/keycloak.native.mjs +0 -134
  118. package/lib/provider/AfterAuth.d.mts +0 -28
  119. package/lib/provider/AfterAuth.d.ts +0 -28
  120. package/lib/provider/AfterAuth.js +0 -18
  121. package/lib/provider/AfterAuth.mjs +0 -18
  122. package/lib/provider/AuthProvider/AuthProvider.d.mts +0 -37
  123. package/lib/provider/AuthProvider/AuthProvider.d.ts +0 -37
  124. package/lib/provider/AuthProvider/AuthProvider.js +0 -19
  125. package/lib/provider/AuthProvider/AuthProvider.mjs +0 -19
  126. package/lib/provider/AuthProvider/AuthProvider.native.d.mts +0 -29
  127. package/lib/provider/AuthProvider/AuthProvider.native.d.ts +0 -29
  128. package/lib/provider/AuthProvider/AuthProvider.native.js +0 -25
  129. package/lib/provider/AuthProvider/AuthProvider.native.mjs +0 -25
  130. package/lib/provider/AuthProvider/index.d.mts +0 -4
  131. package/lib/provider/AuthProvider/index.d.ts +0 -4
  132. package/lib/provider/AuthProvider/index.js +0 -20
  133. package/lib/provider/AuthProvider/index.mjs +0 -20
  134. package/lib/provider/KeycloakProvider.d.mts +0 -34
  135. package/lib/provider/KeycloakProvider.d.ts +0 -34
  136. package/lib/provider/KeycloakProvider.js +0 -21
  137. package/lib/provider/KeycloakProvider.mjs +0 -21
  138. package/lib/provider/index.d.mts +0 -8
  139. package/lib/provider/index.d.ts +0 -8
  140. package/lib/provider/index.js +0 -28
  141. package/lib/provider/index.mjs +0 -28
  142. package/lib/routes.d.mts +0 -34
  143. package/lib/routes.d.ts +0 -34
  144. package/lib/routes.js +0 -131
  145. package/lib/routes.mjs +0 -131
  146. package/lib/session/index.d.mts +0 -3
  147. package/lib/session/index.d.ts +0 -3
  148. package/lib/session/index.js +0 -10
  149. package/lib/session/index.mjs +0 -10
  150. package/lib/session/session.d.mts +0 -18
  151. package/lib/session/session.d.ts +0 -18
  152. package/lib/session/session.js +0 -9
  153. package/lib/session/session.mjs +0 -9
  154. package/lib/session/session.native.d.mts +0 -8
  155. package/lib/session/session.native.d.ts +0 -8
  156. package/lib/session/session.native.js +0 -13
  157. package/lib/session/session.native.mjs +0 -13
  158. package/lib/state.d.mts +0 -12
  159. package/lib/state.d.ts +0 -12
  160. package/lib/state.js +0 -9
  161. package/lib/state.mjs +0 -9
  162. package/lib/token.d.mts +0 -17
  163. package/lib/token.d.ts +0 -17
  164. package/lib/token.js +0 -9
  165. package/lib/token.mjs +0 -9
  166. package/lib/types.d.mts +0 -20
  167. package/lib/types.d.ts +0 -20
  168. package/lib/types.js +0 -1
  169. package/lib/types.mjs +0 -1
package/package.json CHANGED
@@ -1,22 +1,23 @@
1
1
  {
2
2
  "name": "@multiplatform.one/keycloak",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "keycloak client for multiplatform.one ecosystem",
5
- "main": "lib/index.js",
6
- "module": "lib/index.mjs",
5
+ "main": "dist/cjs",
6
+ "module": "dist/esm",
7
+ "module:jsx": "dist/jsx",
7
8
  "react-native": "src/index.ts",
8
9
  "source": "src/index.ts",
9
- "types": "lib/index.d.ts",
10
+ "types": "types/index.d.ts",
10
11
  "exports": {
11
12
  ".": {
12
- "import": "./lib/index.mjs",
13
- "require": "./lib/index.js",
14
- "types": "./lib/index.d.ts"
13
+ "import": "./dist/esm/index.js",
14
+ "require": "./dist/cjs/index.js",
15
+ "types": "./types/index.d.ts"
15
16
  },
16
17
  "./routes": {
17
- "import": "./lib/routes.mjs",
18
- "require": "./lib/routes.js",
19
- "types": "./lib/routes.d.ts"
18
+ "import": "./dist/esm/routes.js",
19
+ "require": "./dist/cjs/routes.js",
20
+ "types": "./dist/esm/routes.d.ts"
20
21
  }
21
22
  },
22
23
  "author": "BitSpur",
@@ -40,35 +41,31 @@
40
41
  "url": "https://gitlab.com/risserlabs/multiplatform.one/keycloak"
41
42
  },
42
43
  "peerDependencies": {
43
- "@react-native-async-storage/async-storage": "1.19.3",
44
- "expo-keycloak-auth": "1.0.14",
45
- "multiplatform.one": "^1.0.2",
44
+ "@react-native-async-storage/async-storage": "1.21.0",
45
+ "multiplatform.one": "^1.0.3",
46
46
  "next": "^13.0.5",
47
- "react": "^18.2.0",
48
- "react-native": "~0.73.1"
47
+ "react": "18.2.0",
48
+ "react-native": "0.73.6"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@react-native-async-storage/async-storage": "1.21.0",
52
- "@react-navigation/native": "^6.1.9",
53
- "@types/eslint": "^8.56.2",
54
- "@types/jest": "^29.5.11",
52
+ "@tamagui/build": "^1.95.1",
53
+ "@types/eslint": "^8.56.10",
54
+ "@types/jest": "^29.5.12",
55
55
  "@types/lodash.camelcase": "^4.3.9",
56
56
  "@types/lodash.startcase": "^4.4.9",
57
- "@types/react": "^18.2.48",
57
+ "@types/react": "^18.3.1",
58
58
  "@types/react-native": "^0.73.0",
59
- "cspell": "^8.3.2",
60
- "eslint": "^8.56.0",
61
- "expo-keycloak-auth": "1.0.14",
59
+ "cspell": "^8.7.0",
60
+ "eslint": "~8.56.0",
62
61
  "jest": "^29.7.0",
63
62
  "jest-sonar-reporter": "^2.0.0",
64
- "multiplatform.one": "^1.0.2",
65
- "next": "^14.0.4",
66
- "prettier": "^3.2.4",
67
- "react": "^18.2.0",
68
- "react-native": "~0.73.2",
69
- "ts-node": "^10.9.2",
70
- "tsup": "^8.0.1",
71
- "typescript": "^5.3.3"
63
+ "multiplatform.one": "^1.0.3",
64
+ "next": "^14.2.3",
65
+ "prettier": "^3.2.5",
66
+ "react": "18.2.0",
67
+ "react-native": "0.73.6",
68
+ "typescript": "5.3.3"
72
69
  },
73
70
  "engines": {
74
71
  "node": ">=6.0.0"
@@ -95,9 +92,10 @@
95
92
  "indent": 4
96
93
  },
97
94
  "dependencies": {
98
- "@apollo/client": "^3.8.9",
99
- "expo-auth-session": "^5.4.0",
100
- "keycloak-js": "^23.0.4",
101
- "next-auth": "^4.24.5"
95
+ "@apollo/client": "^3.10.1",
96
+ "expo-auth-session": "^5.5.1",
97
+ "expo-crypto": "^12.8.1",
98
+ "keycloak-js": "^24.0.3",
99
+ "next-auth": "^4.24.7"
102
100
  }
103
101
  }
package/routes/index.d.ts CHANGED
@@ -19,4 +19,4 @@
19
19
  * limitations under the License.
20
20
  */
21
21
 
22
- export * from '../lib/routes.js';
22
+ export * from '../types/routes';
package/routes/index.js CHANGED
@@ -19,4 +19,4 @@
19
19
  * limitations under the License.
20
20
  */
21
21
 
22
- module.exports = require('../lib/routes/index');
22
+ module.exports = require('../dist/cjs/routes.js');
@@ -19,11 +19,18 @@
19
19
  * limitations under the License.
20
20
  */
21
21
 
22
+ 'use client';
23
+
22
24
  import React, { ComponentType, PropsWithChildren, useEffect } from 'react';
23
25
  import { MultiPlatform } from 'multiplatform.one';
24
- import { useAuthConfig, useTokensFromQuery, useTokensFromState } from './hooks';
26
+ import { Text } from 'tamagui';
27
+ import { useAuthConfig, useTokensFromQuery } from './hooks';
25
28
  import { useKeycloak } from './keycloak';
26
29
 
30
+ import AsyncStorage from '@react-native-async-storage/async-storage';
31
+
32
+ global.AsyncStorage = AsyncStorage;
33
+
27
34
  export interface AuthenticatedProps extends PropsWithChildren {
28
35
  disabled?: boolean;
29
36
  loadingComponent?: ComponentType;
@@ -34,33 +41,25 @@ export function Authenticated({ children, disabled, loggedOutComponent, loadingC
34
41
  const authConfig = useAuthConfig();
35
42
  const keycloak = useKeycloak();
36
43
  const tokensFromQuery = useTokensFromQuery();
37
- const tokensFromState = useTokensFromState();
38
44
 
39
45
  useEffect(() => {
40
- if (
41
- !keycloak ||
42
- MultiPlatform.isIframe ||
43
- MultiPlatform.isServer ||
44
- keycloak.authenticated ||
45
- tokensFromQuery ||
46
- tokensFromState
47
- ) {
46
+ if (!keycloak || MultiPlatform.isIframe || MultiPlatform.isServer || keycloak.authenticated || tokensFromQuery) {
48
47
  return;
49
48
  }
50
49
  keycloak.login({
51
50
  redirectUri: authConfig.loginRedirectUri,
52
51
  });
53
- }, [keycloak]);
52
+ }, [keycloak?.authenticated]);
54
53
 
55
54
  if (typeof disabled === 'undefined') disabled = authConfig.disabled;
56
55
  if (disabled) return <>{children}</>;
57
56
  if (typeof keycloak === 'undefined') {
58
57
  const LoadingComponent = loadingComponent;
59
- return LoadingComponent ? <LoadingComponent /> : <>{authConfig.debug ? 'loading' : null}</>;
58
+ return LoadingComponent ? <LoadingComponent /> : <Text>{authConfig.debug ? 'loading' : null}</Text>;
60
59
  }
61
60
  if (keycloak.authenticated) return <>{children}</>;
62
61
  const LoggedOutComponent = loggedOutComponent;
63
- return LoggedOutComponent ? <LoggedOutComponent /> : <>{authConfig.debug ? 'not authenticated' : null}</>;
62
+ return LoggedOutComponent ? <LoggedOutComponent /> : <Text>{authConfig.debug ? 'not authenticated' : null}</Text>;
64
63
  }
65
64
 
66
65
  export function withAuthenticated<P extends object>(Component: ComponentType<P>) {
package/src/apollo.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * File: /src/apollo.ts
3
3
  * Project: @multiplatform.one/keycloak
4
- * File Created: 13-01-2024 13:37:13
4
+ * File Created: 04-04-2024 15:50:39
5
5
  * Author: Clay Risser
6
6
  * -----
7
7
  * BitSpur (c) Copyright 2021 - 2024
package/src/authConfig.ts CHANGED
@@ -19,6 +19,8 @@
19
19
  * limitations under the License.
20
20
  */
21
21
 
22
+ 'use client';
23
+
22
24
  import { createContext } from 'react';
23
25
 
24
26
  export const defaultAuthConfig: AuthConfig = {};
@@ -19,6 +19,8 @@
19
19
  * limitations under the License.
20
20
  */
21
21
 
22
+ 'use client';
23
+
22
24
  import { MultiPlatform } from 'multiplatform.one';
23
25
  import { useRouter } from 'next/router';
24
26
 
@@ -20,9 +20,9 @@
20
20
  */
21
21
 
22
22
  import { useAuthState } from '../state';
23
- import { validToken } from '../token';
23
+ import { validOrRefreshableToken } from '../token';
24
24
 
25
25
  export function useTokensFromState() {
26
26
  const authState = useAuthState();
27
- return !!validToken(authState.token, authState.refreshToken);
27
+ return !!validOrRefreshableToken(authState.token, authState.refreshToken);
28
28
  }
@@ -1,10 +1,10 @@
1
1
  /*
2
- * File: /src/@types/expoKeycloakAuth.d.ts
2
+ * File: /src/keycloak/config.ts
3
3
  * Project: @multiplatform.one/keycloak
4
- * File Created: 22-06-2023 10:07:56
4
+ * File Created: 27-04-2024 10:53:19
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,18 @@
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;
22
+ 'use client';
23
+
24
+ import type { KeycloakConfig as KeycloakJsConfig } from 'keycloak-js';
25
+ import { createContext } from 'react';
26
+
27
+ export interface KeycloakConfig extends KeycloakJsConfig {
28
+ publicClientId?: string;
29
+ scopes?: string[];
25
30
  }
31
+
32
+ export const KeycloakConfigContext = createContext<KeycloakConfig>({
33
+ clientId: '',
34
+ realm: '',
35
+ url: '',
36
+ });
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * File: /src/keycloak/context.ts
3
3
  * Project: @multiplatform.one/keycloak
4
- * File Created: 10-01-2024 15:10:13
4
+ * File Created: 04-04-2024 15:50:39
5
5
  * Author: Clay Risser
6
6
  * -----
7
7
  * BitSpur (c) Copyright 2021 - 2024
@@ -19,6 +19,8 @@
19
19
  * limitations under the License.
20
20
  */
21
21
 
22
+ 'use client';
23
+
22
24
  import type { Keycloak } from './keycloak';
23
25
  import { createContext } from 'react';
24
26
 
@@ -19,4 +19,5 @@
19
19
  * limitations under the License.
20
20
  */
21
21
 
22
+ export * from './config';
22
23
  export * from './keycloak';
@@ -21,25 +21,36 @@
21
21
 
22
22
  import type KeycloakClient from 'keycloak-js';
23
23
  import type { AccessTokenParsed, TokenParsed } from '../token';
24
- import type { KeycloakLoginOptions, KeycloakLogoutOptions } from 'keycloak-js';
24
+ import type { KeycloakConfig } from 'keycloak-js';
25
+ import type { KeycloakLoginOptions, KeycloakLogoutOptions } from '../keycloak';
25
26
  import type { KeycloakMock } from '../types';
27
+ import { KeycloakConfigContext } from '../keycloak/config';
28
+ import { KeycloakContext } from './context';
26
29
  import { MultiPlatform } from 'multiplatform.one';
27
- import { getSession } from '../session/session';
28
30
  import { jwtDecode } from 'jwt-decode';
29
- import { useKeycloak as useExpoKeycloak } from 'expo-keycloak-auth';
31
+ import { useContext } from 'react';
30
32
 
31
33
  export class Keycloak {
32
- token: string;
34
+ token?: string;
33
35
  idToken?: string;
34
36
  refreshToken?: string;
35
37
 
36
- private _tokenParsed?: AccessTokenParsed;
37
38
  private _idTokenParsed?: TokenParsed;
39
+ private _login?: (_options: KeycloakLoginOptions) => Promise<undefined>;
40
+ private _logout?: (_options: KeycloakLogoutOptions) => Promise<undefined>;
38
41
  private _refreshTokenParsed?: TokenParsed;
42
+ private _tokenParsed?: AccessTokenParsed;
39
43
  private keycloakClient?: KeycloakClient;
40
44
  private mock: KeycloakMock | undefined;
41
45
 
42
- constructor(input: string | KeycloakClient | KeycloakMock, idToken?: string, refreshToken?: string) {
46
+ constructor(
47
+ public readonly config: KeycloakConfig,
48
+ input?: string | KeycloakClient | KeycloakMock,
49
+ idToken?: string,
50
+ refreshToken?: string,
51
+ login?: (_options: KeycloakLoginOptions) => Promise<undefined>,
52
+ logout?: (_options: KeycloakLogoutOptions) => Promise<undefined>,
53
+ ) {
43
54
  if (typeof input === 'string') {
44
55
  this.token = input;
45
56
  this.idToken = idToken;
@@ -56,6 +67,8 @@ export class Keycloak {
56
67
  if (this.refreshToken && !this._refreshTokenParsed) {
57
68
  this._refreshTokenParsed = jwtDecode(this.refreshToken) as TokenParsed;
58
69
  }
70
+ this._login = login;
71
+ this._logout = logout;
59
72
  }
60
73
 
61
74
  get tokenParsed() {
@@ -75,7 +88,7 @@ export class Keycloak {
75
88
 
76
89
  get clientId() {
77
90
  if (this.keycloakClient) return this.keycloakClient.clientId;
78
- return this.tokenParsed?.azp;
91
+ return this.tokenParsed?.azp || this.config.clientId;
79
92
  }
80
93
 
81
94
  get email() {
@@ -86,7 +99,7 @@ export class Keycloak {
86
99
 
87
100
  get realm() {
88
101
  if (this.keycloakClient) return this.keycloakClient.realm;
89
- return this.tokenParsed?.iss?.split('/').pop();
102
+ return this.tokenParsed?.iss?.split('/').pop() || this.config.realm;
90
103
  }
91
104
 
92
105
  get realmAccess() {
@@ -114,35 +127,56 @@ export class Keycloak {
114
127
  return this.tokenParsed?.preferred_username;
115
128
  }
116
129
 
130
+ async getUserInfo() {
131
+ if (!this.authenticated) return;
132
+ const response = await fetch(`${this.config.url}/realms/${this.config.realm}/protocol/openid-connect/userinfo`, {
133
+ method: 'GET',
134
+ headers: {
135
+ Authorization: 'Bearer ' + this.token,
136
+ Accept: 'application/json',
137
+ },
138
+ });
139
+ if (response.ok) return response.json();
140
+ }
141
+
117
142
  async login(options: KeycloakLoginOptions = {}) {
143
+ this.idToken = undefined;
144
+ this.refreshToken = undefined;
145
+ this.token = undefined;
118
146
  if (this.keycloakClient) {
119
147
  await this.keycloakClient.login(options);
148
+ } else {
149
+ await this._login?.(options);
120
150
  }
121
151
  }
122
152
 
123
153
  async logout(options: KeycloakLogoutOptions = {}) {
154
+ this.idToken = undefined;
155
+ this.refreshToken = undefined;
156
+ this.token = undefined;
124
157
  if (this.keycloakClient) {
125
158
  await this.keycloakClient.logout(options);
159
+ } else {
160
+ await this._logout?.(options);
126
161
  }
127
162
  }
128
163
 
129
- async isAuthenticated() {
164
+ get authenticated() {
130
165
  if (this.mock) return true;
131
166
  if (this.keycloakClient) return !!this.keycloakClient.authenticated;
132
- if (MultiPlatform.isNext) return !!(await getSession());
133
- if (!this.tokenParsed?.exp) return false;
167
+ if (!this.tokenParsed?.exp || !this.idToken) return false;
134
168
  return this.tokenParsed.exp > Date.now() / 1000;
135
169
  }
136
170
  }
137
171
 
138
172
  export function useKeycloak() {
139
- const { token, refreshToken, idToken } = useExpoKeycloak();
140
- if (MultiPlatform.isServer) return;
173
+ const keycloak = useContext(KeycloakContext);
174
+ const keycloakConfig = useContext(KeycloakConfigContext);
175
+ if (keycloak) return keycloak;
141
176
  if (MultiPlatform.isStorybook) {
142
- return new Keycloak({
177
+ return new Keycloak(keycloakConfig, {
143
178
  email: 'storybook@example.com',
144
179
  username: 'storybook',
145
180
  });
146
181
  }
147
- if (token) return new Keycloak(token, idToken, refreshToken);
148
182
  }
@@ -22,16 +22,25 @@
22
22
  import type KeycloakClient from 'keycloak-js';
23
23
  import type { AccessTokenParsed, TokenParsed } from '../token';
24
24
  import type { AuthOptions } from 'next-auth';
25
- import type { GetSessionParams } from 'next-auth/react';
26
- import type { KeycloakLoginOptions, KeycloakLogoutOptions } from 'keycloak-js';
25
+ import type { AuthRequestPromptOptions } from 'expo-auth-session';
27
26
  import type { KeycloakMock } from '../types';
27
+ import type { KeycloakProfile } from 'next-auth/providers/keycloak';
28
+ import type { OAuthConfig } from 'next-auth/providers';
28
29
  import type { Session } from '../session/session';
30
+ import { KeycloakConfigContext, type KeycloakConfig } from './config';
29
31
  import { KeycloakContext } from './context';
30
32
  import { MultiPlatform } from 'multiplatform.one';
31
33
  import { getSession, useSession } from '../session/session';
32
34
  import { jwtDecode } from 'jwt-decode';
33
35
  import { signIn, signOut } from 'next-auth/react';
34
36
  import { useContext } from 'react';
37
+ import type {
38
+ KeycloakLoginOptions as KeycloakJsLoginOptions,
39
+ KeycloakLogoutOptions as KeycloakJsLogoutOptions,
40
+ } from 'keycloak-js';
41
+
42
+ export type KeycloakLoginOptions = KeycloakJsLoginOptions & AuthRequestPromptOptions & { redirect?: boolean };
43
+ export type KeycloakLogoutOptions = KeycloakJsLogoutOptions;
35
44
 
36
45
  export class Keycloak {
37
46
  token?: string;
@@ -39,12 +48,21 @@ export class Keycloak {
39
48
  refreshToken?: string;
40
49
 
41
50
  private _idTokenParsed?: TokenParsed;
51
+ private _login?: (_options: KeycloakLoginOptions) => Promise<undefined>;
52
+ private _logout?: (_options: KeycloakLogoutOptions) => Promise<undefined>;
42
53
  private _refreshTokenParsed?: TokenParsed;
43
54
  private _tokenParsed?: AccessTokenParsed;
44
55
  private keycloakClient?: KeycloakClient;
45
56
  private mock: KeycloakMock | undefined;
46
57
 
47
- constructor(input?: string | KeycloakClient | KeycloakMock | Session, idToken?: string, refreshToken?: string) {
58
+ constructor(
59
+ public readonly config: KeycloakConfig,
60
+ input?: string | KeycloakClient | KeycloakMock | Session,
61
+ idToken?: string,
62
+ refreshToken?: string,
63
+ login?: (_options: KeycloakLoginOptions) => Promise<undefined>,
64
+ logout?: (_options: KeycloakLogoutOptions) => Promise<undefined>,
65
+ ) {
48
66
  if (typeof input === 'string') {
49
67
  this.token = input;
50
68
  this.idToken = idToken;
@@ -66,6 +84,8 @@ export class Keycloak {
66
84
  if (this.refreshToken && !this._refreshTokenParsed) {
67
85
  this._refreshTokenParsed = jwtDecode(this.refreshToken) as TokenParsed;
68
86
  }
87
+ this._login = login;
88
+ this._logout = logout;
69
89
  }
70
90
 
71
91
  get tokenParsed() {
@@ -85,7 +105,7 @@ export class Keycloak {
85
105
 
86
106
  get clientId() {
87
107
  if (this.keycloakClient) return this.keycloakClient.clientId;
88
- return this.tokenParsed?.azp;
108
+ return this.tokenParsed?.azp || this.config.clientId;
89
109
  }
90
110
 
91
111
  get email() {
@@ -96,7 +116,7 @@ export class Keycloak {
96
116
 
97
117
  get realm() {
98
118
  if (this.keycloakClient) return this.keycloakClient.realm;
99
- return this.tokenParsed?.iss?.split('/').pop();
119
+ return this.tokenParsed?.iss?.split('/').pop() || this.config.realm;
100
120
  }
101
121
 
102
122
  get realmAccess() {
@@ -124,17 +144,38 @@ export class Keycloak {
124
144
  return this.tokenParsed?.preferred_username;
125
145
  }
126
146
 
147
+ async getUserInfo() {
148
+ if (!this.authenticated) return;
149
+ const response = await fetch(`${this.config.url}/realms/${this.config.realm}/protocol/openid-connect/userinfo`, {
150
+ method: 'GET',
151
+ headers: {
152
+ Authorization: 'Bearer ' + this.token,
153
+ Accept: 'application/json',
154
+ },
155
+ });
156
+ if (response.ok) return response.json();
157
+ }
158
+
127
159
  async login(options: KeycloakLoginOptions = {}) {
160
+ this.idToken = undefined;
161
+ this.refreshToken = undefined;
162
+ this.token = undefined;
128
163
  if (this.keycloakClient) {
129
164
  await this.keycloakClient.login(options);
130
165
  } else if (MultiPlatform.isNext && !MultiPlatform.isServer) {
131
166
  await signIn('keycloak', {
132
167
  callbackUrl: options.redirectUri,
168
+ redirect: options.redirect,
133
169
  });
170
+ } else {
171
+ await this._login?.(options);
134
172
  }
135
173
  }
136
174
 
137
175
  async logout(options: KeycloakLogoutOptions = {}) {
176
+ this.idToken = undefined;
177
+ this.refreshToken = undefined;
178
+ this.token = undefined;
138
179
  if (this.keycloakClient) {
139
180
  await this.keycloakClient.logout(options);
140
181
  } else if (MultiPlatform.isNext && !MultiPlatform.isServer) {
@@ -142,6 +183,8 @@ export class Keycloak {
142
183
  await signOut({
143
184
  callbackUrl: options.redirectUri,
144
185
  });
186
+ } else {
187
+ await this._logout?.(options);
145
188
  }
146
189
  }
147
190
 
@@ -155,22 +198,34 @@ export class Keycloak {
155
198
 
156
199
  export function useKeycloak() {
157
200
  const keycloak = useContext(KeycloakContext);
201
+ const keycloakConfig = useContext(KeycloakConfigContext);
158
202
  if (keycloak) return keycloak;
159
203
  const { session, status } = useSession();
160
204
  if (MultiPlatform.isStorybook) {
161
- return new Keycloak({
205
+ return new Keycloak(keycloakConfig, {
162
206
  email: 'storybook@example.com',
163
207
  username: 'storybook',
164
208
  });
165
209
  } else if (status === 'unauthenticated') {
166
- return new Keycloak();
210
+ return new Keycloak(keycloakConfig);
167
211
  } else if (status === 'authenticated' && session?.accessToken) {
168
- return new Keycloak(session as Session);
212
+ return new Keycloak(keycloakConfig, session as Session);
169
213
  }
170
214
  }
171
215
 
172
- export async function getKeycloak(options?: AuthOptions | GetSessionParams, req?: any, res?: any) {
216
+ export async function getKeycloak(options?: AuthOptions, req?: any, res?: any) {
217
+ const keycloakProvider: OAuthConfig<KeycloakProfile> | undefined = options?.providers.find(
218
+ (provider) => provider.id === 'keycloak',
219
+ )?.options;
220
+ const parts = keycloakProvider?.issuer?.split('/realms/');
221
+ const keycloakConfig: KeycloakConfig = {
222
+ realm: parts?.[1]?.split('/')[0] || '',
223
+ url: parts?.[0] || '',
224
+ clientId: keycloakProvider?.clientId || '',
225
+ };
173
226
  const session = await getSession(options, req, res);
174
- if (session?.accessToken) return new Keycloak(session as Session);
175
- return new Keycloak();
227
+ if (session?.accessToken) {
228
+ return new Keycloak(keycloakConfig, session as Session);
229
+ }
230
+ return new Keycloak(keycloakConfig);
176
231
  }
@@ -19,6 +19,8 @@
19
19
  * limitations under the License.
20
20
  */
21
21
 
22
+ 'use client';
23
+
22
24
  import React, { useEffect } from 'react';
23
25
  import type { PropsWithChildren } from 'react';
24
26
  import { useAuthConfig } from '../hooks';