"Mismatching redirect uri" when enabling restorePreviousSession

Hi! I’m currently developing a webapp for a university teamwork, where we are using a Session Provider in order to manage each user’s account. We are currently using inrupt, cause we are also using SOLID POD’s so every user can store its personal data. The problem comes at the momment of restoring a session, I mean, when you refresh the page, you would expecto to still have your account logged in. This is our App.tsx:

function App(): JSX.Element {

    return (
        <SessionProvider session-id="login">
            <Router>
                <NavBar/>
                <Routes>
                    <Route
                        path='/'
                        element={
                            <HomePage/>
                        }
                    />
                    <Route
                        path='/login'
                        element={
                            <LoginPage/>
                        }
                    />
                    <Route
                        path='/map'
                        element={
                            <MapPage/>
                        }
                    />
                    <Route
                        path='/help'
                        element={
                            <HelpPage/>
                        }
                    />
                    <Route
                        path='/about'
                        element={
                            <AboutPage/>
                        }
                    />
                    <Route
                        path='/profile'
                        element={
                            <UserProfile/>
                        }
                    />
                </Routes>
            </Router>
        </SessionProvider>
    );
}

This is our NavBar:

function NavBar() {
    const { session, sessionRequestInProgress } = useSession();

    const {t} = useTranslation();

    const [isNavExpanded, setIsNavExpanded] = useState(false);

    if (session.info.webId === undefined) {
        session.info.webId = "";
    }

    function handleNavToggle() {
        setIsNavExpanded(!isNavExpanded);
    }

    useEffect(() => {
        function handleResize() {
            if (window.innerWidth >= 992 && isNavExpanded) {
                setIsNavExpanded(false);
            }
        }

        window.addEventListener('resize', handleResize);
        return () => window.removeEventListener('resize', handleResize);
    }, [isNavExpanded]);

    return (
        <nav className={`navbar navbar-expand-lg navbar-dark ${isNavExpanded ? 'nav-expanded' : 'nav-normal'}`}>
            <div className="container-fluid">
                <a className="navbar-brand" href="/">
                    <img src={GOMapLogo} alt="GOMap Logo" height={128} width={256}/>
                </a>
                <button
                    className="navbar-toggler"
                    type="button"
                    onClick={handleNavToggle}
                >
                    <span className="navbar-toggler-icon"></span>
                </button>
                <div className={`collapse navbar-collapse ${isNavExpanded ? 'show' : ''}`}>
                    <ul className="navbar-nav me-auto mb-2 mb-lg-0">
                        <NavItem to={"/"} text={t("home")}/>
                        <NavItem to={"/map"} text={t("map")}/>
                        <NavItem to={"/help"} text={t("help")}/>
                        <NavItem to={"/about"} text={t("about")}/>
                    </ul>
                    <LanguageMenu/>

                    <div id="login-manage">
                        {
                            (session.info.isLoggedIn) ?
                                <OurAvatar webId={session.info.webId}/>
                                :
                                <Link to="/login">
                                    <Button variant="contained" color="primary" id="login">
                                        {t("login")}
                                    </Button>
                                </Link>
                        }
                    </div>
                </div>

            </div>
        </nav>
    );
}

And finally, this is our LoginPage, where we select our POD Provider and then proceed to log in:

function LoginPage() {
    const {t} = useTranslation();

    const [idp, setIdp] = useState("https://inrupt.net");

    const providers = [
        {name: "Inrupt", value: "https://inrupt.net"},
        {name: "SolidCommunity", value: "https://solidcommunity.net"},
    ];

    function changeProvider() {
        let provider = (document.getElementById("selectProvider") as HTMLSelectElement).value;
        console.log(provider)
        setIdp(provider)
    }

    return (
        <div id="loginBody">
            <div id="loginForm">
                <h1>LoMap</h1>
                <h2>Sign In</h2>
                <form>
                    <p>{t("provider")}</p>
                    <select onChange={changeProvider} id="selectProvider">
                        <option value={providers[0].value}>{providers[0].name}</option>
                        <option value={providers[1].value}>{providers[1].name}</option>
                    </select>
                    <a href={idp + "/register"}>{t("register")}</a>
                    <div id="loginButton">
                        <LoginButton oidcIssuer={idp} redirectUrl={window.location.origin}>
                            <Button variant="contained" color="primary" id="login">
                                {t("login")}
                            </Button>
                        </LoginButton>
                    </div>
                </form>
            </div>
        </div>
    )
}

