Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authority must be hard-coded #971

Open
rwb196884 opened this issue Mar 12, 2023 · 1 comment
Open

Authority must be hard-coded #971

rwb196884 opened this issue Mar 12, 2023 · 1 comment

Comments

@rwb196884
Copy link

rwb196884 commented Mar 12, 2023

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.

@jamesdh
Copy link
Contributor

jamesdh commented Mar 12, 2023

@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>
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants