Getting back from oAuth / parsing URL
I'm quite sure there's a recipe but can't quickly figure it out so maybe someone can help me.
Whole app is covered by the OIDC authentication, Router included; so that untill user is authenticated, the router is not initialized. For the authentication, we send user to the oAuth page, with redirect URL (base) and actual URL user requested in the state.
What I want to do is to put that state into the storage shortly until Router is ready, and when it's ready, to handle the URL by TanStack router.
The caveat is that URL is not parsed and I can't send
routeId to the router, I have full path. Using that in navigate would lead to Invariant failed, as the href is not an actual route.
What I'm doing is to use history somehow as a thin layer that will be updated so that router will handle that as an "external" update and will parse URL on it's own – it clearly can do that if I remember correctly and probably does that on the initial load. The trouble is that I can't get it to handle history yet, but maybe this "parsing" API is exposed and I'm missing something?
TLDR: need to turn URL into ToOptions3 Replies
vicious-goldOP•2y ago
Hmm seems like it's not,
Router.parseLocation uses current location and inner functions are not available for use
Tried to do router.history.push and window.history.pushState, doesn't help, though seemingly should
False alarm, tried this but failed:
Interesting - the method above works if you do that after Rotuer mounting – which makes sense. What is unexpected – it leads to the 404
Tried to add timeout before pushing history for fun – 404 too. But if you reload the page, it works.
*if I use router.history.replace – leads to 404, if I use window.history.replaceState – does nothing.fascinating-indigo•2y ago
can you provide a minimal example of your setup on eg codesandbox? I am not fully understanding it.
vicious-goldOP•2y ago
I can if I'll get stuck, but it's nothing complicated really – an example would take some time considering the auth provider. I need to do what router does on initialization, but after initialization. Get an URL and turn it into path, without redirect. After oAuth I'm back with like http://localhost?from=http%3A%2F%2Flocalhost%2Fcool%2Fpath%2Fuser%2Frequested%2Fbefore%2Fauth. I need router to get that "from" query parameter and navigate to it with no redirects.
Essentialy, do
navigate({ to: 'cool/path/user/requested/before/auth', replace: true }), that's it.
What I can't figure out is how to turn 'http://localhost/cool/path/user/requested/before/auth' to { to: 'cool/path/user/requested/before/auth', replace: true }, considering there could be searchParams, hash and other parts.
I tihnk I understood why I cannot achieve what I'm doing, this hook is not called basically when I do history push https://github.com/TanStack/router/blob/main/packages/react-router/src/RouterProvider.tsx#L151, so it's not subscribed yet to the history updates and does not handle the history changes just yet.
Because window.history.pushState({}, '', redirectUrl) should be just enough seems like... or not.
Ok I probably either need to change approach or come up with an example, because in my case it's like this tryLoad is not called when I do window.history.pushState
Oh no it doesn't update latestLocation when I just push state
Solution is quite dirty but I don't think it's possible to do cleaner really:
https://github.com/TanStack/router/blob/main/packages/history/src/index.ts#L195
https://github.com/TanStack/router/blob/main/packages/react-router/src/RouterProvider.tsx#L153
Trick is to strip origin from the href, really, or to use the same function that parses location in your history. History does that on top of the browser history API, so if you won't do that, you'll get 404 as it will consider the whole URL a pathname. After pushing that to the router history, it could be parsed (basepath included, I guess). After parsing, it can be loaded. Here we have a caveat with the transitions, so could explode too. Do not recommend trying at home. Similar flow to one that's happening on initialization.
No need to wait for the effect hooks too, I guess.
Plan B is to just window.location.replace(redirectUrl) but it will cause extra redirect & page load. That way though you'll have a token from session storage (react-oidc-context in my case) and the router will proceed as usual without authentication flow.
I'm actually not sure if that's a valid case or I'm doing something totally wrong.
The thing with oAuth is that you cannot really use the current URL as redirect_url, because it's supposed to be static, and it cannot be changed, at least in the libs like react-oidc-context. Even if you do that initially, when you need to refresh a token, it will redirect you to the page that was loaded when context was initialized. So you cannot really say "oAuth please redirect me to this last page user visited so that router could parse it on load".
As far as I'm concerned, the practice of looping back the desired url after login in the oAuth state is quite common, oftentimes developers even set up a page like "you were logged in and will be redirected soon".
And this place where you will be redirected cannot always be described as a set of ToOptions, though it would be reasonable to send that as state to oAuth instead of the whole URL.
Considering this, and actually quite many cases, I think the access to the process in which Router parses the whole URL would be quite beneficial. I don't think what I've done here is any good because of the modification of router.latestLocation, which, at least, feels wrong.
Having some way to navigate using absolute URLs would be great IMO.