Connecting 2 apps over DDP, how to login across?

@jamgold I agree. An ideal solution would be to have a mobile/ folder on root (like client/) from where Meteor would automatically bundle your Cordova apps. And where it would watch code changes for them (+ eventually point your mobile visitors to).

As for the separation between mobile and desktop, I personally prefer having two separate code bases since in most cases the flow will be pretty different between those devices.

Totally agree about the flow, but you might still need/want to share certain logic, that’s at least the situation I am in right now. I am working with aldeed’s simple-schema and autoform packages, and a lot of the logic is exactly the same, just the flow and presentation are different.

I can’t wait for the day when the package.js logic, that lets you determine which of the package resources go where (server, client), are applicable to the entire application, either by virtue of directory structure or config files.

As @splendido mentioned. I have been playing with DDP.connect for some time now. My case is also very similar to everyone else´s. One DB, one server, one web client, one Cordova client.

At the beginning I was trying to put conditionals into the templates, but I started using Ionic for the Cordova client and Bootstrap for the web client, so two separate projects were a must.

My solution is very similar to @jamgold’s one, but I am still having issues with the user´s tokens onReconnect. Just one question? when are you calling your function? I just put all the code into the main.js in the client folder. In order to avoid code repetition between clients (functions, schemas, etc.) I have created a package that I have added to both projects.

I totally agree that the best would be to have a way to control which packages affect the different platforms and having support for a /cordova or /mobile folder.

I also have to say that I quite like @andrewreedy’s solution. I haven’t tried but it looks very simple.

@jamgold is the login with token working for you?

@PolGuixe, yes the token login is working (most of the time)

@jamgold, where and when are you calling the connectToExistingBackend('url') function? are you doing it at Meteor.startUp()?

No, contrary to popular belief (I believed it) Meteor.startup in the client doesn’t run when the app starts on the client, but when the DOM is ready on the client.

Since I have not checked out remote autoconnect yet, I call DDP.connect before I declare remote collections in the client code, basically in client/lib/bootstrap.js or some thing I know gets called early so as to not to mess with stuff I don’t understand

Meteor.remoteConnection = DDP.connect(RemoteDataUrl);
Meteor.remoteConnection.onReconnect = function() {
  console.log('Meteor.remoteConnection.onReconnect', arguments);
}
Accounts.connection = Meteor.remoteConnection;
Meteor.users = new Meteor.Collection('users',{connection: Meteor.remoteConnection});
//
MyOwnRemoteCollection = new Meteor.Collection('collection', {connection: Meteor.remoteConnection});
// etc.

I know longer use the connectToExistingBackend function or more specifically the hack therein that modifies the connection attribute of Meteor.methods like call, etc, because it messes with hot code push (see comment above).

I explicitly Meteor.remoteConnection.subscribe and Meteor.remoteConnection.call and so forth, and it works. Hot code pushes and Cordova.

5 Likes

And just in case you need to attempt to force an autologin
(I ran into issues with the auth token disappearing from my Meteor app, perhaps only when initializing the DDP inside Meteor.startup())

on login success:

    // backup the localStorage token/userId
    Meteor._localStorage.setItem(
      "remote.userId",
      Meteor._localStorage.getItem("Meteor.userId")
    );
    Meteor._localStorage.setItem(
      "remote.loginToken",
      Meteor._localStorage.getItem("Meteor.loginToken")
    );

on subsequent load:

// autologin with token if possible
autoLogin = function() {
  var userId = Meteor._localStorage.getItem("remote.userId");
  if (!userId) {
    userId = Meteor._localStorage.getItem("Meteor.userId");
  }
  if (!userId) {
    console.log('no autoLogin, no userId');
    return;
  }
  var token = Meteor._localStorage.getItem("remote.loginToken");
  if (!token) {
    token = Meteor._localStorage.getItem("Meteor.loginToken");
  }
  if (!token) {
    console.log('no autoLogin, no token');
    return;
  }
  userId && Accounts.connection.setUserId(userId);
  Meteor.loginWithToken(token, function (err) {
    if (err) {
      Meteor._debug("Error logging in with token: " + err);
      makeClientLoggedOut();
    }
    Accounts._pageLoadLogin({
      type: "resume",
      allowed: !err,
      error: err,
      methodName: "login",
      methodArguments: [{resume: token}]
    });
  });
}
2 Likes

I have these autoruns in my client

//
// autorun.startup._storedLoginToken
//
Tracker.autorun(function () {
  var token = Session.get('_storedLoginToken');
  // var started = Session.get('startup');
  // console.log('autorun.startup._storedLoginToken',token);
  if(token)
    Meteor.loginWithToken(token, function(err){
      // this is going to throw error if we logged out
      if(!err) console.log('loginWithToken ',token);
    });
});
//
// autorun.user
//
Tracker.autorun(function(){
  var user = Meteor.user();
  console.log('autorun.user');
  if(user)
  {
    Session.set('_storedLoginToken', Accounts._storedLoginToken());
  }
});
2 Likes

So I’ve got everything working for me, runs great across 2 different ports on localhost… but when I attempt to deploy (to modulus) it fails me :frowning:

I’m sure theres a simple implementation of a CORS header somewhere, I need to enable for DDP (and the failover AJAX long-polling connection) — but I don’t see it, and most CORS posted I’ve found (and a few I’ve written) are many Meteor versions old…

What’s the current, correct, way to allow remote DDP connections from other domains & devices?

1 Like

@andrewreedy How do you solve the problem of the routing? Do you have the routes for both clients in the same project? Did you experienced any conflict?

Our UI flow is different for Mobile and for Web so we have different routing constructs for each. There hasn’t been any conflicts since they are each indepenant @PolGuixe

@PolGuixe We also have “different” routes for Mobile vs. Web — but there is still a lot which is shared…

The question then becomes “how to share”… which I think can be any combination of:

  • packages
  • symlinked files or folders (organize your code into common vs web/cordova specific)
  • copied code/content (really sad face)

When I take this approach and run:
meteor run android-device --mobile-server https://example.com --settings settings.json

It will initially load up the meteoric mobile app, but then after a second it will send the web version of the site to my mobile.

How does this not happen to you? Is it the hot-code push doing it?

UPDATE:
Ah… Do I need to be running two different servers? Is there no way to be sharing a server, since the only thing unique to the mobile code is client stuff?

Can we have a summary of this post? Finding it hard to read through all the conflicting comments here

I couldn’t see how i can send the web version the your mobile app. The structure only share the server and the lib folder (which are all the mobile version can see). Do I miss something ?

I’m using your file structure and it works pretty well locally.

How do you deal with pushing the lib directory to production? When I push my repo, the lib and server directories are empty. So when my mobile app autoupdates from my mobile repo (using gwendall’s remote autoupdate package), the lib code is empty.

1 Like

@PolGuixe , @andrewreedy, @zeroasterisk , @jamgold

Guys, can you share a skeleton architecture for this thread based on yours experience?

Its seems a very coommon and needed things with N meteor apps: 1 mobile app, 1 webapp

Thanks in advance!

Is this still the best approach to share authentication between 2 Meteor apps?

1 Like

Hi @andrewreedy, how you create symlink folder? Just create an alias?

I can’t make it work with 1.4. Meteor unable to read alias folder