Thanks @NoelDeMartin for opening this conversation, and investigating the interesting topic of offline-first :).
First, to set a framework for the discussion and make sure we talk about the same thing, let me recap what the OAuth2.0/OIDC login interaction looks like. This is a rough overview, but the things relevant to this discussion are present. It’s worthy to note that all of this comes from the OAuth2.0/OIDC specification, and that the Solid spec only adds a little on top of this, but does not change the general flow.
The first thing to note is that one redirect is absolutely necessary to the login process: the user provides their login/password not to the client application, but to the Identity Provider. At some point, in order to log in, the user must be redirected to the Identity Provider, which in turn will redirect them back to the Client Application. That’s the “front channel” part of the diagram. Only after this redirection back to the Client Application is the login process complete, with the Client Application obtaining an Access Token which enables accessing resources on behalf of the User on Solid Servers. At this point, the Client Application communicates with the Identity Provider through HTTP requests, that’s the “back channel” interaction.
When you mention the redirect working without user interaction, that’s indeed a common scenario, that happens when the user is already logged in the Identity Provider. When the user initiates login and gets redirected to the Identity Provider, if it has a cookie set on the browser, the user is immediately redirected back.
Now, that’s for how OAuth2.0/OIDC work. On top of this, there’s how our libraries work, in particular @inrupt/solid-client-authn-browser
(sca-b for short). The library handles how/when redirects are triggered, and manages the access token.
How is the Access Token managed by the library ? The Access Token making it possible to access private resources, we want to limit as much as possible the risks of extraction. If we wanted the Access Token to remain available between refreshes, the only “permanent” storage available (i.e. that survives a page reload) would be the session/local storage, and that storage isn’t secure: any script loaded under an origin can read it. This is why it’s considered a vulnerability to store any sensitive information there. Therefore, the access token can only be kept in memory, and will be lost on reload. That’s why a second redirect is involved after reload: we can redirect the user to and from the identity provider “silently”, leveraging the fact that there is a cookie set, and that no user interaction is required.
So to summarize, you can only get an Access Token after an online interaction (even if it does not involve the user), and the Access Token is rather short-lived (typically not more than a 1-2 hours, often less than that). In any case, as you point out in your message reading/writing to a Pod is also an online interaction, so you’ll only need an Access Token when you are effectively online.
One important thing to note, though, is that sca-b won’t redirect the user away from the client application unpredictably. Redirects only happen in two cases:
- when calling
session.login({...})
(session
being a Session
object as defined by sca-b)
- when calling
session.handleIncomingRedirect({restorePreviousSesion: true})
after a page reload. If the user is being redirected from the Identity Provider, no additional redirect happens. Also, something noteworthy is that at any point, you’ll know if an Access Token is available or not: session.info.isLoggedIn
is a boolean that indicates whether authenticated requests are possible or not.
Considering all of this, what do you think of the following design: initially, the user is logged out. They edit content offline, without being synced to the Pod. A “sync” icon may be greyed out, or stricken through somewhere on the screen. The user may force sync by clicking the icon. At this point, they are informed that syncing requires to login, which is only possible if you have some connectivity. This way, the user themselves work around the question of Lie-Fi, and assess whether a redirection will be successful or not. After being redirected back, sync can happen in the background without further user interaction, and you can try to figure out if the app has connectivity without disrupting the user experience.
This is a lot of information/suggestions, so I’m happy to discuss any specific point that’s unclear :). Overall, does this help to answer your question ?