import {useReactOidc} from "@axa-fr/react-oidc-context";
import {useLocation} from "react-router-dom";
import {setPostLoginPath} from "../LoginRedirectionHandler";
import {useJcuIdentity} from "../../services";
import { useCallback, useMemo } from "react";
/**
* @typedef {object} OidcHookReturn
*/
type OidcHookReturn = {
/**
* Function to trigger an OIDC log in
*/
login: () => void,
/**
* Function to trigger an OIDC log out
*/
logout: () => void,
/**
* An OIDC user object
*/
user: any,
/**
* Whether there is a currently logged in user
*/
loggedIn: boolean,
/**
* OIDC event object
*/
events: any
}
/**
* Custom hook for interacting with OIDC services.
*
* All of the return values are wrappers to the axa
* [useReactOidc](https://github.com/AxaGuilDEv/react-oidc/tree/master/packages/context#how-to-consume--hooks-method-pagesdashboarddashboardjs) hook.
*
* The primary differences are:
* - `oidcUser` has been renamed to `user` for easier reference
* - the `login` function has additional functionality baked in (automatic recording of pre-login URL)
* - new `loggedIn` key to quickly determine if a user is logged in
*
* Usage is the same as other hooks:
*
* ```
* import {useOidc} from '@jcu/spark'
*
* ...
*
* const {login, logout, user, loggedIn} = useOidc()
* ```
* @category Hooks
*
* @return {OidcHookReturn} A pair of functions for logging in/out and the current OIDC user
*/
export function useOidc(): OidcHookReturn {
const {login: oidcLogin, logout: oidcLogout, oidcUser, events} = useReactOidc()
const currentLocation = useLocation()
const introspectedUser = useJcuIdentity()
// Memoize the login and logout callbacks to prevent unnecessary downstream rerenders
const login = useCallback(() => {
if (currentLocation) {
setPostLoginPath(currentLocation.pathname)
}
return oidcLogin()
}, [oidcLogin, currentLocation])
const logout = useCallback(() => {
return oidcLogout()
}, [oidcLogout])
// Memoize the user object so only actual changes trigger downstream rerenders
const user = useMemo(() => {
let user = null
if (introspectedUser && oidcUser) {
user = mergeUserData(oidcUser, introspectedUser)
}
return user
}, [oidcUser, introspectedUser])
return {login, logout, user, loggedIn: !!user, events}
}
// -------------------------------------------------------------
//TODO: JSDOC?
function mergeUserData(oidc, introspect) {
// Extract the scopes from the introspected data
const {scopes} = introspect
// Use the OIDC data as a default (populate what we know already)
// Override with anything we gain from introspection (more authoritative)
let mergedUser = {
...oidc,
scope: scopes,
}
return mergedUser
}
Source