fix infinity auth redirecting
add validation oidp server
This commit is contained in:
parent
811bc5bac7
commit
a5e11f067c
@ -14,7 +14,7 @@ services:
|
|||||||
REACT_APP_OPENID_SERVER: https://server:port/realms/your-realm
|
REACT_APP_OPENID_SERVER: https://server:port/realms/your-realm
|
||||||
REACT_APP_CLIENT_ID: frontend-client
|
REACT_APP_CLIENT_ID: frontend-client
|
||||||
ports:
|
ports:
|
||||||
- 5173:80 # set your port here
|
- 80:80 # set your port here
|
||||||
```
|
```
|
||||||
- run:
|
- run:
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@ -10,4 +10,4 @@ services:
|
|||||||
REACT_APP_OPENID_SERVER: https://server:port/realms/your-realm
|
REACT_APP_OPENID_SERVER: https://server:port/realms/your-realm
|
||||||
REACT_APP_CLIENT_ID: frontend-client
|
REACT_APP_CLIENT_ID: frontend-client
|
||||||
ports:
|
ports:
|
||||||
- 5173:80 # set your port here
|
- 80:80 # set your port here
|
||||||
38
src/App.tsx
38
src/App.tsx
@ -4,11 +4,12 @@ import CenterLoader from './shared/components/loaders/CenterLoader';
|
|||||||
import { ColorScheme, ColorSchemeProvider, MantineProvider } from '@mantine/core';
|
import { ColorScheme, ColorSchemeProvider, MantineProvider } from '@mantine/core';
|
||||||
import { useColorScheme } from '@mantine/hooks';
|
import { useColorScheme } from '@mantine/hooks';
|
||||||
import { getCookie, setCookie } from 'cookies-next';
|
import { getCookie, setCookie } from 'cookies-next';
|
||||||
import { BrowserRouter } from 'react-router-dom';
|
|
||||||
import AppBody from './AppBody';
|
import AppBody from './AppBody';
|
||||||
import Forbidden from './pages/403';
|
import Forbidden from './pages/403';
|
||||||
import { Notifications } from '@mantine/notifications';
|
import { Notifications } from '@mantine/notifications';
|
||||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
|
import RetryErrorPage from './pages/RetryErrorPage';
|
||||||
|
import { keycloakConfig } from '.';
|
||||||
|
|
||||||
|
|
||||||
const queryClient = new QueryClient({
|
const queryClient = new QueryClient({
|
||||||
@ -20,8 +21,10 @@ const queryClient = new QueryClient({
|
|||||||
})
|
})
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
const maxErrorAuthConts = 10
|
||||||
const systemColorScheme = useColorScheme()
|
const systemColorScheme = useColorScheme()
|
||||||
const [colorScheme, setColorScheme] = useState<ColorScheme>(getCookie('mantine-color-scheme') as ColorScheme || systemColorScheme);
|
const [colorScheme, setColorScheme] = useState<ColorScheme>(getCookie('mantine-color-scheme') as ColorScheme || systemColorScheme)
|
||||||
|
const [authErrorCounter, setAuthErrorCounter] = useState(0)
|
||||||
const toggleColorScheme = (value?: ColorScheme) => {
|
const toggleColorScheme = (value?: ColorScheme) => {
|
||||||
const nextColorScheme = value || (colorScheme === 'dark' ? 'light' : 'dark');
|
const nextColorScheme = value || (colorScheme === 'dark' ? 'light' : 'dark');
|
||||||
setColorScheme(nextColorScheme)
|
setColorScheme(nextColorScheme)
|
||||||
@ -33,15 +36,32 @@ function App() {
|
|||||||
// automatically sign-in
|
// automatically sign-in
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!hasAuthParams() &&
|
if (!hasAuthParams() &&
|
||||||
!auth.isAuthenticated && !auth.activeNavigator && !auth.isLoading) {
|
!auth.isAuthenticated && !auth.activeNavigator && !auth.isLoading && authErrorCounter < maxErrorAuthConts) {
|
||||||
auth.signinRedirect();
|
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) {
|
if (auth.activeNavigator || auth.isLoading) {
|
||||||
return <CenterLoader />
|
return <CenterLoader />
|
||||||
}
|
}
|
||||||
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 <RetryErrorPage backVisible={false} mainVisible={false} onRetry={() => 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)
|
console.error(`auth.error:`, auth.error)
|
||||||
return <Forbidden />
|
return <Forbidden />
|
||||||
}
|
}
|
||||||
@ -72,10 +92,8 @@ function App() {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<BrowserRouter>
|
<Notifications />
|
||||||
<Notifications />
|
<AppBody />
|
||||||
<AppBody />
|
|
||||||
</BrowserRouter>
|
|
||||||
</MantineProvider >
|
</MantineProvider >
|
||||||
</ColorSchemeProvider>
|
</ColorSchemeProvider>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,7 +4,8 @@ import App from './App';
|
|||||||
import reportWebVitals from './reportWebVitals';
|
import reportWebVitals from './reportWebVitals';
|
||||||
import RootStore from './shared/stores/root.store';
|
import RootStore from './shared/stores/root.store';
|
||||||
import { AuthProvider, AuthProviderProps } from 'react-oidc-context';
|
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(
|
const root = ReactDOM.createRoot(
|
||||||
document.getElementById('root') as HTMLElement
|
document.getElementById('root') as HTMLElement
|
||||||
@ -21,14 +22,22 @@ export const keycloakConfig: AuthProviderProps = {
|
|||||||
const rootStore = new RootStore()
|
const rootStore = new RootStore()
|
||||||
export const Context = createContext<RootStore>(rootStore)
|
export const Context = createContext<RootStore>(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(
|
root.render(
|
||||||
<Context.Provider value={rootStore}>
|
<Context.Provider value={rootStore}>
|
||||||
<AuthProvider {...keycloakConfig}>
|
<AuthProvider {...keycloakConfig}>
|
||||||
|
<BrowserRouter>
|
||||||
{/* <React.StrictMode> */}
|
{/* <React.StrictMode> */}
|
||||||
<App />
|
<App />
|
||||||
{/* </React.StrictMode> */}
|
{/* </React.StrictMode> */}
|
||||||
</AuthProvider>
|
</BrowserRouter>
|
||||||
</Context.Provider>
|
</AuthProvider>
|
||||||
|
</Context.Provider>
|
||||||
);
|
);
|
||||||
|
|
||||||
// If you want to start measuring performance in your app, pass a function
|
// If you want to start measuring performance in your app, pass a function
|
||||||
|
|||||||
@ -8,10 +8,18 @@ import { Context } from '..';
|
|||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
|
|
||||||
interface RetryErrorPageProps {
|
interface RetryErrorPageProps {
|
||||||
|
repeatVisible?: boolean
|
||||||
|
backVisible?: boolean
|
||||||
|
mainVisible?: boolean
|
||||||
onRetry?: () => void
|
onRetry?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const RetryErrorPage = ({ onRetry }: RetryErrorPageProps) => {
|
const RetryErrorPage = ({
|
||||||
|
repeatVisible = true,
|
||||||
|
backVisible = true,
|
||||||
|
mainVisible = true,
|
||||||
|
onRetry
|
||||||
|
}: RetryErrorPageProps) => {
|
||||||
const executed = useRef(false)
|
const executed = useRef(false)
|
||||||
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
@ -45,9 +53,9 @@ const RetryErrorPage = ({ onRetry }: RetryErrorPageProps) => {
|
|||||||
{ExclamationCogWheel}
|
{ExclamationCogWheel}
|
||||||
<Text fz='lg' fw={700}>{strings.youCanRetryOrGoToMain}</Text>
|
<Text fz='lg' fw={700}>{strings.youCanRetryOrGoToMain}</Text>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Button ml='1rem' onClick={handleRetry}>{strings.retry}</Button>
|
{repeatVisible ? <Button ml='1rem' onClick={handleRetry}>{strings.retry}</Button> : null}
|
||||||
<Button ml='1rem' onClick={handleGoBack}>{strings.back}</Button>
|
{ backVisible ? <Button ml='1rem' onClick={handleGoBack}>{strings.back}</Button> : null }
|
||||||
<Button ml='1rem' onClick={handleGoToMain}>{strings.goToMainPage}</Button>
|
{ mainVisible ? <Button ml='1rem' onClick={handleGoToMain}>{strings.goToMainPage}</Button> : null }
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { z } from "zod"
|
||||||
|
|
||||||
export const appMode = process.env.NODE_ENV
|
export const appMode = process.env.NODE_ENV
|
||||||
export const isProduction = appMode === "production"
|
export const isProduction = appMode === "production"
|
||||||
export const host = isProduction ? window.env?.REACT_APP_HOST : process.env.HOST
|
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 || '')
|
export const proxyURL = new URL(proxy || '')
|
||||||
|
|
||||||
const oidpServer = isProduction ? window.env?.REACT_APP_OPENID_SERVER : process.env.REACT_APP_OPENID_SERVER
|
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
|
const oidpClientId = isProduction ? window.env?.REACT_APP_CLIENT_ID : process.env.REACT_APP_CLIENT_ID
|
||||||
export const oidpSettings = {
|
export const oidpSettings = {
|
||||||
server: oidpServer || '',
|
server: oidpServer || '',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user