Connecting 2 apps over DDP, how to login across?

We have decided to split 1 Meteor app into 2 different Meteor apps

  1. the main “web” application
  2. a client “mobile” application - still a Meteor + Cordova app

The mobile application is really client-only… It’s mostly a way for us to keep all the mobile-specific interface separate from the web interface (and all the web-only admin stuff).

The mobile application should connect back (via DDP) to the main “web” application, for subscriptions, etc. It doesn’t need a DDP connection back to the mobile server at all.

The docs on this seem pretty straightforward: http://docs.meteor.com/#/full/ddp_connect

Now I’m curious about login and accounts and Meteor.userId()

How do I, from the “mobile” app, login to the “web” application?

Ideally, such that the “mobile” app has the userId available like “normal” via Meteor.userId

diagram-screenshot (I’m not allowed to embed images)


Also please confirm that I can NOT just tell the “mobile” client to use the web’s URL as it’s main URL.

meteor build ../build-dev --server my-web-server.com:80

I can not do this, because the --server is where the mobile client’s content comes from, for updates, etc… right?

8 Likes

We are using this same setup with just the --server and --mobile-server flags accordingly. Accounts and collections work great. We aren’t using autoupdate on our mobile app, but it would be cool. So :+1: for the question of how to have this setup and also use autoupdate.

1 Like

You can either do what Andrew said (use DDP.connect manually and disable autoupdate, because the version reported by the server is the one of the full website, not the mobile app), but then you will lose the hot code push feature.

Or you can keep everything in one app and autoupdate will just work.

Right now, there is no good way to load one file only on websites but not on mobile and vice-versa but it can be done easily in the packages files.

2 Likes

@salva Like server and client folders please consider adding a separate mobile/cordova folder. Its a must have feature.

2 Likes

Thanks for the feedback guys - great to see your names.
Experts in these topics answering my question = I win!

  • I require autoupdate (Meteor deployments, updating the Cordova client application)
  • I can not replicate data/functionality to the Mobile fork of the application
  • I want 1 database, 1 set of publish/subscribes, 1 set of Meteor.methods()…
  • but I want to be able to “connect” to them from the Mobile or Web apps
  • I want to have 2 separate apps
  • for performance reasons, I want to keep the mobile client lean
  • for interface/UI reasons, the mobile client is very different from web
  • for business reasons, the functionality of our mobile client is ~15% of our web application, we really only need a small chunk of it.

For this use case, it makes a lot of sense (IMO) to split apps.

I know DDP across Meteor apps is possible, and I’ve played with it a little.
Now, I’m looking for resources on how best to accomplish this.
First hurdle: login from App A, into App B, maintaining security.

Crosslinking: Different interfaces based on devices?

2 Likes

@zafaransari I agree, that sounds cool… but only if it allowed you to limit builds like this:

  • server
  • client
  • lib (both)
  • web (only on web, not compiled for Cordova at all)
  • cordova (only on Cordova, not included for Web at all)

Since that hierarchy is not supported yet and would be a significant change for existing applications, I don’t know how it would be implemented… but perhaps if someone felt up to making an optional Meteor package which modified build to respect that type of directory layout… ???

