diff --git a/README.md b/README.md index 059ae75..47fccfc 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ services: REACT_APP_OPENID_SERVER: https://server:port/realms/your-realm REACT_APP_CLIENT_ID: frontend-client ports: - - 5173:80 # set your port here + - 80:80 # set your port here ``` - run: ```bash diff --git a/example/example.docker-compose.yml b/example/example.docker-compose.yml index dfcfea1..214472b 100644 --- a/example/example.docker-compose.yml +++ b/example/example.docker-compose.yml @@ -10,4 +10,4 @@ services: REACT_APP_OPENID_SERVER: https://server:port/realms/your-realm REACT_APP_CLIENT_ID: frontend-client ports: - - 5173:80 # set your port here \ No newline at end of file + - 80:80 # set your port here \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index d8b8013..ba8cb3d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,11 +4,12 @@ import CenterLoader from './shared/components/loaders/CenterLoader'; import { ColorScheme, ColorSchemeProvider, MantineProvider } from '@mantine/core'; import { useColorScheme } from '@mantine/hooks'; import { getCookie, setCookie } from 'cookies-next'; -import { BrowserRouter } from 'react-router-dom'; import AppBody from './AppBody'; import Forbidden from './pages/403'; import { Notifications } from '@mantine/notifications'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import RetryErrorPage from './pages/RetryErrorPage'; +import { keycloakConfig } from '.'; const queryClient = new QueryClient({ @@ -20,8 +21,10 @@ const queryClient = new QueryClient({ }) function App() { + const maxErrorAuthConts = 10 const systemColorScheme = useColorScheme() - const [colorScheme, setColorScheme] = useState(getCookie('mantine-color-scheme') as ColorScheme || systemColorScheme); + const [colorScheme, setColorScheme] = useState(getCookie('mantine-color-scheme') as ColorScheme || systemColorScheme) + const [authErrorCounter, setAuthErrorCounter] = useState(0) const toggleColorScheme = (value?: ColorScheme) => { const nextColorScheme = value || (colorScheme === 'dark' ? 'light' : 'dark'); setColorScheme(nextColorScheme) @@ -33,15 +36,32 @@ function App() { // automatically sign-in useEffect(() => { if (!hasAuthParams() && - !auth.isAuthenticated && !auth.activeNavigator && !auth.isLoading) { - auth.signinRedirect(); + !auth.isAuthenticated && !auth.activeNavigator && !auth.isLoading && authErrorCounter < maxErrorAuthConts) { + console.log('not authenticated! redirect!') + auth.signinRedirect() } - }, [auth, auth.isAuthenticated, auth.activeNavigator, auth.isLoading, auth.signinRedirect]); + }, [auth, auth.isAuthenticated, auth.activeNavigator, auth.isLoading, auth.signinRedirect]) + if (auth.activeNavigator || auth.isLoading) { return } - if ((!auth.isAuthenticated && !auth.isLoading) || auth.error) { + + if (authErrorCounter > maxErrorAuthConts) { + console.log('maxErrorAuthConts authority', keycloakConfig.authority) + console.log('maxErrorAuthConts client_id', keycloakConfig.client_id) + console.log('maxErrorAuthConts redirect_uri', keycloakConfig.redirect_uri) + return auth.signinRedirect()} /> + } + + if (!auth.isAuthenticated && !auth.isLoading && authErrorCounter < maxErrorAuthConts) { + console.log('not authenticated! redirect!') + setAuthErrorCounter(prevCount => prevCount + 1); + auth.signinRedirect() + } + + if ((!hasAuthParams() && !auth.isAuthenticated && !auth.isLoading) || auth.error) { + setAuthErrorCounter(prevCount => prevCount + 1); console.error(`auth.error:`, auth.error) return } @@ -72,10 +92,8 @@ function App() { } }} > - - - - + + diff --git a/src/index.tsx b/src/index.tsx index e02dd08..3017658 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,7 +4,8 @@ import App from './App'; import reportWebVitals from './reportWebVitals'; import RootStore from './shared/stores/root.store'; import { AuthProvider, AuthProviderProps } from 'react-oidc-context'; -import { oidpSettings } from './shared/env.const'; +import { isProduction, oidpSettings } from './shared/env.const'; +import { BrowserRouter } from 'react-router-dom'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement @@ -21,14 +22,22 @@ export const keycloakConfig: AuthProviderProps = { const rootStore = new RootStore() export const Context = createContext(rootStore) +if (!isProduction) { + console.log('keycloakConfig.authority', keycloakConfig.authority) + console.log('keycloakConfig.client_id', keycloakConfig.client_id) + console.log('keycloakConfig.redirect_uri', keycloakConfig.redirect_uri) +} + root.render( - - + + + {/* */} - + {/* */} - - + + + ); // If you want to start measuring performance in your app, pass a function diff --git a/src/pages/RetryErrorPage.tsx b/src/pages/RetryErrorPage.tsx index a6b790a..10be194 100644 --- a/src/pages/RetryErrorPage.tsx +++ b/src/pages/RetryErrorPage.tsx @@ -8,10 +8,18 @@ import { Context } from '..'; import { observer } from 'mobx-react-lite'; interface RetryErrorPageProps { + repeatVisible?: boolean + backVisible?: boolean + mainVisible?: boolean onRetry?: () => void } -const RetryErrorPage = ({ onRetry }: RetryErrorPageProps) => { +const RetryErrorPage = ({ + repeatVisible = true, + backVisible = true, + mainVisible = true, + onRetry +}: RetryErrorPageProps) => { const executed = useRef(false) const navigate = useNavigate() @@ -45,9 +53,9 @@ const RetryErrorPage = ({ onRetry }: RetryErrorPageProps) => { {ExclamationCogWheel} {strings.youCanRetryOrGoToMain} - - - + {repeatVisible ? : null} + { backVisible ? : null } + { mainVisible ? : null } ); diff --git a/src/shared/env.const.ts b/src/shared/env.const.ts index 84ccca2..7ce1f22 100644 --- a/src/shared/env.const.ts +++ b/src/shared/env.const.ts @@ -1,3 +1,5 @@ +import { z } from "zod" + export const appMode = process.env.NODE_ENV export const isProduction = appMode === "production" export const host = isProduction ? window.env?.REACT_APP_HOST : process.env.HOST @@ -8,6 +10,8 @@ const proxy = isProduction ? window.env?.REACT_APP_FRIGATE_PROXY : process.env. export const proxyURL = new URL(proxy || '') const oidpServer = isProduction ? window.env?.REACT_APP_OPENID_SERVER : process.env.REACT_APP_OPENID_SERVER +const oidpServerParsed= z.string().url().safeParse(oidpServer) +if (!oidpServerParsed.success) throw Error('REACT_APP_OPENID_SERVER must be string and URL') const oidpClientId = isProduction ? window.env?.REACT_APP_CLIENT_ID : process.env.REACT_APP_CLIENT_ID export const oidpSettings = { server: oidpServer || '',