Losing session when going to different page after login

I have a home.js page, where I have a Login button which calls the inbuilt login() function and the page also has the handleIncomingRedirect() function to complete the login process with options {url: window.location.href, restorePreviousSession: true}. I wish to navigate to another page profile.js and fetch some data from the POD. Every time I call getSolidDataset() on the profile.js page, I get 401 Unauthenticated error. When I check the value of isLoggedIn in the session object, it shows false on profile.js and true on home.js. I want the same session to continue on every other page other than just home.js. Any help is appreciated. Thanks

Do you have a repository we can take a look at? I’m not sure I understand the issue just with that information. home.js and profile.js are not pages, those are javascript files and you can potentially load both in the same page. So I’m not sure how you’re writing your app.

1 Like

https://github.com/IshaanOhri/pod-test
The repository contains a react app. Please install the packages via npm ci and then start the app via npm start. The app will open up on http://localhost:3000

On the /home page, you will login into the POD with https://inrupt.net as the POD provider. Please feel free to change it to a POD provider of your preference on line 34 in pages/home.js

On the /profile page you will see your Web ID and below it will be a Write Time button, which should write to current time in milliseconds into the pod but upon clicking the button, it shows an Unauthenticated Error with code 401

Hi @IshaanOhri. I think the issue is the following: after you’ve logged in, calling window.location.href = "/profile" reloads the page, which loses the session. There are multiple approaches to this:

  • Either you go for a Single Page App, and keep everything happening at the same origin, in which case once you’ve redirected you’re good.
  • Or you can redirect to the profile page during login, and handleIncomingRedirect from there instead of the home page.
  • Another approach is to use a framework enabling client-side navigation, such as NextJS. In that case, your app has a client-side router, and your browser doesn’t actually reload the page, even if you navigate between pages in the domain.

Does this help understanding the issue ?

1 Like

That is a good clarification of the problem but does not solve the fact that pods are not anymore easy to use as web server that they where meant to be.

2 Likes

I agree with @bourgeoa, this is not just an inconvenience, it is a disaster for onboarding new developers and a major pain in the neck for existing developers.

1 Like

I understand your concerns, and I 100% agree that the onboarding experience is crucial for adoption. However, that’s something that cannot be separate from security, and the OAuth security guidelines, in general or for browser-based apps are strongly recommanding to match redirect IRIs exactly, and to protect from other scripts loaded under the same origin. A browser-side Solid app would conform to this architectural pattern, which explicitly mentions

As of the date of this publication there is no browser API that allows to
store tokens in a completely secure way

These recommendations make it impossible, to the extent of my knowledge, to support the use case @IshaanOhri initially intended. Setting window.location to load a different page is no different from navigating to a different URL, which is why the SPA pattern is very popular, since it removes this constraint.

However, this doesn’t mean that nothing can be improved, far from that. Some of our work around Inrupt’s authentication library is documenting the possible patterns, so I’ll try to review these and see how to improve them to limit confusion as much as possible. I’ll also bring this up to the Authentication Panel, and see how we can produce information material guiding developers through what is possible, what is not, and why.

3 Likes

Thanks @zwifi - two use cases to keep in mind :

  • serving multiple apps from a pod - @aveltens has been bitten by the inability to have apps at two different URIs on a pod since the login is not forgotten and the redirect always goes to the last logged-in app.

  • developing on an pod - if I want to see how an app behaves on a pod and I mess up, I will keep being redirected to the messed up app and the only remedy is to delete the app from an external script.

1 Like

This solution worked for me. Thanks a lot!

Another question, what if I want this session to stay persistent throughout my web application, i.e. I navigate to a third page eg. "/dashboard" ?

I think my initial response still applies:

  • Either you go for a Single Page App, and keep everything happening at the same origin, in which case once you’ve redirected you’re good.
  • Or you can redirect to the profile page during login, and handleIncomingRedirect from there instead of the home page.
  • Another approach is to use a framework enabling client-side navigation, such as NextJS. In that case, your app has a client-side router, and your browser doesn’t actually reload the page, even if you navigate between pages in the domain.

So your options are basically to have everything on one home page, i.e. the proverbial “Single Page App”, to have one “public” homepage and one “private” page (what you currently have, with the login process redirecting you to the private page), or to go and use a framework which allows client-side navigation. The one I’m familiar with is NextJS, but I’m sure other exists if this one doesn’t work for you.

The idea of client-side navigation is that your browser app embeds its own router, and allows you to navigate from one page to another without actually reloading the page. A somewhat outdated example of what this could look like is provided in this repo. You may also want to use our React components. You’l learn more about NextJS and client-side routing on their website

1 Like

May be I misunderstand the next.js clientside routing but can it work for a pod where the pages are mostly unknown and nearly unlimited?

And another option would be to insert your own server in between to manage sessions across page refreshes, e.g. using solid-client-authn-node to connect to the Pod on the server, and express-session to maintain the session across page loads.

Feels like that may be a bit too ambitious in this specific case, but it might be helpful to someone coming across this in the future.

2 Likes

One way of dealing with this would be to use their notion of dynamic route.

I think the main point is that there is a distinction between an app page and a data source. Your app may have a /profile and a dashboard page for instance, or several /posts/[post-id] pages, but that’s orthogonal to how many Pods/resources are involved in populating these pages with data. In this case a page is a simply view over data, but what is relevant to auth is that it is served from one application which global context remains unchanged while navigating between these pages.

Will using the React SDK Components solve this issue (having session persistent across unlimited pages) or a framework with client-side navigation (NextJS) the only solution?

No, the React SDK provided by Inrupt are “only” regular components, they aim at embedding limited assumptions to be usable in multiple contexts. In order to support persistent sessions across multiple pages without involving a server-side component, using a framework supporting client-side navigation is the only thing I can recommand at the moment.

Thanks for the help! Will try out implementing it in NextJS

Is there any sample application with NextJS which I can use as a reference? I’m getting an error integrating Solid Login in NextJS

There isn’t an “official” sample yet, but I started working on one some time ago, and never got around to wrapping it up. It may help you get started: solid-client-authn-js/packages/browser/examples/single/next at exp/next-demo-app · inrupt/solid-client-authn-js · GitHub. Podbrowser is also a NextJS app using Inrupt’s components, but it’s quite a large codebase, so I’m not sure it’s the best starting point.

Note that the provided example is very experimental, and it directly uses solid-client-authn, rather than our components.

Not a sample application, but Penny uses Next.js. Source code: VincentTunru / Penny · GitLab

Btw, note that Next.js uses React, and React apps in general use client-side navigation. So if you’re fine with using React (which, if you’re OK with using the React components, it sounds like you are), setting up React from scratch yourself should work as well. Next.js can just take a lot of boilerplate out of your hands.

1 Like

I’m trying out NextJS so that I’m able to find a solution to my original problem, that is keeping my login session persistent across unlimited pages