Have you looked into meteorhacks:cluster for managing the different interfaces? cluster-wide authentication is in the pipeline, but for now you can authenticate by calling the main service’s Meteor.method login (just like you would using the standard ddp.connect approach.

1 Like

Thanks @rhyslbw - I’ve looked at meteorhacks:cluster, but have yet to try it.

I’ve seen that you can call Meteor.call("login") via DDP… but I’ve not seen a good example of it… nor do I know if it can “take over” the client’s authentication (which is also a goal).

Know of any good examples you can point me towards?

@slava We’re not using DDP.connect manually (just the --server flag). We don’t use hot code push on our mobile app though. We just submit updates to app stores.

@zafaransari I do think the best answer to this is defining multiple clients (not just web and cordova) … you should be able to define as many clients as you want and build / autoupdate should handle this accordingly.

@zeroasterisk Directory Structure

* appname
  * web - Meteor application 1
    * client - Web specific client 
    * server - Server code which works with web and mobile client
    * lib - Lib code which which works with web and mobile client
  * mobile - Meteor application 2
    * client - Cordova specific client
    * server - Symlink of `../web/server`
    * lib - Symlink of `../web/lib`

With this directory structure it allows me to share server and lib code between both clients for development and building. During development, I can just spin up meteor run ios-device for general dev or meteor run ios-device --mobile-server=https://example.com:443 if I want to test connecting to my production server. When I actually go to build my mobile application, I use meteor build --server=https://example.com:443 which points to my production web-client’s server.

5 Likes

I’ve not looked into the autoupdate issue, but regarding authentication:

The author of Job Collection demonstrates remote DDP auth in this issue using the SHA256 internal package.

Bulletproof Meteor has also been an invaluable resource for me, including this lesson on Microservices which includes authentication using the user’s token. This is a paid resource, but Meteorhacks puts so much into the community for free, so it’s a good investment in the Meteor ecosystem.

4 Likes

I added a description of what I figured out at the already cross linked topic I started a while ago. If you can live without autoupdate in your mobile app (or the desktop app, depending which way you set this up) then DDP_DEFAULT_CONNECTION_URL could be the solution.

I know @PolGuixe is playing a bit with this and ended u popening a couple of issues about this.
one is meteor#3909 and the other one, accidentally, is on useraccounts

He has a couple testing repos you can find the link for in the above linked issue and I’ve managed to get useraccounts autentication over DDP as explaind in this one

Essentially to get packages (any package) using Meteor methos working also over DDP connection you have to hack Meteor.call to get it executed on the remote DDP connection instead on the local one.

To do so, put the following code on some client file so to have it executed as soon as possible after app load:

remote = DDP.connect(remoteUrl);
Meteor.call = function(){
  return remote.call.apply(remote, arguments);
};

Hope this might help!

8 Likes

Ahoy. Seems like I found a solution to both use --mobile-server to connect to a remote server, and get hot code pushes from a server holding your actual Cordova-specific code.

Package here: https://github.com/gwendall/meteor-remote-autoupdate

What it does is allowing you to define the URL where Autoupdate will watch code changes from. Would be nice to have such an option in core though. Tested locally, seems to work fine.

3 Likes

I presume your package method needs to be called after mucking with meteor as in this linked thread?

connectToExistingBackend = function(url) {
  //
  // make a remote connection and set the global connection object to it
  Meteor.connection = DDP.connect(url);
  // make sure Accounts uses that connection
  Accounts.connection = Meteor.connection;
  //
  // this is copied from ddp/*/web.browser/packages/ddp.js
  // it makes sure all method calls are done with the correct connection
  //
  _.each(['subscribe', 'methods', 'call', 'apply', 'status', 'reconnect',                                         // 52
          'disconnect'],                                                                                          // 53
         function (name) {                                                                                        // 54
           Meteor[name] = _.bind(Meteor.connection[name], Meteor.connection);                                     // 55
         });                                                                                                      // 56
  //
  // we need re-declare the users collection so Meteor knows to use the remote one
  //
  Meteor.users = new Meteor.Collection('users');
  //
  // now that we have our act together, try to re-login
  // unfortunately Accounts seems to have already run before
  // we did the Meteor.connection = DDP.connect part, so we manually
  // need to re-check the loginToken or hot code pushes log us out every time
  //
  var token = Accounts._storedLoginToken();
  if(token)
  {
    Meteor.loginWithToken(token, function(err){
      // this is going to throw error if we logged out
      if(err) console.log(err);else console.log('loginWithToken');
    });
  }
}
3 Likes

It doesn’t deal with Meteor and Accounts’ connections at all. You may want to let --mobile-server handle it if you build a Cordova app.

All it does is patch the autoupdate method so that you can give it the URL you want to watch code changes.

Thank you @gwendall , very good point.

I think it is about time to be more specific about what kind of app is being developed.

My confusion about all of this stems from the fact that the original premise of Meteor+Cordova seemed to be that I can have ONE code base which will run in three different environments: desktop, mobile desktop and cordova.

Trying to separate out the mobile from the desktop will now require to sub-divide the mobile browser from the cordova version, in a way.

Over time I believe this will be flushed out more.

@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?