-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #111 from InseeFr/develop
Develop
- Loading branch information
Showing
18 changed files
with
314 additions
and
2,588 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<html> | ||
<body> | ||
<script> | ||
parent.postMessage(location.href, location.origin); | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { useEffect } from "react"; | ||
import { createReactOidc } from "oidc-spa/react"; | ||
|
||
/** | ||
* By default, without initialization we use a mock as a return of "useOidc" | ||
* | ||
* This object will be used for testing purpose to simulate authentication status | ||
*/ | ||
const mockOidc = { login: () => {}, isUserLoggedIn: false, oidcTokens: {} } | ||
// Global method that will be replaced when oidc is initialized | ||
let useOidc = ({assertUserLoggedIn}) => mockOidc; | ||
|
||
/** | ||
* Helper method used for tests, set a fake Oidc authentication state | ||
*/ | ||
export const mockOidcForUser = () => { | ||
window.localStorage.setItem("AUTHENTICATION_MODE", "oidc") | ||
mockOidc.isUserLoggedIn = true | ||
mockOidc.oidcTokens = {accessToken: '12031203'} | ||
} | ||
export const mockOidcFailed = () => { | ||
mockOidc.isUserLoggedIn = false | ||
mockOidc.oidcTokens = {} | ||
} | ||
|
||
/** | ||
* Initialize oidc | ||
*/ | ||
export function initializeOidc (config) { | ||
const oidc = createReactOidc(config) | ||
useOidc = oidc.useOidc | ||
return oidc; | ||
} | ||
|
||
/** | ||
* Retrieve authentication status based of Oidc | ||
*/ | ||
export function useIsAuthenticated() { | ||
const { login, isUserLoggedIn, oidcTokens, renewTokens} = useOidc({ assertUserLoggedIn: false }); | ||
|
||
useEffect(() => { | ||
if (!login) { | ||
return; | ||
} | ||
login({ | ||
doesCurrentHrefRequiresAuth: true, | ||
}); | ||
}, [login]); | ||
|
||
return { isAuthenticated: isUserLoggedIn, tokens: oidcTokens, renewTokens }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,88 @@ | ||
import React from 'react'; | ||
import Keycloak from 'keycloak-js'; | ||
import View from '../View/View'; | ||
import DataFormatter from '../../utils/DataFormatter'; | ||
import { KEYCLOAK, ANONYMOUS } from '../../utils/constants.json'; | ||
import initConfiguration from '../../initConfiguration'; | ||
import D from '../../i18n'; | ||
import React, { useEffect, useState, useRef } from "react"; | ||
import { useIsAuthenticated } from "../../Authentication/useAuth"; | ||
import D from "../../i18n"; | ||
import View from "../View/View"; | ||
import DataFormatter from "../../utils/DataFormatter"; | ||
import { OIDC, ANONYMOUS } from "../../utils/constants.json"; | ||
|
||
class App extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.state = { | ||
keycloak: null, | ||
authenticated: false, | ||
contactFailed: false, | ||
initialisationFailed: false, | ||
data: null, | ||
export const App = () => { | ||
const [authenticated, setAuthenticated] = useState(false); | ||
const [contactFailed, setContactFailed] = useState(false); | ||
const [data, setData] = useState(null); | ||
const timeoutIdRef = useRef(null); | ||
|
||
const { tokens, renewTokens } = useIsAuthenticated(); | ||
|
||
useEffect(() => { | ||
const resetInactivityTimeout = () => { | ||
if (timeoutIdRef.current) { | ||
clearTimeout(timeoutIdRef.current); | ||
} | ||
timeoutIdRef.current = setTimeout(renewTokens, 5 * 60 * 1000); | ||
}; | ||
} | ||
|
||
async componentDidMount() { | ||
try { | ||
await initConfiguration(); | ||
} catch (e) { | ||
this.setState({ initialisationFailed: true }); | ||
} | ||
if (window.localStorage.getItem('AUTHENTICATION_MODE') === ANONYMOUS) { | ||
const events = [ | ||
"mousemove", | ||
"mousedown", | ||
"keypress", | ||
"touchstart", | ||
"click", | ||
]; | ||
|
||
events.forEach((event) => { | ||
window.addEventListener(event, resetInactivityTimeout); | ||
}); | ||
|
||
resetInactivityTimeout(); | ||
|
||
return () => { | ||
if (timeoutIdRef.current) { | ||
clearTimeout(timeoutIdRef.current); | ||
} | ||
events.forEach((event) => { | ||
window.removeEventListener(event, resetInactivityTimeout); | ||
}); | ||
}; | ||
}, [renewTokens]); | ||
|
||
useEffect(() => { | ||
if (window.localStorage.getItem("AUTHENTICATION_MODE") === ANONYMOUS) { | ||
const dataRetreiver = new DataFormatter(); | ||
dataRetreiver.getUserInfo((data) => { | ||
if (data.error) { | ||
this.setState({ contactFailed: true }); | ||
setContactFailed(true); | ||
} else { | ||
this.setState({ authenticated: true, data }); | ||
setAuthenticated(true); | ||
setData(data); | ||
} | ||
}); | ||
} else if (window.localStorage.getItem('AUTHENTICATION_MODE') === KEYCLOAK) { | ||
const keycloak = Keycloak('/keycloak.json'); | ||
keycloak.init({ onLoad: 'login-required', checkLoginIframe: false }).then((authenticated) => { | ||
const dataRetreiver = new DataFormatter(keycloak); | ||
dataRetreiver.getUserInfo((data) => { | ||
this.setState({ keycloak, authenticated, data }); | ||
}); | ||
// Update 20 seconds before expiracy | ||
const updateInterval = (keycloak.tokenParsed.exp + keycloak.timeSkew) | ||
* 1000 | ||
- new Date().getTime() | ||
- 20000; | ||
setInterval(() => { | ||
keycloak.updateToken(100).error(() => { | ||
throw new Error('Failed to refresh token'); | ||
}); | ||
}, updateInterval); | ||
} else if ( | ||
window.localStorage.getItem("AUTHENTICATION_MODE") === OIDC && | ||
tokens?.accessToken | ||
) { | ||
const dataRetreiver = new DataFormatter(tokens.accessToken); | ||
dataRetreiver.getUserInfo((data) => { | ||
setAuthenticated(data !== undefined); | ||
setData(data); | ||
}); | ||
} | ||
} | ||
}, [tokens]); | ||
|
||
render() { | ||
const { | ||
keycloak, authenticated, data, contactFailed, initialisationFailed, | ||
} = this.state; | ||
if (keycloak || authenticated) { | ||
if (authenticated) { | ||
return ( | ||
<div className="App"> | ||
if (!tokens?.accessToken) { | ||
return <div>{D.initializationFailed}</div>; | ||
} | ||
|
||
<View | ||
keycloak={keycloak} | ||
userData={data} | ||
/> | ||
</div> | ||
); | ||
} | ||
return (<div>{D.unableToAuthenticate}</div>); | ||
} | ||
if (initialisationFailed) { | ||
return (<div>{D.initializationFailed}</div>); | ||
} | ||
if (contactFailed) { | ||
return (<div>{D.cannotContactServer}</div>); | ||
} | ||
if (authenticated && tokens?.accessToken && data) { | ||
return ( | ||
<div>{D.initializing}</div> | ||
<div className="App"> | ||
<View token={tokens.accessToken} userData={data} /> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
export default App; | ||
if (contactFailed) { | ||
return <div>{D.cannotContactServer}</div>; | ||
} | ||
|
||
return <div>{D.initializing}</div>; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.