apollographql / meteor-integration

🚀 meteor add apollo
http://dev.apollodata.com/core/meteor.html
108 stars 45 forks source link

Issue with facebook-accounts: user not loggedIn after FB redirect #113

Closed fede-rodes closed 6 years ago

fede-rodes commented 6 years ago

Hi guys,

I'm using facebook-accounts along with this package and have the following issue. When the user logs in with facebook using loginStyle = 'redirect', the loginTokens take some milliseconds to be set on localStorage which produces that the user stays 'logged out' after response comes back from facebook. Of course, if I refresh the page, the tokens are read correctly and the user is then authenticated. At the moment I've solved the issue by setting up a Meteor.setInterval that fires a refetch call after 500 miliseconds. Is this a bug from the package? Do you have a better solution to solve the issue?

This is the patch I use to solve the issue:

//------------------------------------------------------------------------------
// COMPONENT:
//------------------------------------------------------------------------------
/**
 * @summary Injects global data (current user and/or global settings to name a
 * few examples) into child components.
 */
class GlobalDataProvider extends React.Component {
  componentWillMount() {
    // Patch to handle FB auth request when using redirect login style
    const handler = Meteor.setTimeout(() => {
      this.props.refetch();
      console.log('refetch');
      Meteor.clearTimeout(handler);
    }, 500);
  }

  render() {
    const {
      refetch,
      hasErrors,
      userLoading,
      curUser,
      children,
      ...rest
    } = this.props;

    if (hasErrors) {
      return <div>Something bad happend!</div>;
    }

    if (userLoading) {
      return <Loading />;
    }

    return React.cloneElement(children, { refetch, curUser, ...rest });
  }
}

GlobalDataProvider.propTypes = {
  hasErrors: PropTypes.bool,
  refetch: PropTypes.func,
  userLoading: PropTypes.bool,
  curUser: propType(userFragment),
  children: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.array,
  ]).isRequired,
};

GlobalDataProvider.defaultProps = {
  hasErrors: false,
  refetch: () => {},
  userLoading: false,
  curUser: null,
};

//------------------------------------------------------------------------------
// APOLLO INTEGRATION:
//------------------------------------------------------------------------------
/*
 * We use the `graphql` higher order component to send the graphql query to our
 * server. See for more information: http://dev.apollodata.com/react/
 */
const withData = graphql(userQuery, {
  // Destructure the default props to more explicit ones
  props: ({ data: { error, loading, user, refetch } }) => {
    if (loading) {
      return { userLoading: true };
    }

    if (error) {
      console.log(error);
      return { hasErrors: true };
    }

    return {
      curUser: user,
      refetch,
    };
  },
});

//------------------------------------------------------------------------------

export default withData(GlobalDataProvider);

And here is my Apollo-Client config:

import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import { meteorClientConfig } from 'meteor/apollo';
import { ApolloProvider } from 'react-apollo';
import ApolloClient from 'apollo-client';
import createReduxStore from './redux/store.js';
import GlobalDataProvider from './global-data-provider.jsx';
import DefaultLayout from './layouts/default/index.jsx';
import Routes from './routes.jsx';

/**
 * To get started, create an ApolloClient instance and point it at your GraphQL
 * server (handled in our case by meteor-apollo). By default, this client will
 * send queries to the '/graphql' endpoint on the same host.
 */
const client = new ApolloClient(meteorClientConfig());

// For redux integration see http://dev.apollodata.com/react/redux.html
const store = createReduxStore(client);

const App = () => (
  <Router>
    <ApolloProvider client={client} store={store}>
      <GlobalDataProvider>
        <DefaultLayout>
          <Routes />
        </DefaultLayout>
      </GlobalDataProvider>
    </ApolloProvider>
  </Router>
);

export default App;

Here's the repo I'm working on: https://github.com/fede-rodes/meteor-apollo-starter-kit

Any help will be really appreciated :)

lorensr commented 6 years ago

It's a middleware function so should fetch from localStorage on each request:

https://github.com/apollographql/meteor-integration/blob/master/src/main-client.js#L73 https://github.com/apollographql/meteor-integration/blob/master/src/main-client.js#L127

Instead of setInterval, could Tracker.autorun on Meteor.userId()

fede-rodes commented 6 years ago

Hi @lorensr thanks for the quick reply and for the suggestion :)

I removed Tracker and reactive-vars from my project, I'm trying to rely as little as possible on Meteor from the front-end. I'll try to listen to localStore changes coming from the same tab, maybe in that way I can trigger a refetch more naturally; otherwise I'll probably go back to tracker!

Cheers and keep the great work!

lorensr commented 6 years ago

Oh, have you tried this? 😄

http://docs.meteor.com/api/accounts-multi.html#AccountsCommon-onLogin

On Wed, Nov 15, 2017 at 7:49 AM, Federico Rodes notifications@github.com wrote:

Closed #113 https://github.com/apollographql/meteor-integration/issues/113.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/apollographql/meteor-integration/issues/113#event-1342924802, or mute the thread https://github.com/notifications/unsubscribe-auth/AAPVmNErTJ8FLPT1UUe5wN6YS8dfvlJDks5s2t3cgaJpZM4QeJb4 .

fede-rodes commented 6 years ago

@lorensr just saw your comment, sorry!

I'll take a look, many thanks and I'll let you know if it woks :)

fede-rodes commented 6 years ago

haha the simplest solution always works :) Thanks