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_CLIENT_ID: frontend-client
|
||||
ports:
|
||||
- 5173:80 # set your port here
|
||||
- 80:80 # set your port here
|
||||
```
|
||||
- run:
|
||||
```bash
|
||||
|
||||
@ -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
|
||||
- 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 { 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<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 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 <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)
|
||||
return <Forbidden />
|
||||
}
|
||||
@ -72,10 +92,8 @@ function App() {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<BrowserRouter>
|
||||
<Notifications />
|
||||
<AppBody />
|
||||
</BrowserRouter>
|
||||
<Notifications />
|
||||
<AppBody />
|
||||
</MantineProvider >
|
||||
</ColorSchemeProvider>
|
||||
</div>
|
||||
|
||||
@ -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>(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(
|
||||
<Context.Provider value={rootStore}>
|
||||
<AuthProvider {...keycloakConfig}>
|
||||
<Context.Provider value={rootStore}>
|
||||
<AuthProvider {...keycloakConfig}>
|
||||
<BrowserRouter>
|
||||
{/* <React.StrictMode> */}
|
||||
<App />
|
||||
<App />
|
||||
{/* </React.StrictMode> */}
|
||||
</AuthProvider>
|
||||
</Context.Provider>
|
||||
</BrowserRouter>
|
||||
</AuthProvider>
|
||||
</Context.Provider>
|
||||
);
|
||||
|
||||
// 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';
|
||||
|
||||
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}
|
||||
<Text fz='lg' fw={700}>{strings.youCanRetryOrGoToMain}</Text>
|
||||
<Flex>
|
||||
<Button ml='1rem' onClick={handleRetry}>{strings.retry}</Button>
|
||||
<Button ml='1rem' onClick={handleGoBack}>{strings.back}</Button>
|
||||
<Button ml='1rem' onClick={handleGoToMain}>{strings.goToMainPage}</Button>
|
||||
{repeatVisible ? <Button ml='1rem' onClick={handleRetry}>{strings.retry}</Button> : null}
|
||||
{ backVisible ? <Button ml='1rem' onClick={handleGoBack}>{strings.back}</Button> : null }
|
||||
{ mainVisible ? <Button ml='1rem' onClick={handleGoToMain}>{strings.goToMainPage}</Button> : null }
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
@ -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 || '',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user