I know that the solution should be easy, If just added:

restorePreviousSession={true}

To the SessionProvider element, but right after I add this, my app just crashes and returns this:

{"error":"invalid_request","error_description":"Mismatching redirect uri"}

So it just does not work as anyone would expect, I’ve tried searching for it but got nothing…

Has anyone had this problem before or know what should I do in order to fix it and be able to store a user’s session?

Thank you!

Hello @Omitg24, welcome to the forum!

Try to fix it

I’ve seen this issue before, and i don’t know what causes it. But you could try to clear your localStorage and cookies along the lines of these options. It worked for the same issue in different context recently. (see details in the other thread)

Try to figure out what’s going on

I hope somebody could shed some light to what causes this issue. I vaguely remember there was something weird with redirect_uri during the authentication redirect.

Persist Logs in your browser’s developer tools may help debug it. (screenshot below taken in Firefox)

Persist Logs in Firefox

And this is what my browser console says when i refresh an app:

Navigated to https://solidcommunity.net/authorize?client_id=[redacted]&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2F&response_type=code&scope=openid%20offline_access%20webid&state=[redacted]&code_challenge=[redacted]&code_challenge_method=S256&prompt=none&response_mode=query

Example from Node Solid Server, but ESS (Enterprise Solid Server) might have something similar. I suspect redirect_uri part of search params of the uri may be weird in your case.

2 Likes

I’ve tried all of those options, I cleared local storage and cookies on https://solidweb.org/ and still does not respond correctly, even when I try to do it with private mode.

When I first log in, my console says:

Navega a https://inrupt.net/authorize?client_id=025cd45a182df5b89c9107429809179c&redirect_uri=http%3A%2F%2Flocalhost%3A3000&response_type=code&scope=openid%20offline_access%20webid&state=335a15d4731c47ca900179dc16eed3df&code_challenge=vPGlajf1UnyfJ3o5sAu1tnhLUmJg8PTAMastZpVQQik&code_challenge_method=S256&prompt=consent&response_mode=query

But right after I refresh my page, my console prints:

Navega a https://inrupt.net/authorize?client_id=025cd45a182df5b89c9107429809179c&redirect_uri=http%3A%2F%2Flocalhost%3A3000&response_type=code&scope=openid%20offline_access%20webid&state=335a15d4731c47ca900179dc16eed3df&code_challenge=vPGlajf1UnyfJ3o5sAu1tnhLUmJg8PTAMastZpVQQik&code_challenge_method=S256&prompt=consent&response_mode=query

And then it just shows me the error again, I thought it could be that me and our team have a wrong session management, and this could be the error (since we know other groups are doing the same and works for them).

This are all my console prints:

As you may have noticed, the redirect_uri second time is http://localhost:3000?state=[...], and the ?state= part may cause you troubles. I’m not sure about this.

I’ve never used Solid with Next.js (is that where your SessionProvider comes from?). I typically use library @inrupt/solid-client-authn-browser with CRA app to manage Solid sessions. Not sure how they come together with Next. (edit: never mind, my bad assumption)

Hopefully somebody else can help here… :woman_shrugging:

Yeah, I’ve noticed that, but I don’t really know what can I do to solve it.

About library, I’m using “import {SessionProvider} from “@inrupt/solid-ui-react”;”, so its not a problem with Next…

1 Like

I have been getting that error in various situations but don’t have time to track it done. Perhaps file a bug with Inrupt?

2 Likes

What is your version of @inrupt/solid-client-authn-browser ?

Try npm ls @inrupt/solid-client-authn-browser

2 Likes

It is:

`-- @inrupt/solid-ui-react@2.8.2
  `-- @inrupt/solid-client-authn-browser@1.13.3

Try to upgrade solid-client-authn-browser to 1.13.4 or higher, there was a bug fixed that is probably the same as yours: mismatching redirect uri in solid-client-authn-browser@1.13.2 · Issue #2738 · inrupt/solid-client-authn-js · GitHub

4 Likes

Thank you so much! It actually worked! Right now it keeps my session

3 Likes

I’ve replied to this many times on the forum, but you really need to be using a stable URL for the redirect_uri — don’t use just window.location.href, instead use something like new URL("/", window.location.href) such that you’ll always be taken back to “/” and you won’t end up with a client using multiple redirect_uri’s.

This really needs documentation to be improved in both specifications and tutorials / documentation

5 Likes