handleIncomingRedirect() w/ redirect creates endless loop

I’m using a multi-page app. After I successfully login to Solid, I come back to the main page where I call handleIncomingRedirect(), as the documentation suggests. Then click on the ‘about’ page and my session is lost.

According to this page:
https://docs.inrupt.com/developer-tools/javascript/client-libraries/tutorial/restore-session-browser-refresh/#enable-session-restore

I should call handleIncomingRedirect() again in the ‘about’ page with ({restorePreviousSession: true, url: window.location.href}). This again puts be back to the main page.

According to the same doc above, if I add a session event before the call the call to handleIncomingRedirect(), then I can interrupt the redirect and stay on the same page with the login session restored properly. So, I add in the event similar to the example on the doc page:

let session = getDefaultSession();
session.events.on(EVENTS.SESSION_RESTORED, (url) => {
    window.location.href = url;
});

This event does get called, but after the handleIncomingRedirect() sends to the original redirect from the login. Then when this event handler gets called, it redirects again to the ‘about’ page, and then this whole process repeats in an endless loop.

Anyone have any example on how to do this without resorting to a SPA structure?

1 Like

Is suggest checking out the appropriate Noel is taking in umai

Thanks @jeswr , but that is a single page app (SPA). Is that really the only style that can be employed with Solid.
The browser gives us so much, routing and history. Using a SPA tries to duplicate that in JS on the client side. I think this reduces search engines from discovering pages. If I’m wrong about that, point me in the right direction.

Huh - I thought UMAI was multi page, my bad!

Another example for you then is Inrupts AMC which I can confirm is multi-page

It’s been a while since I’ve built an MPA with Solid (AMC is the most recent once I’ve worked on), so unfortunately I don’t have the key tips and tricks top of mind.

The browser gives us so much, routing and history. Using a SPA tries to duplicate that in JS on the client side. I think this reduces search engines from discovering pages.

This is completely right IMO

1 Like

I’m afraid that using Inrupt’s library it’s currently not possible to restore the session silently, without user interaction :/. Yes, Umai is an SPA, but I also tried to restore the session after reloading because if users have already logged in, I think it’s not the best UX to redirect them again. But so far, I don’t think it’s possible.

I have discussed it with Inrupt’s maintainers in these two threads/issues:

However, not everything is lost. I haven’t done it myself, but I’m pretty sure you could use something like Turbo (previously called Turbolinks) to keep the Javascript session alive when you navigate. Essentially, your app would continue being an MPA, but navigation would happen without reloading the page. Maybe it’s not ideal, but with the current limitations I think that’s the best you can do.

Also, I have to wonder, how are you using the library? With the way it works, I’m pretty sure you can only use it in the frontend. So that would mean that you’re not doing any rendering in the server-side. At that point, why not do an SPA? I don’t think there’s anything wrong with an MPA, as you mention, but if I were to make an MPA I’d use some server-side login mechanism that doesn’t rely on Inrupt’s library. That way, you could also do requests server-side, and you don’t even need Javascript (you can implement your app with PHP, Ruby, or whatever you like).

I’m pinging @zwifi in case he has something to add.

4 Likes

Hi @TimG (and thanks @NoelDeMartin for the ping!).

Just for me to make sure we are aligned, when you say multi-page app, you are talking about a “traditional” web application, with a server-side component handling the routing and serving the (mostly server-side generated) pages to the browser, is that accurate? I’m rephrasing the same question as @NoelDeMartin essentially :slight_smile: .

If so, you might be interested by Authenticate (Node.js Web Server) — Inrupt JavaScript Client Libraries, which should do what you are asking, i.e. store the user session on the server side, so that authentication is maintained during the browsing session between the different pages (typically using a cookie to correlate the requests from one browser to the different pages so that the appropriate user session is used). A very basic example of this is shown in solid-client-authn-js/packages/node/examples/multiSession at main · inrupt/solid-client-authn-js · GitHub.

If I’m going in the wrong direction, then I’m happy to hear more details about what you’re building to be able to provide some support. Is what you’re building public, so that I could have a look?

1 Like

@NoelDeMartin and @zwifi Thanks for the info. I’ve read through them, and I’m understanding the process better but I still have some more research to do such as looking into the Authenticate (Node.js Web Server).

Yes, my goal is to create a more traditional web app with separate pages. I was hoping that even with the Solid login process, that creating this app would be as straightforward as building my first web site way back in 1998. I definitely was not anticipating hosting a Node server on with my web hosting company since they already provide an Apache server.

Here is an initial thought about linking to a different page:
Since the original login() process returns info in the URL when it is done and redirects back to the app, can we save off that information and use it in subsequent links to the other pages? To be more secure or consistent, maybe include in the Solid library a way to register links that when clicked get the information appended to them before the browser moves to the next page. That way when the next page is loaded and calls handleIncomingRedirect({ restorePreviousSession: true }) it can re-read that information as it did during the original login() and that way restore the session information for the next page.

2 Likes

Unfortunately at the moment we only support Node and Java servers.

The authentication code that is being provided on the URL on redirect is single-use for security reasons. The browser library is also designed not to allow the obtained access token to be exfiltrated because other scripts could be running on the origin under which it is loaded, so you wouldn’t be able to pass that around easily and securely (it would require messing pretty deeply with cookies for instance). I’m afraid what you are suggesting would be trying to fit square pegs into round holes, and that Inrupt isn’t providing tooling for the use case you’re targeting at the moment.

However, that doesn’t mean it cannot be done: the delta between Solid-OIDC and regular OIDC is not huge, so it would be possible to extend an existing OIDC library that is suitable to your environment to achieve that kind of use case. I haven’t worked with PHP in years, so I have no idea of what the ecosystem and wouldn’t be able to provide any useful pointers there unfortunately.

1 Like

Yes, I did some experimenting last night and found that, as you mentioned, those query params are one time params. So, that did not work to pass it around when I went to another page.

I guess I’ll have to research a SPA treatment for my app :slight_smile:

Last night I downloaded the solid-client-auth-js (SCA) repo and did some testing moving between pages and trying to stay logged in. As per security concerns, I did not want to store anything in localStorage. I did see that the SCA used the sessionStorage for the sessionId. For my purposes, I only want the Session.info to persist across pages.

So, I added some functionality to Session to register certain navigation links to save the Session.info to sessionStorage before moving to the next page. When the next page calls handleIncomingRedirect({ restorePreviousSession: true }), the Session picks up that Session.info from the sessionStorage, removes the item from storage, and resets the internal session. Looks all good at this point.

I still need to do some testing with reading/writing to the POD after moving pages.

If anyone sees any security concerns with this approach, let me know.