Question

I am running into a race condition when an unknown user is trying to access a secured page.

Iron-Router code:

function secured() {
    if ( Meteor.user() == null ) {
        Meteor.loginWithLinkedin({
        },function (err){
            if(err){
                console.log("Error when login with LinkedIn."+JSON.stringify(err));
            }
        });
    }
}

Router.map(function () {this.route('customer_researchRequest', {
    before: secured,
    waitOn: waitOnHuman,
    path: '/research/request',
    template: 'customer_researchRequest',
    layoutTemplate: 'customer_requestLayout'
});});

On the server:

    ServiceConfiguration.configurations.remove({
        service: 'linkedin'
    });

    ServiceConfiguration.configurations.insert({... settings ...});

If the user goes directly to /research/request, there is a race condition.

  1. before condition fires
  2. (on client)ServiceConfiguration.configurations has no configuration
  3. client has exception about no linkedin service defined.
  4. server publishes the ServiceConfiguration.configurations to the client

At this point, my solution is to hard code in the clientId and other linkedin config information into the linkedin authentication code ( Yech ).

Is there a better more elegant/correct solution?

Update #1: My solution was to tweak the meteor-linkedin package so that it expects the linkedIn clientId as an option and does not depend on the ServiceConfiguration.configuration. This way the clientId is always available.

Was it helpful?

Solution 2

The best solution turns out to be my "hack" of creating a forked meteor-linkedin which accepts the client configuration in the login call.

We edited the meteor-linkedin so that the Meteor.loginWithLinkedIn() call supplied the linkedIn clientId.

Currently, Meteor's ServiceConfiguration is stored in a mongo table and needs to be published from the server to client. The clientId is essentially a static configuration variable that might as well be encoded into the client code. Just putting the linkedin clientId directly in the login code turns out to be infinitely more reliable and simpler.

Even if Meteor was to 'fix' the publishing race condition, we would stick with our solution: it is bulletproof and guaranteed to work. You can borrow our code our meteor-linkedin and accounts-meteor-linkedin

The meteor dev people aren't planning on fixing the issue. I agree with this decision, it is much better to just have the (constant) client configuration on the client rather than being stored on the server and sent to the client.

Update: In the end for a variety of reasons, we almost entirely abandoning the meteor oauth code. The client-side centric approach with popup dialogs caused numerous problems. I talk about some of the issues on the 1911 bug report. We ended up triggering the oauth code ourselves server-side.

OTHER TIPS

Edited to address comment:

Maybe a different use of reactivity can help. Set up a deferred redirect to customer_researchRequest, by first diverting the user, then bringing them up

A) Have secured() save the original destination path to the session. Redirect to a page you allow without security (or a 'Loading...' page), to avoid your #3
B) when the login callback happens, save another flag to the session, indicating that #4 is no longer true C) have a Deps.autorun redirect to the desired path when both flags become true.

Someone else may know a smarter way, (maybe waitOn should test for the config) but ...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top