@multiplatform.one/keycloak 0.2.17 → 0.3.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.
- package/dist/esm/authConfig.mjs +2 -2
- package/dist/esm/authConfig.mjs.map +1 -1
- package/dist/esm/provider/afterAuth.mjs +1 -1
- package/dist/esm/provider/afterAuth.mjs.map +2 -2
- package/dist/esm/provider/index.mjs +64 -8
- package/dist/esm/provider/index.mjs.map +2 -2
- package/dist/esm/provider/keycloakProvider.mjs +54 -31
- package/dist/esm/provider/keycloakProvider.mjs.map +2 -2
- package/dist/esm/provider/keycloakProvider.native.mjs +1 -1
- package/dist/esm/provider/keycloakProvider.native.mjs.map +1 -1
- package/dist/jsx/authConfig.mjs +2 -2
- package/dist/jsx/authConfig.mjs.map +1 -1
- package/dist/jsx/provider/afterAuth.mjs +1 -1
- package/dist/jsx/provider/afterAuth.mjs.map +2 -2
- package/dist/jsx/provider/index.mjs +45 -7
- package/dist/jsx/provider/index.mjs.map +2 -2
- package/dist/jsx/provider/keycloakProvider.mjs +61 -32
- package/dist/jsx/provider/keycloakProvider.mjs.map +2 -2
- package/dist/jsx/provider/keycloakProvider.native.mjs +1 -1
- package/dist/jsx/provider/keycloakProvider.native.mjs.map +1 -1
- package/dist/lib/authConfig.d.ts +1 -1
- package/dist/lib/authConfig.js +2 -2
- package/dist/lib/authConfig.js.map +1 -1
- package/dist/lib/provider/afterAuth.js +1 -1
- package/dist/lib/provider/afterAuth.js.map +2 -2
- package/dist/lib/provider/index.d.ts +11 -4
- package/dist/lib/provider/index.js +77 -7
- package/dist/lib/provider/index.js.map +2 -2
- package/dist/lib/provider/keycloakProvider.d.ts +2 -10
- package/dist/lib/provider/keycloakProvider.js +62 -32
- package/dist/lib/provider/keycloakProvider.js.map +2 -2
- package/dist/lib/provider/keycloakProvider.native.js +1 -1
- package/dist/lib/provider/keycloakProvider.native.js.map +1 -1
- package/dist/lib/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/authConfig.ts +3 -3
- package/src/provider/afterAuth.tsx +1 -1
- package/src/provider/index.tsx +65 -12
- package/src/provider/keycloakProvider.native.tsx +1 -1
- package/src/provider/keycloakProvider.tsx +64 -43
package/package.json
CHANGED
package/src/authConfig.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* File Created: 08-11-2022 09:21:15
|
|
5
5
|
* Author: Clay Risser
|
|
6
6
|
* -----
|
|
7
|
-
* Last Modified:
|
|
7
|
+
* Last Modified: 14-05-2023 01:22:15
|
|
8
8
|
* Modified By: Clay Risser
|
|
9
9
|
* -----
|
|
10
10
|
* Risser Labs LLC (c) Copyright 2021 - 2022
|
|
@@ -26,8 +26,8 @@ import { createContext } from 'react';
|
|
|
26
26
|
|
|
27
27
|
export const defaultAuthConfig: AuthConfig = {
|
|
28
28
|
ensureFreshness: true,
|
|
29
|
-
persist:
|
|
30
|
-
ssr:
|
|
29
|
+
persist: false,
|
|
30
|
+
ssr: false,
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
export const AuthConfigContext = createContext<AuthConfig>(defaultAuthConfig);
|
|
@@ -57,7 +57,7 @@ export const AfterAuth: FC<AfterAuthProps> = ({ children }: AfterAuthProps) => {
|
|
|
57
57
|
}, [authState.idToken]);
|
|
58
58
|
|
|
59
59
|
useEffect(() => {
|
|
60
|
-
if (authConfig.debug && authState.refreshToken) logger.debug(authState.refreshToken);
|
|
60
|
+
if (authConfig.debug && authState.refreshToken) logger.debug('refreshToken', authState.refreshToken);
|
|
61
61
|
}, [authState.refreshToken]);
|
|
62
62
|
|
|
63
63
|
useEffect(() => {
|
package/src/provider/index.tsx
CHANGED
|
@@ -23,30 +23,83 @@
|
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
import React, { useMemo } from 'react';
|
|
26
|
+
import type { AuthClientEvent, AuthClientError, AuthClientTokens } from '@bitspur/react-keycloak-core';
|
|
26
27
|
import type { AuthConfig } from '../authConfig';
|
|
27
|
-
import type { FC } from 'react';
|
|
28
|
-
import type {
|
|
28
|
+
import type { FC, ComponentType, ReactNode } from 'react';
|
|
29
|
+
import type { KeycloakConfig, KeycloakInitOptions } from '@bitspur/keycloak-js';
|
|
29
30
|
import { AuthConfigContext, defaultAuthConfig } from '../authConfig';
|
|
30
31
|
import { KeycloakProvider } from './keycloakProvider';
|
|
32
|
+
// @ts-ignore
|
|
33
|
+
import { config } from 'app/config';
|
|
31
34
|
|
|
32
|
-
export interface AuthProviderProps
|
|
33
|
-
|
|
35
|
+
export interface AuthProviderProps
|
|
36
|
+
extends Partial<Omit<AuthConfig, 'persist'>>,
|
|
37
|
+
Omit<KeycloakConfig, 'url'>,
|
|
38
|
+
KeycloakInitOptions {
|
|
39
|
+
children: ReactNode;
|
|
40
|
+
cookies?: unknown;
|
|
41
|
+
disabled?: boolean;
|
|
42
|
+
baseUrl?: string;
|
|
43
|
+
loadingComponent?: ComponentType;
|
|
44
|
+
onEvent?: (eventType: AuthClientEvent, error?: AuthClientError) => void;
|
|
45
|
+
onTokens?: (tokens: AuthClientTokens) => void;
|
|
34
46
|
}
|
|
35
47
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
48
|
+
const persist = config.get('KEYCLOAK_PERSIST') === '1';
|
|
49
|
+
|
|
50
|
+
export const AuthProvider: FC<AuthProviderProps> = ({
|
|
51
|
+
// keycloak config
|
|
52
|
+
realm,
|
|
53
|
+
clientId,
|
|
54
|
+
baseUrl,
|
|
55
|
+
// auth config
|
|
56
|
+
debug,
|
|
57
|
+
ensureFreshness,
|
|
58
|
+
loginRoute,
|
|
59
|
+
messageHandlerKeys,
|
|
60
|
+
ssr,
|
|
61
|
+
// props
|
|
62
|
+
children,
|
|
63
|
+
cookies,
|
|
64
|
+
disabled,
|
|
65
|
+
loadingComponent,
|
|
66
|
+
onEvent,
|
|
67
|
+
onTokens,
|
|
68
|
+
...keycloakInitOptions
|
|
69
|
+
}: AuthProviderProps) => {
|
|
70
|
+
const authConfig = useMemo(
|
|
39
71
|
() => ({
|
|
40
72
|
...defaultAuthConfig,
|
|
41
|
-
|
|
42
|
-
|
|
73
|
+
debug,
|
|
74
|
+
ensureFreshness,
|
|
75
|
+
loginRoute,
|
|
76
|
+
messageHandlerKeys,
|
|
77
|
+
persist: ssr ? false : persist,
|
|
78
|
+
ssr,
|
|
43
79
|
}),
|
|
44
|
-
[],
|
|
80
|
+
[debug, ensureFreshness, loginRoute, messageHandlerKeys, persist, ssr],
|
|
45
81
|
);
|
|
46
82
|
|
|
83
|
+
if (disabled) {
|
|
84
|
+
return <AuthConfigContext.Provider value={authConfig}>{children}</AuthConfigContext.Provider>;
|
|
85
|
+
}
|
|
86
|
+
|
|
47
87
|
return (
|
|
48
|
-
<AuthConfigContext.Provider value={
|
|
49
|
-
<KeycloakProvider
|
|
88
|
+
<AuthConfigContext.Provider value={authConfig}>
|
|
89
|
+
<KeycloakProvider
|
|
90
|
+
cookies={cookies}
|
|
91
|
+
keycloakConfig={{
|
|
92
|
+
realm,
|
|
93
|
+
clientId,
|
|
94
|
+
url: baseUrl,
|
|
95
|
+
}}
|
|
96
|
+
keycloakInitOptions={keycloakInitOptions}
|
|
97
|
+
loadingComponent={loadingComponent}
|
|
98
|
+
onEvent={onEvent}
|
|
99
|
+
onTokens={onTokens}
|
|
100
|
+
>
|
|
101
|
+
{children}
|
|
102
|
+
</KeycloakProvider>
|
|
50
103
|
</AuthConfigContext.Provider>
|
|
51
104
|
);
|
|
52
105
|
};
|
|
@@ -32,7 +32,7 @@ import { KeycloakProvider as ExpoKeycloakProvider } from 'expo-keycloak-auth';
|
|
|
32
32
|
export const KeycloakProvider: FC<KeycloakProviderProps> = ({ children, keycloakConfig }: KeycloakProviderProps) => {
|
|
33
33
|
const clonedKeycloakConfig = {
|
|
34
34
|
...(keycloakConfig as Omit<KeycloakConfig, 'baseUrl'>),
|
|
35
|
-
url: keycloakConfig.
|
|
35
|
+
url: keycloakConfig.url,
|
|
36
36
|
};
|
|
37
37
|
// @ts-ignore
|
|
38
38
|
delete keycloakConfig.baseUrl;
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
import Keycloak from '@bitspur/keycloak-js';
|
|
26
26
|
import React, { useMemo, useEffect, useState, useCallback } from 'react';
|
|
27
27
|
import type { AuthClientEvent, AuthClientError, AuthClientTokens } from '@bitspur/react-keycloak-core';
|
|
28
|
-
import type { KeycloakInitOptions } from '@bitspur/keycloak-js';
|
|
28
|
+
import type { KeycloakInitOptions, KeycloakConfig } from '@bitspur/keycloak-js';
|
|
29
29
|
import type { ReactNode, ComponentType } from 'react';
|
|
30
30
|
import { AfterAuth } from './afterAuth';
|
|
31
31
|
import { MultiPlatform } from 'multiplatform.one';
|
|
@@ -38,8 +38,6 @@ import { useRouter } from 'next/router';
|
|
|
38
38
|
export interface KeycloakProviderProps {
|
|
39
39
|
children: ReactNode;
|
|
40
40
|
cookies?: unknown;
|
|
41
|
-
debug?: boolean;
|
|
42
|
-
disabled?: boolean;
|
|
43
41
|
keycloakConfig: KeycloakConfig;
|
|
44
42
|
keycloakInitOptions?: KeycloakInitOptions;
|
|
45
43
|
loadingComponent?: ComponentType;
|
|
@@ -52,35 +50,42 @@ const logger = console;
|
|
|
52
50
|
export function KeycloakProvider({
|
|
53
51
|
children,
|
|
54
52
|
cookies,
|
|
55
|
-
debug,
|
|
56
53
|
keycloakConfig,
|
|
57
54
|
keycloakInitOptions,
|
|
58
55
|
loadingComponent,
|
|
59
56
|
onEvent,
|
|
60
57
|
onTokens,
|
|
61
58
|
}: KeycloakProviderProps) {
|
|
59
|
+
const { debug, ensureFreshness, persist, messageHandlerKeys, ssr } = useAuthConfig();
|
|
62
60
|
const authState = useAuthState();
|
|
63
61
|
const LoadingComponent = loadingComponent || (() => <>{debug ? 'authenticating' : null}</>);
|
|
64
62
|
const { query } = MultiPlatform.isNext ? useRouter() : { query: {} };
|
|
65
|
-
const
|
|
63
|
+
const [refreshToken, setRefreshToken] = useState<string | boolean>(
|
|
64
|
+
validToken(
|
|
65
|
+
(ensureFreshness &&
|
|
66
|
+
(('refreshToken' in query && (query.refreshToken?.toString() || true)) ||
|
|
67
|
+
(persist && authState.refreshToken))) ||
|
|
68
|
+
false,
|
|
69
|
+
),
|
|
70
|
+
);
|
|
66
71
|
const [idToken, setIdToken] = useState<string | boolean>(
|
|
67
|
-
(
|
|
72
|
+
validToken(
|
|
73
|
+
('idToken' in query && (query.idToken?.toString() || true)) || (persist && authState.idToken) || false,
|
|
74
|
+
refreshToken,
|
|
75
|
+
),
|
|
68
76
|
);
|
|
69
77
|
const [token, setToken] = useState<string | boolean>(
|
|
70
|
-
(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
(('refreshToken' in query && (query.refreshToken?.toString() || true)) ||
|
|
75
|
-
(authConfig.persist && authState.refreshToken))) ||
|
|
76
|
-
false,
|
|
78
|
+
validToken(
|
|
79
|
+
('token' in query && (query.token?.toString() || true)) || (persist && authState.token) || false,
|
|
80
|
+
refreshToken,
|
|
81
|
+
),
|
|
77
82
|
);
|
|
78
83
|
const explicitToken = 'idToken' in query || 'token' in query || 'refreshToken' in query;
|
|
79
84
|
|
|
80
85
|
useEffect(() => {
|
|
81
86
|
if (token !== true && refreshToken !== true && idToken !== true) return;
|
|
82
87
|
if (debug) logger.debug('post message', { type: 'LOADED' });
|
|
83
|
-
(
|
|
88
|
+
(messageHandlerKeys || []).forEach((key: string) => {
|
|
84
89
|
window?.webkit?.messageHandlers?.[key]?.postMessage(JSON.stringify({ type: 'LOADED' }));
|
|
85
90
|
});
|
|
86
91
|
window?.ReactNativeWebView?.postMessage(JSON.stringify({ type: 'LOADED' }));
|
|
@@ -88,9 +93,9 @@ export function KeycloakProvider({
|
|
|
88
93
|
}, []);
|
|
89
94
|
|
|
90
95
|
useEffect(() => {
|
|
91
|
-
if (
|
|
96
|
+
if (refreshToken !== true) return;
|
|
92
97
|
const messageCallback = (e: MessageEvent<any>) => {
|
|
93
|
-
let data = e?.data;
|
|
98
|
+
let data = e?.data || null;
|
|
94
99
|
if (typeof data === 'string') {
|
|
95
100
|
try {
|
|
96
101
|
data = JSON.parse(data);
|
|
@@ -99,15 +104,15 @@ export function KeycloakProvider({
|
|
|
99
104
|
if (debug) logger.debug('received message', data);
|
|
100
105
|
const message: MessageSchema = data;
|
|
101
106
|
if (!message.type) return;
|
|
102
|
-
if (message.type.toUpperCase() === '
|
|
103
|
-
if (debug) logger.debug('setting token', message.payload);
|
|
104
|
-
|
|
107
|
+
if (message.type.toUpperCase() === 'REFRESH_TOKEN' && message.payload) {
|
|
108
|
+
if (debug) logger.debug('setting refresh token', message.payload);
|
|
109
|
+
setRefreshToken(validToken(message.payload));
|
|
105
110
|
}
|
|
106
111
|
};
|
|
107
112
|
if (debug) {
|
|
108
113
|
logger.debug('listening for message', {
|
|
109
|
-
type: '
|
|
110
|
-
payload: '<
|
|
114
|
+
type: 'REFRESH_TOKEN',
|
|
115
|
+
payload: '<some_refresh_token>',
|
|
111
116
|
});
|
|
112
117
|
}
|
|
113
118
|
window.addEventListener('message', messageCallback);
|
|
@@ -117,9 +122,9 @@ export function KeycloakProvider({
|
|
|
117
122
|
}, []);
|
|
118
123
|
|
|
119
124
|
useEffect(() => {
|
|
120
|
-
if (
|
|
125
|
+
if (token !== true) return;
|
|
121
126
|
const messageCallback = (e: MessageEvent<any>) => {
|
|
122
|
-
let data = e?.data;
|
|
127
|
+
let data = e?.data || null;
|
|
123
128
|
if (typeof data === 'string') {
|
|
124
129
|
try {
|
|
125
130
|
data = JSON.parse(data);
|
|
@@ -128,15 +133,15 @@ export function KeycloakProvider({
|
|
|
128
133
|
if (debug) logger.debug('received message', data);
|
|
129
134
|
const message: MessageSchema = data;
|
|
130
135
|
if (!message.type) return;
|
|
131
|
-
if (message.type.toUpperCase() === '
|
|
132
|
-
if (debug) logger.debug('setting
|
|
133
|
-
|
|
136
|
+
if (message.type.toUpperCase() === 'TOKEN' && message.payload) {
|
|
137
|
+
if (debug) logger.debug('setting token', message.payload);
|
|
138
|
+
setToken(validToken(message.payload, refreshToken));
|
|
134
139
|
}
|
|
135
140
|
};
|
|
136
141
|
if (debug) {
|
|
137
142
|
logger.debug('listening for message', {
|
|
138
|
-
type: '
|
|
139
|
-
payload: '<
|
|
143
|
+
type: 'TOKEN',
|
|
144
|
+
payload: '<some_token>',
|
|
140
145
|
});
|
|
141
146
|
}
|
|
142
147
|
window.addEventListener('message', messageCallback);
|
|
@@ -146,9 +151,9 @@ export function KeycloakProvider({
|
|
|
146
151
|
}, []);
|
|
147
152
|
|
|
148
153
|
useEffect(() => {
|
|
149
|
-
if (
|
|
154
|
+
if (idToken !== true) return;
|
|
150
155
|
const messageCallback = (e: MessageEvent<any>) => {
|
|
151
|
-
let data = e?.data;
|
|
156
|
+
let data = e?.data || null;
|
|
152
157
|
if (typeof data === 'string') {
|
|
153
158
|
try {
|
|
154
159
|
data = JSON.parse(data);
|
|
@@ -157,15 +162,15 @@ export function KeycloakProvider({
|
|
|
157
162
|
if (debug) logger.debug('received message', data);
|
|
158
163
|
const message: MessageSchema = data;
|
|
159
164
|
if (!message.type) return;
|
|
160
|
-
if (message.type.toUpperCase() === '
|
|
161
|
-
if (debug) logger.debug('setting
|
|
162
|
-
|
|
165
|
+
if (message.type.toUpperCase() === 'ID_TOKEN' && message.payload) {
|
|
166
|
+
if (debug) logger.debug('setting id token', message.payload);
|
|
167
|
+
setIdToken(validToken(message.payload, refreshToken));
|
|
163
168
|
}
|
|
164
169
|
};
|
|
165
170
|
if (debug) {
|
|
166
171
|
logger.debug('listening for message', {
|
|
167
|
-
type: '
|
|
168
|
-
payload: '<
|
|
172
|
+
type: 'ID_TOKEN',
|
|
173
|
+
payload: '<some_id_token>',
|
|
169
174
|
});
|
|
170
175
|
}
|
|
171
176
|
window.addEventListener('message', messageCallback);
|
|
@@ -188,7 +193,7 @@ export function KeycloakProvider({
|
|
|
188
193
|
() =>
|
|
189
194
|
typeof window !== 'undefined' &&
|
|
190
195
|
new Keycloak({
|
|
191
|
-
url: keycloakConfig.
|
|
196
|
+
url: keycloakConfig.url,
|
|
192
197
|
realm: keycloakConfig.realm,
|
|
193
198
|
clientId: keycloakConfig.clientId,
|
|
194
199
|
}),
|
|
@@ -214,11 +219,13 @@ export function KeycloakProvider({
|
|
|
214
219
|
}, [keycloakInitOptions, token, refreshToken, idToken]);
|
|
215
220
|
|
|
216
221
|
if (token === true || idToken === true || refreshToken === true) return <LoadingComponent />;
|
|
217
|
-
if (cookies &&
|
|
222
|
+
if (cookies && ssr) {
|
|
218
223
|
return (
|
|
219
224
|
// @ts-ignore
|
|
220
225
|
<SSRKeycloakProvider
|
|
221
226
|
LoadingComponent={<LoadingComponent />}
|
|
227
|
+
// keycloak-js already handles refreshing tokens
|
|
228
|
+
autoRefreshToken={false}
|
|
222
229
|
initOptions={initOptions}
|
|
223
230
|
onEvent={handleEvent}
|
|
224
231
|
onTokens={onTokens}
|
|
@@ -226,7 +233,7 @@ export function KeycloakProvider({
|
|
|
226
233
|
keycloakConfig={{
|
|
227
234
|
clientId: keycloakConfig.clientId,
|
|
228
235
|
realm: keycloakConfig.realm,
|
|
229
|
-
url: keycloakConfig.
|
|
236
|
+
url: keycloakConfig.url,
|
|
230
237
|
}}
|
|
231
238
|
>
|
|
232
239
|
<AfterAuth>{children}</AfterAuth>
|
|
@@ -238,6 +245,8 @@ export function KeycloakProvider({
|
|
|
238
245
|
<ReactKeycloakProvider
|
|
239
246
|
LoadingComponent={<LoadingComponent />}
|
|
240
247
|
authClient={keycloak}
|
|
248
|
+
// keycloak-js already handles refreshing tokens
|
|
249
|
+
autoRefreshToken={false}
|
|
241
250
|
initOptions={initOptions}
|
|
242
251
|
onEvent={handleEvent}
|
|
243
252
|
onTokens={onTokens}
|
|
@@ -247,11 +256,23 @@ export function KeycloakProvider({
|
|
|
247
256
|
);
|
|
248
257
|
}
|
|
249
258
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
259
|
+
function validToken(token: string | boolean, refreshToken?: string | boolean) {
|
|
260
|
+
if (typeof token !== 'string') return token;
|
|
261
|
+
if (refreshToken) {
|
|
262
|
+
if (refreshToken === true || isTokenValid(refreshToken)) return token;
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
return isTokenValid(token) ? token : false;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function isTokenValid(token: string) {
|
|
269
|
+
try {
|
|
270
|
+
const { exp } = JSON.parse(Buffer.from(token.split('.')?.[1] || '', 'base64').toString() || '{}');
|
|
271
|
+
return Math.floor(Date.now() / 1000) <= exp;
|
|
272
|
+
} catch (err) {
|
|
273
|
+
if (err instanceof SyntaxError) return false;
|
|
274
|
+
throw err;
|
|
275
|
+
}
|
|
255
276
|
}
|
|
256
277
|
|
|
257
278
|
export const defaultKeycloakInitOptions: KeycloakInitOptions = {
|