@bmc-soft/keycloak-auth 1.0.11 → 2.0.1
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/README.md +115 -59
- package/dist/_lib/types/confirmAuthPhase.d.ts +1 -2
- package/dist/_lib/types/confirmAuthPhase.d.ts.map +1 -1
- package/dist/_lib/types/confirmAuthPhase.js +1 -2
- package/dist/_lib/types/confirmAuthPhase.js.map +1 -1
- package/dist/axios/adapters/KeycloakTokenProvider.js +8 -8
- package/dist/axios/adapters/KeycloakTokenProvider.js.map +1 -1
- package/dist/axios/interceptors.js +2 -2
- package/dist/axios/interceptors.js.map +1 -1
- package/dist/context/KeycloakConfigContext.d.ts +17 -1
- package/dist/context/KeycloakConfigContext.d.ts.map +1 -1
- package/dist/context/KeycloakConfigContext.js +36 -2
- package/dist/context/KeycloakConfigContext.js.map +1 -1
- package/dist/context/KeycloakInstanceContext.d.ts +2 -0
- package/dist/context/KeycloakInstanceContext.d.ts.map +1 -1
- package/dist/context/KeycloakInstanceContext.js +59 -16
- package/dist/context/KeycloakInstanceContext.js.map +1 -1
- package/dist/context/KeycloakProvider.d.ts +7 -1
- package/dist/context/KeycloakProvider.d.ts.map +1 -1
- package/dist/context/KeycloakProvider.js +3 -3
- package/dist/context/KeycloakProvider.js.map +1 -1
- package/dist/context/ReauthContext.d.ts +3 -1
- package/dist/context/ReauthContext.d.ts.map +1 -1
- package/dist/context/ReauthContext.js +6 -2
- package/dist/context/ReauthContext.js.map +1 -1
- package/dist/context/TokenContext.d.ts +2 -0
- package/dist/context/TokenContext.d.ts.map +1 -1
- package/dist/context/TokenContext.js +14 -6
- package/dist/context/TokenContext.js.map +1 -1
- package/dist/context/index.d.ts +2 -2
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +1 -1
- package/dist/context/index.js.map +1 -1
- package/dist/context/reauthRequiredRef.d.ts +2 -1
- package/dist/context/reauthRequiredRef.d.ts.map +1 -1
- package/dist/context/reauthRequiredRef.js.map +1 -1
- package/dist/core/adapter.d.ts.map +1 -1
- package/dist/core/adapter.js +30 -4
- package/dist/core/adapter.js.map +1 -1
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/sessionPolicy.d.ts +21 -0
- package/dist/core/sessionPolicy.d.ts.map +1 -0
- package/dist/core/sessionPolicy.js +63 -0
- package/dist/core/sessionPolicy.js.map +1 -0
- package/dist/core/types.d.ts +14 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/hooks/useKeycloakAuth.d.ts +3 -0
- package/dist/hooks/useKeycloakAuth.d.ts.map +1 -1
- package/dist/hooks/useKeycloakAuth.js +12 -7
- package/dist/hooks/useKeycloakAuth.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/screens/AuthPage/AuthPage.d.ts +2 -0
- package/dist/screens/AuthPage/AuthPage.d.ts.map +1 -1
- package/dist/screens/AuthPage/AuthPage.js +12 -15
- package/dist/screens/AuthPage/AuthPage.js.map +1 -1
- package/dist/screens/ConfirmAuthPage/ConfirmAuthPage.d.ts +2 -1
- package/dist/screens/ConfirmAuthPage/ConfirmAuthPage.d.ts.map +1 -1
- package/dist/screens/ConfirmAuthPage/ConfirmAuthPage.js +67 -52
- package/dist/screens/ConfirmAuthPage/ConfirmAuthPage.js.map +1 -1
- package/dist/screens/ConfirmAuthPage/index.d.ts +1 -0
- package/dist/screens/ConfirmAuthPage/index.d.ts.map +1 -1
- package/dist/screens/index.d.ts +1 -0
- package/dist/screens/index.d.ts.map +1 -1
- package/dist/storage/credentialStorage.d.ts +8 -0
- package/dist/storage/credentialStorage.d.ts.map +1 -1
- package/dist/storage/credentialStorage.js +99 -1
- package/dist/storage/credentialStorage.js.map +1 -1
- package/dist/storage/tokenStorage.d.ts +10 -0
- package/dist/storage/tokenStorage.d.ts.map +1 -1
- package/dist/storage/tokenStorage.js +30 -8
- package/dist/storage/tokenStorage.js.map +1 -1
- package/dist/ui/LogoutConfirmSheet/LogoutConfirmSheet.js +4 -2
- package/dist/ui/LogoutConfirmSheet/LogoutConfirmSheet.js.map +1 -1
- package/dist/ui/NumberPad/NumberPad.d.ts.map +1 -1
- package/dist/ui/NumberPad/NumberPad.js +16 -9
- package/dist/ui/NumberPad/NumberPad.js.map +1 -1
- package/dist/ui/PINConfirm/PINConfirm.d.ts.map +1 -1
- package/dist/ui/PINConfirm/PINConfirm.js +7 -7
- package/dist/ui/PINConfirm/PINConfirm.js.map +1 -1
- package/dist/ui/PINSetup/stages/BiometryStage.d.ts.map +1 -1
- package/dist/ui/PINSetup/stages/BiometryStage.js +6 -2
- package/dist/ui/PINSetup/stages/BiometryStage.js.map +1 -1
- package/dist/ui/PINSetup/styles.d.ts +0 -1
- package/dist/ui/PINSetup/styles.d.ts.map +1 -1
- package/dist/ui/PINSetup/styles.js +0 -1
- package/dist/ui/PINSetup/styles.js.map +1 -1
- package/dist/ui/WebViewLogin/WebViewLogin.d.ts.map +1 -1
- package/dist/ui/WebViewLogin/WebViewLogin.js +2 -2
- package/dist/ui/WebViewLogin/WebViewLogin.js.map +1 -1
- package/dist/widgets/ReauthBottomSheet/ReauthBottomSheet.d.ts +2 -0
- package/dist/widgets/ReauthBottomSheet/ReauthBottomSheet.d.ts.map +1 -1
- package/dist/widgets/ReauthBottomSheet/ReauthBottomSheet.js +12 -5
- package/dist/widgets/ReauthBottomSheet/ReauthBottomSheet.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -60,9 +60,9 @@ import { AuthPage } from '@bmc-soft/keycloak-auth';
|
|
|
60
60
|
const LoginScreen = () => (
|
|
61
61
|
<AuthPage
|
|
62
62
|
logo={require('./logo.png')}
|
|
63
|
-
onSuccess={(
|
|
64
|
-
// Сохраняем
|
|
65
|
-
|
|
63
|
+
onSuccess={(accessToken) => {
|
|
64
|
+
// Сохраняем access token в сессию приложения и переходим
|
|
65
|
+
Session.events.onLogin(accessToken);
|
|
66
66
|
navigation.replace('Home');
|
|
67
67
|
}}
|
|
68
68
|
onError={(err) => console.error(err)}
|
|
@@ -74,6 +74,18 @@ const LoginScreen = () => (
|
|
|
74
74
|
|
|
75
75
|
Если используете axios, задайте провайдер токенов (см. [Axios](#axios)) и вызовите `setupAxiosInterceptors` с `tokenProvider` и `onReauthRequired`. Провайдер обычно настраивается внутри KeycloakProvider после инициализации keycloak (см. [Интеграция](#интеграция)).
|
|
76
76
|
|
|
77
|
+
### Требования к Keycloak client
|
|
78
|
+
|
|
79
|
+
Для нового mobile flow настройте Keycloak client как:
|
|
80
|
+
|
|
81
|
+
- **Client type**: public
|
|
82
|
+
- **Flow**: Authorization Code / Standard Flow
|
|
83
|
+
- **PKCE**: required, `S256`
|
|
84
|
+
- **Scope**: разрешён `offline_access`
|
|
85
|
+
- **Redirect URI**: только URI приложения, например `myapp://callback`
|
|
86
|
+
|
|
87
|
+
`client_secret` не передаётся и не хранится в React Native приложении.
|
|
88
|
+
|
|
77
89
|
---
|
|
78
90
|
|
|
79
91
|
## Провайдер и конфигурация
|
|
@@ -83,10 +95,12 @@ const LoginScreen = () => (
|
|
|
83
95
|
| Проп | Тип | Обязательный | Описание |
|
|
84
96
|
|------|-----|--------------|----------|
|
|
85
97
|
| `children` | ReactNode | да | Дерево приложения |
|
|
86
|
-
| `config` | KeycloakConfigWith2FA | да | `url`, `realm`, `clientId`;
|
|
98
|
+
| `config` | KeycloakConfigWith2FA | да | `url`, `realm`, `clientId`; `clientId2fa` оставлен для legacy-сценариев, новый мобильный flow использует один public client + PKCE |
|
|
87
99
|
| `redirectUri` | string | да | URI OAuth callback (например `myapp://callback`) |
|
|
88
100
|
| `theme` | KeycloakTheme | нет | Цвета, шрифты, LoaderComponent, компоненты кнопок |
|
|
89
101
|
| `onTokens` | (tokens: KeycloakTokens) => void | нет | Вызывается при изменении токенов (логин, refresh, logout) |
|
|
102
|
+
| `offlineAccessEnabled` | boolean | нет | Запрашивать `offline_access` в login URL; по умолчанию `true` |
|
|
103
|
+
| `backgroundReauth` | `{ enabled?: boolean; thresholdMs?: number; internalNetworkMode?: 'ip-host-is-internal' }` | нет | Настройки PIN/биометрии после возврата из background; по умолчанию `enabled: true`, `thresholdMs: 60000` |
|
|
90
104
|
| `autoRefreshToken` | boolean | нет | По умолчанию `true` |
|
|
91
105
|
| `autoRefreshTokenMinValidity` | number | нет | За сколько секунд до истечения вызывать refresh; по умолчанию `5` |
|
|
92
106
|
| `onReauthRequired` | () => void | нет | Вызывается при ошибке обновления токена (например показать экран реавторизации) |
|
|
@@ -124,20 +138,26 @@ const LoginScreen = () => (
|
|
|
124
138
|
|
|
125
139
|
#### ConfirmAuthPage
|
|
126
140
|
|
|
127
|
-
Подтверждение сессии:
|
|
141
|
+
Подтверждение сессии: сначала PIN/биометрия, затем продолжение с текущим access token или refresh через offline token. Если repeat-login не может восстановить токены через offline token, открывается обычный Keycloak login. Скрытый ввод username/password в новом flow не используется.
|
|
142
|
+
|
|
143
|
+
Режимы:
|
|
144
|
+
|
|
145
|
+
- `login` — повторный вход в приложение; при невозможности refresh открывает обычный Keycloak login.
|
|
146
|
+
- `unlock` — локальная разблокировка после background; refresh выполняется только если access token уже истёк.
|
|
147
|
+
- `reauth` — повторная авторизация после 401; refresh через offline token обязателен.
|
|
128
148
|
|
|
129
149
|
| Проп | Тип | По умолчанию | Описание |
|
|
130
150
|
|------|-----|--------------|----------|
|
|
131
|
-
| `onSuccess` | () => void | — |
|
|
151
|
+
| `onSuccess` | () => void | — | Успешное локальное подтверждение и восстановление/проверка access token |
|
|
132
152
|
| `onError` | (error: Error) => void | — | Например неверный PIN |
|
|
133
153
|
| `onLogout` | () => void | — | После очистки хранилища пакета; в приложении — очистить сессию и перейти на экран входа |
|
|
154
|
+
| `mode` | `'login' \| 'unlock' \| 'reauth'` | `"login"` | Сценарий: повторный вход, unlock после background или reauth после 401 |
|
|
134
155
|
| `logoutText` | string | "Выйти из аккаунта" | Текст ссылки «Выйти» |
|
|
135
156
|
| `logo`, `logoHeight`, `logoWidth` | — | 80 | Логотип |
|
|
136
157
|
| `pinLength` | number | 4 | Длина PIN |
|
|
137
158
|
| `allowBiometry`, `autoShowBiometry` | boolean | true | Биометрия |
|
|
138
159
|
| `title`, `description` | string | — | Заголовок и описание блока PIN |
|
|
139
160
|
| `style` | ViewStyle | — | Стиль контейнера |
|
|
140
|
-
| `webViewTimeoutMs` | number | 3000 | Задержка (мс) в фазе webview_detect перед переходом на PIN |
|
|
141
161
|
|
|
142
162
|
### Виджеты
|
|
143
163
|
|
|
@@ -152,10 +172,9 @@ BottomSheet с подтверждением PIN для реавторизаци
|
|
|
152
172
|
| `onError` | (error: Error) => void | — | Ошибка ввода PIN |
|
|
153
173
|
| `pinLength` | number | 4 | Длина PIN |
|
|
154
174
|
| `allowBiometry`, `autoShowBiometry` | boolean | true | Биометрия |
|
|
175
|
+
| `mode` | `'login' \| 'unlock' \| 'reauth'` | авто | Если не передан, `background` открывается как `unlock`, остальные причины как `reauth` |
|
|
155
176
|
| `title` | string | "Подтвердите вход" | Заголовок |
|
|
156
177
|
| `description` | string | "Введите PIN-код" | Описание |
|
|
157
|
-
| `footer` | ReactNode | — | Опциональный футер |
|
|
158
|
-
| `snapPointPercentage` | number | 50 | Высота sheet в % |
|
|
159
178
|
|
|
160
179
|
### Кнопки выхода
|
|
161
180
|
|
|
@@ -187,15 +206,15 @@ BottomSheet с подтверждением PIN для реавторизаци
|
|
|
187
206
|
|
|
188
207
|
Полный API авторизации: инстанс keycloak, токен, login, logout, URL, состояние реавторизации.
|
|
189
208
|
|
|
190
|
-
Возвращает: `keycloak`, `isInitialized`, `isLoading`, `error`, `token`, `isExpired`, `isAuthenticated`, `updateToken`, `login`, `logout`, `loadUserProfile`, `createLoginUrl`, `createLogoutUrl`, `clearTokens`, `isReauthRequired`, `showReauth`, `hideReauth`.
|
|
209
|
+
Возвращает: `keycloak`, `isInitialized`, `isLoading`, `error`, `accessToken`, `token`, `offlineToken`, `refreshToken`, `isExpired`, `isAuthenticated`, `updateToken`, `login`, `logout`, `loadUserProfile`, `createLoginUrl`, `createLogoutUrl`, `clearTokens`, `isReauthRequired`, `showReauth`, `hideReauth`.
|
|
191
210
|
|
|
192
211
|
### useToken()
|
|
193
212
|
|
|
194
|
-
Доступ только к токенам (меньше ре-рендеров). Возвращает: `token`, `refreshToken`, `idToken`, `isExpired`, `updateToken`, `clearTokens`.
|
|
213
|
+
Доступ только к токенам (меньше ре-рендеров). Возвращает: `accessToken`, `token`, `offlineToken`, `refreshToken`, `idToken`, `isExpired`, `updateToken`, `clearTokens`.
|
|
195
214
|
|
|
196
215
|
### useReauth()
|
|
197
216
|
|
|
198
|
-
Состояние UI реавторизации. Возвращает: `isReauthRequired`, `showReauth`, `hideReauth`.
|
|
217
|
+
Состояние UI реавторизации. Возвращает: `isReauthRequired`, `reauthReason`, `showReauth`, `hideReauth`.
|
|
199
218
|
|
|
200
219
|
**Состояние isReauthRequired:**
|
|
201
220
|
|
|
@@ -209,7 +228,7 @@ BottomSheet с подтверждением PIN для реавторизаци
|
|
|
209
228
|
|
|
210
229
|
Возвращает: `screen: 'login' | 'confirm' | null`, `isLoading`, `error`.
|
|
211
230
|
|
|
212
|
-
Опции: `shouldShowConfirm?: () => Promise<boolean>` — переопределить стандартную проверку (наличие
|
|
231
|
+
Опции: `shouldShowConfirm?: () => Promise<boolean>` — переопределить стандартную проверку (наличие offline token и PIN).
|
|
213
232
|
|
|
214
233
|
### useKeycloakTheme()
|
|
215
234
|
|
|
@@ -221,15 +240,15 @@ BottomSheet с подтверждением PIN для реавторизаци
|
|
|
221
240
|
|
|
222
241
|
### tokenStorage
|
|
223
242
|
|
|
224
|
-
Хранение токенов в Keychain. API: `getToken`, `saveToken`, `getRefreshToken`, `saveRefreshToken`, `getIdToken`, `saveIdToken`, `getTokens`, `saveTokens`, `clearTokens`, `hasTokens`.
|
|
243
|
+
Хранение токенов в Keychain. API: `getToken`/`getAccessToken`, `saveToken`/`saveAccessToken`, `getRefreshToken`/`getOfflineToken`, `saveRefreshToken`/`saveOfflineToken`, `getIdToken`, `saveIdToken`, `getTokens`, `saveTokens`, `clearTokens`, `hasTokens`.
|
|
225
244
|
|
|
226
|
-
После успешного ConfirmAuthPage
|
|
245
|
+
`refresh_token` из Keycloak при `offline_access` хранится как offline token. Он не отправляется в backend; backend получает только `Authorization: Bearer <accessToken>`. После успешного ConfirmAuthPage вызовите `tokenStorage.getAccessToken()`, чтобы получить текущий access token и обновить сессию приложения.
|
|
227
246
|
|
|
228
247
|
> **Важно**: не храните токены в AsyncStorage. Используйте только Keychain через пакет.
|
|
229
248
|
|
|
230
249
|
### credentialStorage
|
|
231
250
|
|
|
232
|
-
Используется внутри пакета для
|
|
251
|
+
Используется внутри пакета для PIN-verifier и биометрии. Legacy-хранение зашифрованных credentials оставлено для совместимости, но новый offline_access flow не использует username/password для повторного входа.
|
|
233
252
|
|
|
234
253
|
---
|
|
235
254
|
|
|
@@ -264,7 +283,7 @@ BottomSheet с подтверждением PIN для реавторизаци
|
|
|
264
283
|
|
|
265
284
|
### 1. Оборачивание приложения в KeycloakProvider
|
|
266
285
|
|
|
267
|
-
Конфиг и `redirectUri` берут из настроек приложения. Тему (Loader, кнопки, цвета) передайте из темы приложения. В `onTokens` сохраняйте
|
|
286
|
+
Конфиг и `redirectUri` берут из настроек приложения. Тему (Loader, кнопки, цвета) передайте из темы приложения. В `onTokens` сохраняйте access token в хранилище сессии; в `onReauthRequired` показывайте экран реавторизации.
|
|
268
287
|
|
|
269
288
|
**Порядок провайдеров**: если используется `BottomSheetModalProvider` из `@gorhom/bottom-sheet` (например для реавторизации или других модалок), он должен находиться **внутри** KeycloakProvider. Иначе ReauthBottomSheet или ConfirmAuthPage внутри модалки не получат контекст Keycloak. Порядок: `KeycloakProvider` → `BottomSheetModalProvider` → остальное дерево приложения.
|
|
270
289
|
|
|
@@ -297,8 +316,8 @@ export const App = () => (
|
|
|
297
316
|
}}
|
|
298
317
|
redirectUri="myapp://callback"
|
|
299
318
|
theme={theme}
|
|
300
|
-
onTokens={({
|
|
301
|
-
Session.events.onChangeAuthToken(
|
|
319
|
+
onTokens={({ accessToken }) => {
|
|
320
|
+
Session.events.onChangeAuthToken(accessToken);
|
|
302
321
|
}}
|
|
303
322
|
onReauthRequired={() => {
|
|
304
323
|
Session.events.onRequireReauth();
|
|
@@ -313,26 +332,34 @@ export const App = () => (
|
|
|
313
332
|
|
|
314
333
|
### 2. Установка TokenProvider для axios
|
|
315
334
|
|
|
316
|
-
Провайдер токенов настраивается один раз внутри KeycloakProvider после инициализации keycloak
|
|
335
|
+
Провайдер токенов настраивается один раз внутри KeycloakProvider после инициализации keycloak. Он отдаёт backend только access token, а refresh выполняет через offline token.
|
|
317
336
|
|
|
318
337
|
```tsx
|
|
319
|
-
import {
|
|
320
|
-
|
|
338
|
+
import {
|
|
339
|
+
KeycloakTokenProvider,
|
|
340
|
+
setupAxiosInterceptors,
|
|
341
|
+
useKeycloakAuth,
|
|
342
|
+
} from '@bmc-soft/keycloak-auth';
|
|
343
|
+
|
|
344
|
+
const api = axios.create({ baseURL: 'https://api.example.com' });
|
|
321
345
|
|
|
322
346
|
const KeycloakAxiosTokenProviderSetup = ({ children }) => {
|
|
323
347
|
const { keycloak, isInitialized } = useKeycloakAuth();
|
|
324
348
|
|
|
325
349
|
useEffect(() => {
|
|
326
|
-
if (isInitialized
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
350
|
+
if (!isInitialized || !keycloak) return undefined;
|
|
351
|
+
|
|
352
|
+
const { cleanup } = setupAxiosInterceptors(api, {
|
|
353
|
+
tokenProvider: new KeycloakTokenProvider(keycloak),
|
|
354
|
+
onReauthRequired: () => {
|
|
355
|
+
Session.events.onRequireReauth();
|
|
356
|
+
},
|
|
357
|
+
onTokenRefreshed: (accessToken) => {
|
|
358
|
+
Session.events.onChangeAuthToken(accessToken);
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
return cleanup;
|
|
336
363
|
}, [isInitialized, keycloak]);
|
|
337
364
|
|
|
338
365
|
return <>{children}</>;
|
|
@@ -348,29 +375,27 @@ const KeycloakAxiosTokenProviderSetup = ({ children }) => {
|
|
|
348
375
|
</KeycloakProvider>
|
|
349
376
|
```
|
|
350
377
|
|
|
351
|
-
|
|
378
|
+
Если у приложения уже есть свой `tokenProvider`, его методы должны соблюдать тот же контракт:
|
|
352
379
|
|
|
353
380
|
```tsx
|
|
354
|
-
import { setupAxiosInterceptors } from '@bmc-soft/keycloak-auth';
|
|
355
|
-
import { getKeycloakTokenProvider } from './keycloakTokenProvider';
|
|
356
|
-
|
|
357
|
-
const api = axios.create({ baseURL: 'https://api.example.com' });
|
|
358
|
-
|
|
359
381
|
setupAxiosInterceptors(api, {
|
|
360
382
|
tokenProvider: {
|
|
361
|
-
getToken: () =>
|
|
362
|
-
refreshToken: () =>
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
383
|
+
getToken: () => keycloak.token || null,
|
|
384
|
+
refreshToken: async () => {
|
|
385
|
+
await keycloak.updateToken(-1);
|
|
386
|
+
return keycloak.token || null;
|
|
387
|
+
},
|
|
388
|
+
hasRefreshToken: () => Boolean(keycloak.refreshToken),
|
|
389
|
+
},
|
|
390
|
+
onReauthRequired: () => {
|
|
391
|
+
Session.events.onRequireReauth();
|
|
366
392
|
},
|
|
367
|
-
onReauthRequired: () => Session.events.onRequireReauth(),
|
|
368
393
|
});
|
|
369
394
|
```
|
|
370
395
|
|
|
371
396
|
### 3. Стек авторизации (Login + Confirm)
|
|
372
397
|
|
|
373
|
-
Два экрана: Login (AuthPage) и Confirm (ConfirmAuthPage). Начальный маршрут задаётся через `useKeycloakAuthScreen()`: показывать Confirm, если есть
|
|
398
|
+
Два экрана: Login (AuthPage) и Confirm (ConfirmAuthPage). Начальный маршрут задаётся через `useKeycloakAuthScreen()`: показывать Confirm, если есть offline token и PIN, иначе Login.
|
|
374
399
|
|
|
375
400
|
```tsx
|
|
376
401
|
import { useKeycloakAuthScreen, AuthPage, ConfirmAuthPage, tokenStorage } from '@bmc-soft/keycloak-auth';
|
|
@@ -395,7 +420,7 @@ export const AuthStack = () => {
|
|
|
395
420
|
const LoginScreen = () => (
|
|
396
421
|
<AuthPage
|
|
397
422
|
logo={require('./logo.png')}
|
|
398
|
-
onSuccess={(
|
|
423
|
+
onSuccess={(accessToken) => Session.events.onLogin(accessToken)}
|
|
399
424
|
onError={(err) => console.error(err)}
|
|
400
425
|
/>
|
|
401
426
|
);
|
|
@@ -404,8 +429,8 @@ const ConfirmScreen = () => {
|
|
|
404
429
|
const navigation = useNavigation();
|
|
405
430
|
|
|
406
431
|
const onSuccess = useCallback(async () => {
|
|
407
|
-
const
|
|
408
|
-
if (
|
|
432
|
+
const accessToken = await tokenStorage.getAccessToken();
|
|
433
|
+
if (accessToken) Session.events.onLogin(accessToken);
|
|
409
434
|
}, []);
|
|
410
435
|
|
|
411
436
|
return (
|
|
@@ -423,7 +448,7 @@ const ConfirmScreen = () => {
|
|
|
423
448
|
|
|
424
449
|
### 4. Реавторизация при 401
|
|
425
450
|
|
|
426
|
-
При 401 интерцепторы вызывают `onReauthRequired`. Можно использовать `isReauthRequired` из `useKeycloakAuth()` как единственный источник правды для отображения реавторизации. Если используете готовый **ReauthBottomSheet** из пакета, он сам открывается и закрывается по `isReauthRequired` — достаточно смонтировать компонент и при необходимости передать коллбэки (`onSuccess`, `onDismiss`). Для кастомной обёртки (свой BottomSheet и контент) можно использовать **ConfirmAuthPage** и вручную управлять видимостью по `isReauthRequired`. После успешного ввода PIN получите
|
|
451
|
+
При 401 интерцепторы вызывают `onReauthRequired`. Можно использовать `isReauthRequired` из `useKeycloakAuth()` как единственный источник правды для отображения реавторизации. Если используете готовый **ReauthBottomSheet** из пакета, он сам открывается и закрывается по `isReauthRequired` — достаточно смонтировать компонент и при необходимости передать коллбэки (`onSuccess`, `onDismiss`). Для кастомной обёртки (свой BottomSheet и контент) можно использовать **ConfirmAuthPage** и вручную управлять видимостью по `isReauthRequired`. После успешного ввода PIN получите access token из пакета, обновите сессию и закройте реавторизацию. Флаг `isReauthRequired` сбрасывается пакетом автоматически при успехе в ReauthBottomSheet/ConfirmAuthPage; в `onSuccess` достаточно своей логики (обновление сессии, закрытие sheet).
|
|
427
452
|
|
|
428
453
|
Пример с кастомным BottomSheet и ConfirmAuthPage (управление видимостью вручную):
|
|
429
454
|
|
|
@@ -440,9 +465,9 @@ export const CustomReauthSheet = () => {
|
|
|
440
465
|
}, [showReauth]);
|
|
441
466
|
|
|
442
467
|
const handleSuccess = useCallback(async () => {
|
|
443
|
-
const
|
|
444
|
-
if (
|
|
445
|
-
Session.events.onLogin(
|
|
468
|
+
const accessToken = await tokenStorage.getAccessToken();
|
|
469
|
+
if (accessToken) {
|
|
470
|
+
Session.events.onLogin(accessToken);
|
|
446
471
|
Session.events.onReauthCompleted();
|
|
447
472
|
}
|
|
448
473
|
sheetRef.current?.close();
|
|
@@ -450,13 +475,35 @@ export const CustomReauthSheet = () => {
|
|
|
450
475
|
|
|
451
476
|
return (
|
|
452
477
|
<BottomSheet ref={sheetRef} snapPoints={['50%']} enablePanDownToClose>
|
|
453
|
-
<ConfirmAuthPage onSuccess={handleSuccess} pinLength={4} />
|
|
478
|
+
<ConfirmAuthPage mode="reauth" onSuccess={handleSuccess} pinLength={4} />
|
|
454
479
|
</BottomSheet>
|
|
455
480
|
);
|
|
456
481
|
};
|
|
457
482
|
```
|
|
458
483
|
|
|
459
|
-
### 5.
|
|
484
|
+
### 5. PIN/биометрия после возврата из background
|
|
485
|
+
|
|
486
|
+
Если `backgroundReauth.enabled !== false`, библиотека отслеживает `AppState`: при возврате из background/inactive через более чем `thresholdMs` миллисекунд открывается `ReauthBottomSheet`.
|
|
487
|
+
|
|
488
|
+
По умолчанию:
|
|
489
|
+
|
|
490
|
+
```tsx
|
|
491
|
+
<KeycloakProvider
|
|
492
|
+
config={{ url: 'https://sso.example.com', realm: 'my-realm', clientId: 'my-app' }}
|
|
493
|
+
redirectUri="myapp://callback"
|
|
494
|
+
backgroundReauth={{
|
|
495
|
+
enabled: true,
|
|
496
|
+
thresholdMs: 60000,
|
|
497
|
+
internalNetworkMode: 'ip-host-is-internal',
|
|
498
|
+
}}
|
|
499
|
+
>
|
|
500
|
+
<App />
|
|
501
|
+
</KeycloakProvider>
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
Правило внутренней сети: если host в `config.url` является IP-адресом, сеть считается внутренней и background sheet не показывается; если host является DNS-именем, сеть считается внешней.
|
|
505
|
+
|
|
506
|
+
### 6. Выход
|
|
460
507
|
|
|
461
508
|
Используйте LogoutButtonIcon или LogoutButtonText. По нажатию открывается Modal с WebViewLogout; при успешном выходе вызывается `onLogoutSuccess` — там очищайте сессию приложения.
|
|
462
509
|
|
|
@@ -494,17 +541,25 @@ KeycloakProvider → инициализация Keycloak → установка
|
|
|
494
541
|
↓
|
|
495
542
|
useKeycloakAuthScreen → Login (AuthPage) или Confirm (ConfirmAuthPage)
|
|
496
543
|
↓
|
|
497
|
-
|
|
544
|
+
Confirm → PIN/биометрия → текущий access token или refresh через offline token
|
|
545
|
+
↓
|
|
546
|
+
onSuccess → Session.onLogin(accessToken) | onLogout → Session.onLogout + навигация
|
|
498
547
|
↓
|
|
499
|
-
axios 401
|
|
548
|
+
axios 401 / background > 60с вне внутренней сети → ReauthBottomSheet с ConfirmAuthPage
|
|
500
549
|
↓
|
|
501
|
-
|
|
550
|
+
PIN/биометрия → refresh при необходимости → tokenStorage.getAccessToken() → закрыть sheet
|
|
502
551
|
```
|
|
503
552
|
|
|
504
553
|
---
|
|
505
554
|
|
|
506
555
|
## Архитектура и безопасность
|
|
507
556
|
|
|
557
|
+
### Mobile client и offline_access
|
|
558
|
+
|
|
559
|
+
Для мобильного приложения используйте Keycloak public client + Authorization Code Flow with PKCE (`S256`). `client_secret` не должен попадать в React Native приложение; confidential client допустим только через backend/BFF.
|
|
560
|
+
|
|
561
|
+
При `offlineAccessEnabled=true` библиотека добавляет `offline_access` в login scope. Keycloak возвращает offline token в поле `refresh_token`; библиотека хранит его в Keychain как `offlineToken`/`refreshToken` и использует только для получения новых access token.
|
|
562
|
+
|
|
508
563
|
### Иерархия контекстов
|
|
509
564
|
|
|
510
565
|
```
|
|
@@ -520,9 +575,10 @@ KeycloakConfigProvider ← конфиг (редко меняется)
|
|
|
520
575
|
### Безопасность
|
|
521
576
|
|
|
522
577
|
- Токены в OS Keychain (не AsyncStorage)
|
|
523
|
-
- PIN
|
|
578
|
+
- PIN хранится как verifier в Keychain; legacy-хранилище encrypted credentials сохранено только для обратной совместимости
|
|
579
|
+
- Offline token не отправляется в backend и используется только для refresh в Keycloak
|
|
524
580
|
- Запросы по HTTPS
|
|
525
|
-
-
|
|
581
|
+
- Username/password не используются для repeat-login в новом offline_access flow
|
|
526
582
|
|
|
527
583
|
|
|
528
584
|
## Экспорты
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export declare const CONFIRM_AUTH_PHASE: {
|
|
2
|
-
readonly WEBVIEW_DETECT: "webview_detect";
|
|
3
2
|
readonly PIN: "pin";
|
|
4
|
-
readonly
|
|
3
|
+
readonly WEBVIEW_LOGIN: "webview_login";
|
|
5
4
|
};
|
|
6
5
|
export type ConfirmAuthPhase = (typeof CONFIRM_AUTH_PHASE)[keyof typeof CONFIRM_AUTH_PHASE];
|
|
7
6
|
//# sourceMappingURL=confirmAuthPhase.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirmAuthPhase.d.ts","sourceRoot":"","sources":["../../../src/_lib/types/confirmAuthPhase.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"confirmAuthPhase.d.ts","sourceRoot":"","sources":["../../../src/_lib/types/confirmAuthPhase.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,kBAAkB;;;CAGrB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirmAuthPhase.js","sourceRoot":"","sources":["../../../src/_lib/types/confirmAuthPhase.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,
|
|
1
|
+
{"version":3,"file":"confirmAuthPhase.js","sourceRoot":"","sources":["../../../src/_lib/types/confirmAuthPhase.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,GAAG,EAAE,KAAK;IACV,aAAa,EAAE,eAAe;CACtB,CAAC"}
|
|
@@ -10,7 +10,7 @@ export class KeycloakTokenProvider {
|
|
|
10
10
|
return token;
|
|
11
11
|
}
|
|
12
12
|
const tokens = await tokenStorage.getTokens();
|
|
13
|
-
return tokens?.token || null;
|
|
13
|
+
return tokens?.accessToken || tokens?.token || null;
|
|
14
14
|
}
|
|
15
15
|
catch (error) {
|
|
16
16
|
console.error('[KeycloakTokenProvider] Get token error:', error);
|
|
@@ -19,15 +19,15 @@ export class KeycloakTokenProvider {
|
|
|
19
19
|
}
|
|
20
20
|
async refreshToken() {
|
|
21
21
|
try {
|
|
22
|
-
const updated = await this.keycloakClient.updateToken(
|
|
23
|
-
if (!updated) {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
22
|
+
const updated = await this.keycloakClient.updateToken(-1);
|
|
26
23
|
const { token, refreshToken, idToken } = this.keycloakClient;
|
|
27
24
|
if (token) {
|
|
25
|
+
if (!updated) {
|
|
26
|
+
return token;
|
|
27
|
+
}
|
|
28
28
|
await tokenStorage.saveTokens({
|
|
29
|
-
token,
|
|
30
|
-
|
|
29
|
+
accessToken: token,
|
|
30
|
+
offlineToken: refreshToken ?? undefined,
|
|
31
31
|
idToken: idToken ?? undefined,
|
|
32
32
|
});
|
|
33
33
|
return token;
|
|
@@ -45,7 +45,7 @@ export class KeycloakTokenProvider {
|
|
|
45
45
|
return true;
|
|
46
46
|
}
|
|
47
47
|
const tokens = await tokenStorage.getTokens();
|
|
48
|
-
return !!tokens?.refreshToken;
|
|
48
|
+
return !!(tokens?.offlineToken || tokens?.refreshToken);
|
|
49
49
|
}
|
|
50
50
|
catch (error) {
|
|
51
51
|
console.error('[KeycloakTokenProvider] Has refresh token error:', error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeycloakTokenProvider.js","sourceRoot":"","sources":["../../../src/axios/adapters/KeycloakTokenProvider.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAC;AAuBxD,MAAM,OAAO,qBAAqB;IAGhC,YAAY,cAAyC;QACnD,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;IAMD,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC;YAEH,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC;YACxC,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,KAAK,CAAC;YACf,CAAC;YAGD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,SAAS,EAAE,CAAC;YAC9C,OAAO,MAAM,EAAE,KAAK,IAAI,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"KeycloakTokenProvider.js","sourceRoot":"","sources":["../../../src/axios/adapters/KeycloakTokenProvider.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAC;AAuBxD,MAAM,OAAO,qBAAqB;IAGhC,YAAY,cAAyC;QACnD,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;IAMD,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC;YAEH,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC;YACxC,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,KAAK,CAAC;YACf,CAAC;YAGD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,SAAS,EAAE,CAAC;YAC9C,OAAO,MAAM,EAAE,WAAW,IAAI,MAAM,EAAE,KAAK,IAAI,IAAI,CAAC;QACtD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,KAAK,CAAC,CAAC;YACjE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IASD,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;YAG1D,MAAM,EAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAC,GAAG,IAAI,CAAC,cAAc,CAAC;YAC3D,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,OAAO,KAAK,CAAC;gBACf,CAAC;gBAED,MAAM,YAAY,CAAC,UAAU,CAAC;oBAC5B,WAAW,EAAE,KAAK;oBAClB,YAAY,EAAE,YAAY,IAAI,SAAS;oBACvC,OAAO,EAAE,OAAO,IAAI,SAAS;iBAC9B,CAAC,CAAC;gBACH,OAAO,KAAK,CAAC;YACf,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,8CAA8C,EAAE,KAAK,CAAC,CAAC;YACrE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAKD,KAAK,CAAC,eAAe;QACnB,IAAI,CAAC;YAEH,IAAI,IAAI,CAAC,cAAc,CAAC,YAAY,EAAE,CAAC;gBACrC,OAAO,IAAI,CAAC;YACd,CAAC;YAGD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,SAAS,EAAE,CAAC;YAC9C,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,YAAY,IAAI,MAAM,EAAE,YAAY,CAAC,CAAC;QAC1D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,kDAAkD,EAAE,KAAK,CAAC,CAAC;YACzE,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CAOF"}
|
|
@@ -35,7 +35,7 @@ export const setupAxiosInterceptors = (axiosInstance, config = {}) => {
|
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
37
37
|
const tokens = await tokenStorage.getTokens();
|
|
38
|
-
token = tokens?.token || null;
|
|
38
|
+
token = tokens?.accessToken || tokens?.token || null;
|
|
39
39
|
}
|
|
40
40
|
if (token) {
|
|
41
41
|
const formattedToken = tokenProvider?.formatToken?.(token) || `Bearer ${token}`;
|
|
@@ -96,7 +96,7 @@ export const setupAxiosInterceptors = (axiosInstance, config = {}) => {
|
|
|
96
96
|
}
|
|
97
97
|
else {
|
|
98
98
|
const tokens = await tokenStorage.getTokens();
|
|
99
|
-
if (!tokens?.refreshToken) {
|
|
99
|
+
if (!tokens?.offlineToken && !tokens?.refreshToken) {
|
|
100
100
|
throw new Error('No refresh token available');
|
|
101
101
|
}
|
|
102
102
|
console.warn('[AxiosInterceptors] Using deprecated built-in refresh logic. Consider using tokenProvider instead.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interceptors.js","sourceRoot":"","sources":["../../src/axios/interceptors.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,iBAAiB,EAAC,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAC,YAAY,EAAC,MAAM,yBAAyB,CAAC;AAIrD,MAAM,YAAY,GAAG,EAAC,OAAO,EAAE,KAAK,EAAC,CAAC;AACtC,MAAM,WAAW,GAGZ,EAAE,CAAC;AAKR,MAAM,YAAY,GAAG,CAAC,KAAmB,EAAE,QAAuB,IAAI,EAAE,EAAE;IACxE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;QAC5B,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;aAAM,IAAI,KAAK,EAAE,CAAC;YACjB,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;AACzB,CAAC,CAAC;AAKF,MAAM,aAAa,GAAG,CAAC,GAAuB,EAAE,mBAA6B,EAAE,EAAW,EAAE;IAC1F,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,OAAO,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;AACnE,CAAC,CAAC;AAmCF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,aAA4B,EAC5B,SAAkC,EAAE,EACf,EAAE;IACvB,MAAM,EACJ,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,UAAU,GAAG,CAAC,EACd,YAAY,GAAG,IAAI,EACnB,cAAc,GAAG,IAAI,EACrB,gBAAgB,GAAG,EAAE,EACrB,aAAa,EACb,QAAQ,EACR,YAAY,GACb,GAAG,MAAM,CAAC;IAGX,MAAM,oBAAoB,GAAG,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CACjE,KAAK,EAAE,aAAyC,EAAE,EAAE;QAElD,IAAI,aAAa,CAAC,aAAa,CAAC,GAAG,EAAE,gBAAgB,CAAC,EAAE,CAAC;YACvD,OAAO,aAAa,CAAC;QACvB,CAAC;QAGD,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC;gBACH,IAAI,KAAK,GAAkB,IAAI,CAAC;gBAGhC,IAAI,aAAa,EAAE,CAAC;oBAClB,KAAK,GAAG,MAAM,aAAa,CAAC,QAAQ,EAAE,CAAC;gBACzC,CAAC;qBAAM,IAAI,QAAQ,EAAE,CAAC;oBACpB,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;gBAC3B,CAAC;qBAAM,CAAC;oBACN,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,SAAS,EAAE,CAAC;oBAC9C,KAAK,GAAG,MAAM,EAAE,KAAK,IAAI,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"interceptors.js","sourceRoot":"","sources":["../../src/axios/interceptors.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,iBAAiB,EAAC,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAC,YAAY,EAAC,MAAM,yBAAyB,CAAC;AAIrD,MAAM,YAAY,GAAG,EAAC,OAAO,EAAE,KAAK,EAAC,CAAC;AACtC,MAAM,WAAW,GAGZ,EAAE,CAAC;AAKR,MAAM,YAAY,GAAG,CAAC,KAAmB,EAAE,QAAuB,IAAI,EAAE,EAAE;IACxE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;QAC5B,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;aAAM,IAAI,KAAK,EAAE,CAAC;YACjB,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;AACzB,CAAC,CAAC;AAKF,MAAM,aAAa,GAAG,CAAC,GAAuB,EAAE,mBAA6B,EAAE,EAAW,EAAE;IAC1F,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,OAAO,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;AACnE,CAAC,CAAC;AAmCF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,aAA4B,EAC5B,SAAkC,EAAE,EACf,EAAE;IACvB,MAAM,EACJ,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,UAAU,GAAG,CAAC,EACd,YAAY,GAAG,IAAI,EACnB,cAAc,GAAG,IAAI,EACrB,gBAAgB,GAAG,EAAE,EACrB,aAAa,EACb,QAAQ,EACR,YAAY,GACb,GAAG,MAAM,CAAC;IAGX,MAAM,oBAAoB,GAAG,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CACjE,KAAK,EAAE,aAAyC,EAAE,EAAE;QAElD,IAAI,aAAa,CAAC,aAAa,CAAC,GAAG,EAAE,gBAAgB,CAAC,EAAE,CAAC;YACvD,OAAO,aAAa,CAAC;QACvB,CAAC;QAGD,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC;gBACH,IAAI,KAAK,GAAkB,IAAI,CAAC;gBAGhC,IAAI,aAAa,EAAE,CAAC;oBAClB,KAAK,GAAG,MAAM,aAAa,CAAC,QAAQ,EAAE,CAAC;gBACzC,CAAC;qBAAM,IAAI,QAAQ,EAAE,CAAC;oBACpB,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;gBAC3B,CAAC;qBAAM,CAAC;oBACN,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,SAAS,EAAE,CAAC;oBAC9C,KAAK,GAAG,MAAM,EAAE,WAAW,IAAI,MAAM,EAAE,KAAK,IAAI,IAAI,CAAC;gBACvD,CAAC;gBAED,IAAI,KAAK,EAAE,CAAC;oBAEV,MAAM,cAAc,GAAG,aAAa,EAAE,WAAW,EAAE,CAAC,KAAK,CAAC,IAAI,UAAU,KAAK,EAAE,CAAC;oBAChF,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;wBAC3B,aAAa,CAAC,OAAO,GAAG,EAA2C,CAAC;oBACtE,CAAC;oBACD,aAAa,CAAC,OAAO,CAAC,aAAa,GAAG,cAAc,CAAC;gBACvD,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,KAAK,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;QAED,OAAO,aAAa,CAAC;IACvB,CAAC,EACD,CAAC,KAAY,EAAE,EAAE;QACf,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC,CACF,CAAC;IAGF,MAAM,qBAAqB,GAAG,aAAa,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CACnE,QAAQ,CAAC,EAAE,CAAC,QAAQ,EACpB,KAAK,EAAE,KAAiB,EAAE,EAAE;QAC1B,MAAM,eAAe,GAAG,KAAK,CAAC,MAG7B,CAAC;QAGF,IAAI,CAAC,cAAc,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,EAAE,CAAC;YACtD,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;QAGD,IAAI,aAAa,CAAC,eAAe,EAAE,GAAG,EAAE,gBAAgB,CAAC,EAAE,CAAC;YAC1D,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;QAGD,MAAM,UAAU,GAAG,eAAe,CAAC,WAAW,IAAI,CAAC,CAAC;QACpD,IAAI,UAAU,IAAI,UAAU,EAAE,CAAC;YAE7B,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAC;YACjF,iBAAiB,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;YACpC,gBAAgB,EAAE,EAAE,CAAC;YACrB,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;QAGD,eAAe,CAAC,MAAM,GAAG,IAAI,CAAC;QAC9B,eAAe,CAAC,WAAW,GAAG,UAAU,GAAG,CAAC,CAAC;QAG7C,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;YACzB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACrC,WAAW,CAAC,IAAI,CAAC;oBACf,OAAO,EAAE,CAAC,KAAa,EAAE,EAAE;wBACzB,IAAI,eAAe,CAAC,OAAO,EAAE,CAAC;4BAC5B,eAAe,CAAC,OAAO,CAAC,aAAa,GAAG,UAAU,KAAK,EAAE,CAAC;wBAC5D,CAAC;wBACD,OAAO,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC,CAAC;oBAC1C,CAAC;oBACD,MAAM,EAAE,CAAC,WAAkB,EAAE,EAAE;wBAC7B,MAAM,CAAC,WAAW,CAAC,CAAC;oBACtB,CAAC;iBACF,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;QAGD,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC;QAE5B,IAAI,CAAC;YACH,IAAI,QAAQ,GAAkB,IAAI,CAAC;YAGnC,IAAI,aAAa,EAAE,CAAC;gBAClB,QAAQ,GAAG,MAAM,aAAa,CAAC,YAAY,EAAE,CAAC;YAChD,CAAC;iBAAM,IAAI,YAAY,EAAE,CAAC;gBACxB,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;YAClC,CAAC;iBAAM,CAAC;gBAGN,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,SAAS,EAAE,CAAC;gBAC9C,IAAI,CAAC,MAAM,EAAE,YAAY,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC;oBACnD,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;gBAChD,CAAC;gBAID,OAAO,CAAC,IAAI,CACV,oGAAoG,CACrG,CAAC;gBACF,MAAM,IAAI,KAAK,CACb,uGAAuG,CACxG,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;YACjD,CAAC;YAGD,gBAAgB,EAAE,CAAC,QAAQ,CAAC,CAAC;YAG7B,IAAI,eAAe,CAAC,OAAO,EAAE,CAAC;gBAC5B,MAAM,cAAc,GAAG,aAAa,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,UAAU,QAAQ,EAAE,CAAC;gBACtF,eAAe,CAAC,OAAO,CAAC,aAAa,GAAG,cAAc,CAAC;YACzD,CAAC;YAGD,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAE7B,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;YAE7B,iBAAiB,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;YAGpC,OAAO,aAAa,CAAC,eAAe,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,YAAY,EAAE,CAAC;YAEtB,MAAM,iBAAiB,GAAG,YAAqB,CAAC;YAChD,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,iBAAiB,CAAC,CAAC;YAC7E,cAAc,EAAE,CAAC,iBAAiB,CAAC,CAAC;YAGpC,YAAY,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;YAEtC,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;YAE7B,iBAAiB,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;YACpC,gBAAgB,EAAE,EAAE,CAAC;YAErB,OAAO,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC,CACF,CAAC;IAGF,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAC/D,aAAa,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACjE,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;QAC7B,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,CAAC,CAAC;IAEF,OAAO,EAAC,OAAO,EAAC,CAAC;AACnB,CAAC,CAAC;AAyBF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,aAA4B,EAC5B,SAAkC,EAAE,EACpC,EAAE;IAGF,OAAO,sBAAsB,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;AACvD,CAAC,CAAC"}
|
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
import React, { type ReactNode } from 'react';
|
|
2
|
-
import type { KeycloakConfig, KeycloakConfigWith2FA } from '../core
|
|
2
|
+
import type { BackgroundReauthConfig, InitRecoveryStrategy, KeycloakConfig, KeycloakConfigWith2FA } from '../core';
|
|
3
|
+
interface KeycloakConfigContextValue {
|
|
4
|
+
config: KeycloakConfig;
|
|
5
|
+
offlineAccessEnabled: boolean;
|
|
6
|
+
backgroundReauth: BackgroundReauthConfig;
|
|
7
|
+
clientSecret?: string;
|
|
8
|
+
getClientSecret?: () => string | undefined | Promise<string | undefined>;
|
|
9
|
+
initRecoveryStrategy: InitRecoveryStrategy;
|
|
10
|
+
refreshPinCheck: () => Promise<void>;
|
|
11
|
+
}
|
|
3
12
|
export interface KeycloakConfigProviderProps {
|
|
4
13
|
children: ReactNode;
|
|
5
14
|
config: KeycloakConfigWith2FA;
|
|
15
|
+
offlineAccessEnabled?: boolean;
|
|
16
|
+
backgroundReauth?: BackgroundReauthConfig;
|
|
17
|
+
clientSecret?: string;
|
|
18
|
+
getClientSecret?: () => string | undefined | Promise<string | undefined>;
|
|
19
|
+
initRecoveryStrategy?: InitRecoveryStrategy;
|
|
6
20
|
}
|
|
7
21
|
export declare const KeycloakConfigProvider: React.NamedExoticComponent<KeycloakConfigProviderProps>;
|
|
8
22
|
export declare const useKeycloakConfig: () => KeycloakConfig;
|
|
23
|
+
export declare const useKeycloakSessionOptions: () => Pick<KeycloakConfigContextValue, "offlineAccessEnabled" | "backgroundReauth" | "clientSecret" | "getClientSecret" | "initRecoveryStrategy">;
|
|
9
24
|
export declare const useKeycloakConfigRefresh: () => (() => Promise<void>);
|
|
25
|
+
export {};
|
|
10
26
|
//# sourceMappingURL=KeycloakConfigContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeycloakConfigContext.d.ts","sourceRoot":"","sources":["../../src/context/KeycloakConfigContext.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EAEZ,KAAK,SAAS,EAMf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"KeycloakConfigContext.d.ts","sourceRoot":"","sources":["../../src/context/KeycloakConfigContext.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EAEZ,KAAK,SAAS,EAMf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EACV,sBAAsB,EACtB,oBAAoB,EACpB,cAAc,EACd,qBAAqB,EACtB,MAAM,SAAS,CAAC;AAGjB,UAAU,0BAA0B;IAClC,MAAM,EAAE,cAAc,CAAC;IACvB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,gBAAgB,EAAE,sBAAsB,CAAC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACzE,oBAAoB,EAAE,oBAAoB,CAAC;IAE3C,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAID,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,SAAS,CAAC;IAEpB,MAAM,EAAE,qBAAqB,CAAC;IAC9B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACzE,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAiBD,eAAO,MAAM,sBAAsB,yDAoElC,CAAC;AASF,eAAO,MAAM,iBAAiB,QAAO,cAQpC,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAAO,IAAI,CAC/C,0BAA0B,EACxB,sBAAsB,GACtB,kBAAkB,GAClB,cAAc,GACd,iBAAiB,GACjB,sBAAsB,CAezB,CAAC;AAKF,eAAO,MAAM,wBAAwB,QAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAM/D,CAAC"}
|
|
@@ -11,7 +11,7 @@ function getEffectiveConfig(config, pinSet) {
|
|
|
11
11
|
...(config.oidcProvider != null && { oidcProvider: config.oidcProvider }),
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
|
-
export const KeycloakConfigProvider = React.memo(({ children, config }) => {
|
|
14
|
+
export const KeycloakConfigProvider = React.memo(({ children, config, offlineAccessEnabled, backgroundReauth, clientSecret, getClientSecret, initRecoveryStrategy, }) => {
|
|
15
15
|
const [pinSet, setPinSet] = useState(null);
|
|
16
16
|
useEffect(() => {
|
|
17
17
|
let mounted = true;
|
|
@@ -29,7 +29,28 @@ export const KeycloakConfigProvider = React.memo(({ children, config }) => {
|
|
|
29
29
|
setPinSet(hasPin);
|
|
30
30
|
}, []);
|
|
31
31
|
const effectiveConfig = useMemo(() => getEffectiveConfig(config, pinSet), [config, pinSet]);
|
|
32
|
-
const
|
|
32
|
+
const resolvedOfflineAccessEnabled = offlineAccessEnabled ?? config.offlineAccessEnabled ?? true;
|
|
33
|
+
const resolvedClientSecret = clientSecret ?? config.clientSecret;
|
|
34
|
+
const resolvedGetClientSecret = getClientSecret ?? config.getClientSecret;
|
|
35
|
+
const resolvedInitRecoveryStrategy = initRecoveryStrategy ?? 'none';
|
|
36
|
+
const resolvedBackgroundReauth = useMemo(() => backgroundReauth ?? config.backgroundReauth ?? {}, [backgroundReauth, config.backgroundReauth]);
|
|
37
|
+
const value = useMemo(() => ({
|
|
38
|
+
config: effectiveConfig,
|
|
39
|
+
offlineAccessEnabled: resolvedOfflineAccessEnabled,
|
|
40
|
+
backgroundReauth: resolvedBackgroundReauth,
|
|
41
|
+
clientSecret: resolvedClientSecret,
|
|
42
|
+
getClientSecret: resolvedGetClientSecret,
|
|
43
|
+
initRecoveryStrategy: resolvedInitRecoveryStrategy,
|
|
44
|
+
refreshPinCheck,
|
|
45
|
+
}), [
|
|
46
|
+
effectiveConfig,
|
|
47
|
+
resolvedOfflineAccessEnabled,
|
|
48
|
+
resolvedBackgroundReauth,
|
|
49
|
+
resolvedClientSecret,
|
|
50
|
+
resolvedGetClientSecret,
|
|
51
|
+
resolvedInitRecoveryStrategy,
|
|
52
|
+
refreshPinCheck,
|
|
53
|
+
]);
|
|
33
54
|
return (<KeycloakConfigContext.Provider value={value}>{children}</KeycloakConfigContext.Provider>);
|
|
34
55
|
});
|
|
35
56
|
KeycloakConfigProvider.displayName = 'KeycloakConfigProvider';
|
|
@@ -40,6 +61,19 @@ export const useKeycloakConfig = () => {
|
|
|
40
61
|
}
|
|
41
62
|
return context.config;
|
|
42
63
|
};
|
|
64
|
+
export const useKeycloakSessionOptions = () => {
|
|
65
|
+
const context = useContext(KeycloakConfigContext);
|
|
66
|
+
if (!context) {
|
|
67
|
+
throw new Error('useKeycloakSessionOptions must be used within KeycloakConfigProvider');
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
offlineAccessEnabled: context.offlineAccessEnabled,
|
|
71
|
+
backgroundReauth: context.backgroundReauth,
|
|
72
|
+
clientSecret: context.clientSecret,
|
|
73
|
+
getClientSecret: context.getClientSecret,
|
|
74
|
+
initRecoveryStrategy: context.initRecoveryStrategy,
|
|
75
|
+
};
|
|
76
|
+
};
|
|
43
77
|
export const useKeycloakConfigRefresh = () => {
|
|
44
78
|
const context = useContext(KeycloakConfigContext);
|
|
45
79
|
if (!context) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeycloakConfigContext.js","sourceRoot":"","sources":["../../src/context/KeycloakConfigContext.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EACZ,aAAa,EAEb,WAAW,EACX,UAAU,EACV,SAAS,EACT,OAAO,EACP,QAAQ,GACT,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"KeycloakConfigContext.js","sourceRoot":"","sources":["../../src/context/KeycloakConfigContext.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { type ReactNode } from 'react';
|
|
2
2
|
import KeycloakReactNativeClient from '../core/client';
|
|
3
|
+
import type { RNKeycloakInitOptions } from '../core';
|
|
3
4
|
interface KeycloakInstanceContextValue {
|
|
4
5
|
keycloak: KeycloakReactNativeClient | null;
|
|
5
6
|
isInitialized: boolean;
|
|
@@ -14,6 +15,7 @@ export interface KeycloakInstanceProviderProps {
|
|
|
14
15
|
autoRefreshToken?: boolean;
|
|
15
16
|
autoRefreshTokenMinValidity?: number;
|
|
16
17
|
onReauthRequired?: () => void;
|
|
18
|
+
initOnLoad?: RNKeycloakInitOptions['onLoad'];
|
|
17
19
|
}
|
|
18
20
|
export declare const KeycloakInstanceProvider: React.NamedExoticComponent<KeycloakInstanceProviderProps>;
|
|
19
21
|
export declare const useKeycloakInstance: () => KeycloakInstanceContextValue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeycloakInstanceContext.d.ts","sourceRoot":"","sources":["../../src/context/KeycloakInstanceContext.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,EAEZ,KAAK,SAAS,EAMf,MAAM,OAAO,CAAC;AAGf,OAAO,yBAAyB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"KeycloakInstanceContext.d.ts","sourceRoot":"","sources":["../../src/context/KeycloakInstanceContext.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,EAEZ,KAAK,SAAS,EAMf,MAAM,OAAO,CAAC;AAGf,OAAO,yBAAyB,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,SAAS,CAAC;AAMnD,UAAU,4BAA4B;IACpC,QAAQ,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC3C,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IAEpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAID,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,SAAS,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IAEpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IAErC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAE9B,UAAU,CAAC,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;CAC9C;AAID,eAAO,MAAM,wBAAwB,2DA2LpC,CAAC;AAQF,eAAO,MAAM,mBAAmB,QAAO,4BAQtC,CAAC"}
|