example-storefront: Redirect for reauth should not present login form
Issue Description
Currently, when the storefront recieves a Status 401 from the backend over GraphQL, it will redirect to the /signin route. This will then redirect to the meteor backend to get a new authentication token. The assumption here seems to be, that the Meteor User still is logged in. If the User is logged out on the Backend, this will just present a login form. Skipping the auth redirect won’t solve anything, as the page will just stay at its current point and display a Status 500 then.
example-storefront/src/lib/apollo/initApollo.js
The desired behaviour should be: If GraphQL gives a 401, get an actual indication if there is a logged in backend user. If there is, do the redirect to get a new token. If not, ditch the current token and reload (Although I’d be unhappy with a real reload, maybe Apollo Client could just try to connect a second time )
Steps to Reproduce
Please provide starting context, i.e. logged in as a user, configure a particular payment method.
- Log in to the storefront
- Wait until the token expires 2.5 Im not sure when actually the backend logout happens
- Visit the storefront again, and see that it will redirect to the backend login form.
Possible Solution
I’m unsure if that can be fixed in the backend on the route that also provides the silent reauth, or has to be done in the storefront.
We currently don’t separate actual logins from silent reauths in the /loginendpoint on the Backend:
https://github.com/reactioncommerce/reaction/blob/746f5acf8eb2a9e877d7ede93f46a595b8013348/imports/plugins/core/hydra-oauth/server/oauthEndpoints.js#L18
We could instead provide both a /login and /refresh (or /reauth as it isn’t really a refresh in oauth terminology) endpoint. While the behaviour for both would be the same when getLoginRequestRes.skip is set, for the other case /login could still redirect to the login form as usual, while /refresh would redirect back to the storefront instead. I The storefront would have dropped the session cookie by then so it won’t try the reauth again.
I think it would be even better if the unsuccessful redirect could be completely avoided, as it would happen quite often for logged in users. But the storefront would need to know beforehand if there is an authenticated backend user, and I’m not sure if that could work, as I think the Meteor Client bundle will always need to load once and grab the token from localStorage to which no other page has access. A hidden iframe solution could maybe work, that would only trigger a redirect if silent re-authentication is possible.
Im still need to figure out why exactly this issue occurs where the backend doesn’t have valid authentication anymore while the frontend still thinks it is logged in.
Versions
2.1.0
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 15 (5 by maintainers)
@aldeed Thanks, I also noticed that package, and I think it basically does the same thing, which is to queue upcoming queries until the fetch is resolved. I will compare implementations, because that’s where I got stuck and didn’t have time left last time. Also I did’t want to just plug that in, as I didn’t want to introduce another unknown here and instead want to be able to actually keep track of what happens at what point in the chain.
@janus-reith Seems like you’ve put a lot of work into this, so thank you for that. Some of your issues bring to mind the same roadblocks we hit in the initial implementation.
I haven’t looked at it closely, but there might be some techniques in this package that could help: https://www.npmjs.com/package/apollo-link-token-refresh
The logout call does nothing except clear the auth cookie. I would need to debug a lot more to fully understand how the multiple requests are clashing with each other, but it makes sense that would happen. Attempting to track the expiration time and reauth before the token expires (i.e., not in
onError) might be an option, but it might miss some situations.You might try posting an issue with some of this info in the Apollo Client repo. I’m sure they’d love to have good docs on how to do this with a standard OAuth flow, which they don’t currently have. Maybe some minimal changes to the core packages would simplify what you’re trying to do. It also seems like a situation where creating a minimal reproduction app would be helpful. An app that just has a single page that looks different depending on user and tries to fulfill all the requirements of the storefront.