Authority must be hard-coded
rwb196884 opened this issue · 1 comments
I need to get the authority
from a request to /settings
Here's how I'm getting the settings.
import { Context, createContext, useContext, useEffect, useState } from "react";
export class AppSettings {
buildName: string = '';
authority: string = '';
truthPortalApi: string = '';
environment: string = '';
}
export const AppSettingsContext: Context<AppSettings> = createContext<AppSettings>(null!)
export const AppSettingsProvider: React.FC<{ children: JSX.Element }> = ({ children }) => {
const [settings, setSettings] = useState<AppSettings>(new AppSettings())
useEffect(() => {
fetch(`${window.location.origin}/settings`)
.then(response => response.json())
.then(data => setSettings(data))
}, []);
return (
<AppSettingsContext.Provider value={ settings }>
{children}
</AppSettingsContext.Provider>
)
}
export function useAppSettings(): AppSettings {
return useContext<AppSettings>(AppSettingsContext);
}
And here's how I'm trying to use them
let url: string = `${window.location.protocol}//${window.location.host}/`;
function createUserManager(appSettings: AppSettings): UserManager {
const authSettings: UserManagerSettings = {
authority: appSettings.authority,
client_id: 'client_app',
redirect_uri: `${url}signin-callback`, // Guess. It's unclear what this should be.
silent_redirect_uri: `${url}silent-callback.html`, // Guess. It's unclear what this should be.
post_logout_redirect_uri: `${url}`,
response_type: 'code',
scope: 'openid profile offline_access app',
loadUserInfo: true
};
return new UserManager(authSettings);
}
export const LocalAuthProvider: React.FC<{ children: JSX.Element[] }> = ({ children }) => {
let appSettings: AppSettings = useAppSettings();
const [userManager, setUserManager] = useState<UserManager>(() => (appSettings && appSettings.authority) ? createUserManager(appSettings) : null!);
useEffect(() => () => {
if (appSettings && appSettings.authority) {
console.warn(`LocalAuthProvider setUserManager authority='${appSettings.authority}'`);
setUserManager(createUserManager(appSettings));
}
}, [appSettings]);
return (
<AuthProvider //userManager={userManager}
authority={ appSettings.authority}
clientId={'truth_portal'}
redirectUri={url}
silentRedirectUri={`${url}silent-callback.html`}
postLogoutRedirectUri={url}
responseType={'code'}
scope={'openid profile offline_access truth_portal'}
loadUserInfo={true}
>
{children}
</AuthProvider >
);
}
The userManager
property doesn't work and you have to pass all of the others.
However, it doesn't work because
Uncaught (in promise) Error: No authority or metadataUrl configured on settings
Clearly the problem is returning an AuthProvider before the settings have loaded, but how do you fix this?
Can this be made to work or is it just a limitation of `oidc-react that the authority must be hard-coded?
You need to wait for the settings to load, but this seems to be impossible in React.
@rwb196884 wouldn't this do the trick? Just don't return the AuthProvider until userManager, and therefore appSettings, are not null:
return !userManager ? null : (
<AuthProvider userManager={userManager}>
...
</AuthProvider>
);