We have to split our web app into mobile web app and dashboard. Dashboard is a main app located in localhost:3000. We are trying to connect mobile app located at loalhost:3002 to our main app.
There is a code:
Meteor.remoteConnection = DDP.connect('localhost:3000');
Meteor.remoteConnection.onReconnect = function() {
console.log('Meteor.remoteConnection.onReconnect', arguments);
};
// make sure Accounts uses this so I can login
Accounts.connection = Meteor.remoteConnection;
// redeclare so it uses remote users
Meteor.users = new Meteor.Collection('users',{connection: Meteor.remoteConnection});
Products = new Mongo.Collection("products", Meteor.remoteConnection);
Meteor.remoteConnection.subscribe('Products');
After login in to mobile app I can recieve Meteor.user() but after refreshing this page I’ve got an error: Error logging in with token: Error: You've been logged out by the server. Please log in again. [403].
Just yesterday we solved it with sessionStorage or localStorage:
Tracker.autorun(function () {
var token = sessionStorage.getItem('_storedLoginToken');
if(token){
Meteor.loginWithToken(token, function(err){
// this is going to throw error if we logged out
if(!err) {console.log('loginWithToken ',token)}
else{console.log('loginWithTokenError ',err)};
});
}
});
//
// autorun.user
//if user is logged in we put token to **sessionStorage**
Tracker.autorun(function(){
var user = Meteor.user();
//sometimes user can be null
if (user === null){
user = undefined;
}
if(user)
{
console.log('set token');
sessionStorage.setItem('_storedLoginToken', Accounts._storedLoginToken());
}
});
I’ve created the file in root client directory called ‘startup.js’ and put this code to it, after meteor was updated i had to make some changes in the code:
// Connecting to the remote server
var connection = DDP.connect('localhost:3000'); //You have to put there your remote server
//Connecting accounts system from remote server
ClientAccounts = new AccountsClient({connection: connection});
//Replace base connections
Meteor.connection = connection;
//// make sure Accounts uses this so I can login
Accounts.connection = connection;
// Patching methods
var methods = ["subscribe", "call", "apply", "methods", "status", "reconnect", "disconnect", "onReconnect"];
methods.forEach(function (method) {
Meteor[method] = function () {
return connection[method].apply(connection, arguments);
};
});
// always checks if token was changed
Tracker.autorun(function () {
var token = localStorage.getItem('_storedLoginToken');
if (token) {
ClientAccounts.loginWithToken(token, function (err) {
// this is going to throw error if we logged out
if (!err) {
console.log('loginWithToken ', token);
//back to previous page after login in
// if (Iron.Location.get().path!='/')
// history.back();
}
else {
// Router.go("/login");
console.log('loginWithTokenError ', err)
}
});
//if client login success, redirect to prev. page
ClientAccounts.onLogin(function(){
var path = Iron.Location.get().path;
if (path!='/' && path=="/login")
history.back();
});
}
});
//Always checks if user was changed
Tracker.autorun(function () {
var user = ClientAccounts.user();
if (user === null) {
user = undefined;
}
if (user) {
localStorage.setItem('_storedLoginToken', Accounts._storedLoginToken());
}
});
@zarkostanisicI have installed this package both on master(web) and slave(mobile) application.
On master appliction client code i add:
// Run this when the meteor app is started
Meteor.startup(function () {
Accounts.onLogin(function(){
Cookie.set('storedLoginToken', Accounts._storedLoginToken(), {expires: 30});
});
Tracker.autorun(function(){
var user = Accounts.user();
if (user === null) {
token = Cookie.get('_storedLoginToken');
Accounts.loginWithToken(token);
}
});
});
On slave application client code I add:
Meteor.startup(function() {
REMOTE_ACCOUNTS_DDP_URL = "http://smartworkout.ru:3000";
REMOTE_ACCOUNTS_DDP_CONNECTION = DDP.connect(REMOTE_ACCOUNTS_DDP_URL);
REMOTE_ACCOUNTS_DDP_CONNECTION.subscribe('users');
Accounts.connection = REMOTE_ACCOUNTS_DDP_CONNECTION;
Accounts.users = new Meteor.Collection('users', REMOTE_ACCOUNTS_DDP_CONNECTION);
Accounts.onLogin(function(){
Cookie.set('_storedLoginToken', Accounts._storedLoginToken(), {expires: 30});
});
Tracker.autorun(function(){
var user = Accounts.user();
if (user === null) {
token = Cookie.get('_storedLoginToken');
Accounts.loginWithToken(token);
}
});
});
But after success login and refresh page I have same message:
Error logging in with token: Error: You've been logged out by the server. Please log in again. [403]
Solve.
Problem was in Accounts.storedLoginToken(). It is should be Accounts._storedLoginToken() with _ underscore prefix(corrected above).
But now I still see error message hovewer user are logged in. I think this is just workaround. We need a better solution.
However, in my app both are sharing the same database so I just added the accounts to both and logged in regularly. I don’t use allow/deny and needed to check this.userID in my Meteor method… so I just passed in the login token and then used a function to fetch the user with that login token and use that instead of this.userId.
Also in another microservice app cluster, one that’s using mostly a ReactNative app as a client, I skipped using the Meteor accounts/auth all together and rolled my own using a JWT token (standard for APIs now a days). This has been much much easier than fighting with the built in auth. but this won’t be a viable solution for every app.
Wow, do you plan on publishing your work in the form of a post or package?
Perhaps if I release a boilerplate for the REST router/controller setup I have.
Basically the JWT just works as a middleware layer for all incoming HTTP JSON requests (except user create). They’re not using any Meteor methods but if it was you could pass that JWT token as well to authenticate.
Just mocked up a sample of the REST library i’m using… thinking about open sourcing it if there’s enough interest. Currently it’s just a local package and is a bit project specific.