Use separate server for centralized users database - javascript

I am using Meteor 1.10 + mongodb.
I have multiple mobile chat & information applications.
These mobile application are natively developed using Meteor DDP libraries.
But I have same users base for all the apps.
Now I want to create a separate meteor instance on separate individual server to keep the users base centralized.
I need suggestions that how can I acheive this architecture with meteor.
Keeping reactivity and performance in mind.

For a centralized user-base with full reactive functionality you need an Authorization Server which will be used by your apps (= Resource Servers) in order to allow an authenticated/authorized request. This is basically the OAuth2 3-tier workflow.
See:
https://www.rfc-editor.org/rfc/rfc6749
https://www.oauth.com/
Login Service
You will also have to write your own login handler (Meteor.loginWithMyCustomAuthServer) in order to avoid DDP.connect because you would then have to manage two userbases (one for the app itself and one for the Authorization Server) and this will get really messy.
This login handler is then retrieving the user account data after the Oauth2 authorization request has been successful, which will make the Authorization Server's userbase the single point of truth for any of your app that is registered (read on Oauth2 workflow about clientId and secret).
Subcribing to users
The Auth server is the single point of truth where you create, updat or delete your users there and on a successfull login your local app will always get the latest user data synced from this accounts Auth Server (this is how Meteor does it with loginWith<Service> too)
You then subscribe to your users to the app itself without any ddp remote connection. This of course works only if the user data you want to get is actually for online users.
If you want to subscribe for any user (where the data might have not been synced yet) you still need a remote subscription to a publication on the Authorizazion server.
Note, that in order to authenticate users with this remote subscription you need an authenticated DDP request (which is also backed by the packages below).
Implementation
Warning - the following is an implementation by myself. This is due to I have faced the same issue and found no other implementation before mine.
There is a full working Accounts server (but constantly work in progress)
https://github.com/leaonline/leaonline-accounts
it uses an Oauth2 nodejs implementation, which has been wrapped inside a Meteor package:
https://github.com/leaonline/oauth2-server
and the respective login handler has also been created:
https://github.com/leaonline/meteor-accounts-lea

So finally I got a work around. It might not be the perfect way to handle this, but to my knowledge it worked for me so well. But yes I still open for suggestions.
Currently I have 4 connecting applications which are dependent on same users base.
So I decided to build SSO (Centralized Server for managing Users Database)
All 4 connecting applications ping SSO for User-Authentication and getting users related data.
Now those 4 connecting applications are developed using Meteor.
Main challenge here was to make things Reactive/Realtime.
E.g Chat/Messaging, Group Creations, Showing users list & listeners for newly registered users.
So in this scenario users database was on other remote server (SSO), so on connecting application I couldn't just:
Meteor.publish("getUsers")
So on connecting applications I decided to create a Temporary Collection called:
UserReactiveCollection
With following structure:
UserReactiveCollection.{
_id: 1,
userId: '2',
createdAt: new Date()
}
And I published subscription:
Meteor.publish("subscribeNewUserSso", function () {
return UserReactiveCollection.find({});
});
So for updating UserReactiveCollection I exposed Rest Api's on each connecting application respectively.
Those apis receive data from SSO and updates in UserReactiveCollection.
So on SSO side when ever a new user is registered. I ping those Apis (on connecting applications) and send the inserted userId in the payload.
So now those connecting applications receives onDataChanged ping from the subscription and gets userId.
Using that userId the connecting applications pings back to SSO and get user details of that specific userId and prepends to the users list.
Thats how I got it all working so for now I am just marking my answer accepted but as I mentioned above that: "It might not be the perfect way to handle this, but to my knowledge it worked for me so well. But yes I still open for suggestions."
And special thanks to #Jankapunkt for helping me out.

Related

How to implement a client to server connection that is secure and syncs

I’m struggling to understand how the pouchDB interactions should be implemented. Say I want an offline-first app with syncing and auth, would I need to implement a middleman such as a node server to ensure my credentials to my main server are protected as having a PouchDB on the client with new PouchDB(‘name’, ‘https://username:password#server/dbname’) my creds to my main database are exposed. Would it be better to connect to a node server and that decide wether or not to allow access?
How would this be done? Can I handle a direct connection to the server with auth and it be secure? Or is a middle man needed to ensure security.
If a middle man is needed will you need to implement a sort of api i.e
//client
const db = new Pouch('days')
db.sync(remote)
//server
app.get('/db/days', (res, req) => // do some pouch stuff for each db)
https://github.com/pouchdb-community/pouchdb-authentication
Somewhat simplified, if your application is backed by an application 'master' database and it runs using a single set of credentials, you need a middle layer: you will then need to multiplex all users' data into a single database.
Applications backed by CouchDB/Cloudant often instead use the 'database-per-user' pattern, meaning that each application user have their own database, and their own credentials, meaning that a lot of things become simpler, conceptually, and a middle layer might not be required.
Note that the 'database-per-user' pattern needs some thought to scale well if you intend to cater for millions of users.
On Cloudant you can also use API keys to define access.
If you want the simplicity of the db-per-user pattern without (some of) the drawbacks, you may be able to draw some inspiration from Cloudant Envoy (https://github.com/cloudant-labs/envoy) -- a thin proxy that multiplexes users' data into a single db, whilst still presenting the db-per-user API surface outwards. Disclaimer: I'm one of the authors of Envoy.
Another approach that I use depends on crypto-pouch (https://github.com/calvinmetcalf/crypto-pouch) to encrypt all of your databases on the client. The first time the site is visited, username/password is required to access a cloud couch instance and get things installed on the client.
During this process, a pouchdb database is created on the client for each possible user (retrieved from the cloud couch instance), with each database encrypted with the user's password, and in each database is placed a single document that contains a master password. In addition to these user databases, the 'main' database that stores real data is created and encrypted with the master password.
Subsequent visits to the site whether online or offline, will require the user to enter their username/password, which will attempt to unlock the appropriate user database and get the master password, which is then used to unlock the main database. Only with the master password can the data be accessed and a sync performed to the cloud instance.

Node.js client api key

I have a node.js backend for an ios app that will provide json data to the app. I want to handle client authentication for each app. The users do not need to create an account. I only want to identify the client apps when providing data and save some data for each client on the node server.
How do I handle identifying each app on the server?
If I need to create an API key, how do I handle that?
If there is a way to authenticate the app when the app first accesses the API, how can I create a unique identifier for the app?
Last, what do I need to know before I deploy the node server? Can I get away by just pointing a domain to my router, opening a port and serving the api from there or is it a must to have a web server setup to handle that?
Thank you
You can basically find a lot of blogs posts to get best practices to follow when designing an api. But here is an over all idea
You can create a client key and send it on every api request or add as part of url
Example: api.example.com/v1/users?client=android&version=1.1
Use Middileware. You can either name as to your convenience or have a database to store key value to manage your clients.
Example:
Create a Middleware which does the handling of authentication and API key checker before you forward it to the routes.
android => 0, ios => 1, web => 2
url: api.example.com/v1/users?client=0&version=1.1
There are many ways to create api keys. Here are some of them
UUID - https://www.npmjs.com/package/uuid
Json web token - https://github.com/auth0/node-jsonwebtoken
Oauth - https://github.com/ciaranj/node-oauth
Again, You have a lot of online posts explaining best practices to follow in production. If express.js, You can find best practices to follow here Express Production
This is just an overview. I request you to do a lot of research online and ask a relative more concrete problems you face towards your learning.

How to add database system to WebGL application

I'm currently working on a WebGL sketch drawing project where users can draw arbitrary objects on an html canvas. The javascript libraries and files are all stored on a node.js server which is currently being started up locally every time the software has to be run. Essentially all of the functionality for saving all of the drawn objects on the page has been implemented where the drawings are being written as JSON objects, but the next step is to persist these objects to a database where they can be mapped to a user id. I will also need to implement a login system where users will login and be able to select previously drawn objects to edit from the database.
If this was just a normal website, I would probably just use express.js or something similar, but as the views are essentially rendered entirely in WebGL, I wouldn't think that frameworks would work well with this construct.
Given that I currently just need to create a login system and implement a feature for persisting the JSON object to the DB, are there any frameworks or existing software that accommodates the specified needs of the system?
With regard to authentication, I would recommend taking a look at OAuth and using existing identity providers (e.g. Google, Facebook, etc). You can still retain profiles for your users but you don't have to deal with all of the intricacies of authentication, authorization, security, etc.
There are a ton of JavaScript libraries out there for handling OAuth/OAuth2 interactions. Some even have built-in identity providers. Here are a couple links that returned all sorts of potentially useful libraries:
https://www.npmjs.com/search?q=oauth2
https://www.google.com/search?q=javascript%20oauth2%20library
As for a database, you have a lot of options for storing raw JSON. Some that I've used recently for my JavaScript projects are PostgreSQL, MongoDB, and ArangoDB. You can find well written JS libraries for interacting with any of those.
Another thing to think about is if you want to install the database on your server or use a hosted solution such as RDS or DynamoDB (available from Amazon).
Regardless of the exact authentication and persistence options you choose you will likely use a pattern similar to this:
Your Node.js server is deployed somewhere accessible on the internet, where it exposes the endpoints for your WebGL application, authentication, and saving/loading sketches.
When the user navigates to the WebGL application endpoint on your Node.js server they are required to authenticate (which will utilize your authentication endpoints on the Node.js server).
When the user requests a "save" in your WebGL application you will submit the JSON representation of their sketch (and their authorization token) to the "save" endpoint of your Node.js server.
This "save" endpoint validates the user's authorization token and inserts the JSON into whatever database you've chosen.
The "load" endpoint works just like the "save" endpoint but in reverse. The user asks for a specific sketch. The identity of the sketch (id, name, etc) is sent along with their authorization token. The "load" endpoint on your Node.js server validates their authorization token and then queries the database for the sketch.
The key pattern to notice here is that users don't send requests to your database directly. Your WebGL application should communicate back to your Node.js server and it should commmunicate with your database. This is essential for controlling security, performance, and future updates.
Hopefully this gives you an idea of where to go next.
EDIT based on comments:
I searched around for a Node.js + PostgreSQL guide but didn't find anything I would feel comfortable recommending. I did find this JS library though, which I would check out:
https://github.com/vitaly-t/pg-promise
For MongoDB I would just use their official guide:
https://docs.mongodb.org/getting-started/node/introduction/

Server Sent Events with Hybrid Application

I'm working on a hybrid app that is based on Angular 1.5. In part of the app now, the client wants a messaging system for the admin of a group to be able to message the normal worker/user. I want to check and see if this is done, would server sent events be the solution? If so, do I continue to let it run as the user has the app open? How does this affect performance?
I am presuming authentication would need to be performed against users in order to differentiate between admin and worker accounts.
Have Angular send AJAX calls to your server, which will check the users' authentication status before the client-side view is rendered.
You should research the resolve property in Angular in order to implement this type of solution.

Ionic authentication for login with angularjs

As ionic uses angularjs, for login system there isn't any browser to save cookie or session in order to authenticate for each part of application.
One way is protecting by using this in app.js:
$urlRouterProvider.otherwise('/login');
Because any one doesn't access to other links into application. When returned answer from server (mysql database) is true , we can use this:
$state.go('app.main');
Is this a good idea? Or any other ways?
Since ionic essentially calls to a back end api, you can implement any standard api authentication mechanism.
The most common was would be have a toke based authentication, High level workflow can be as follows
1 - ionic app calls a backend server end point and get a token (by passing some kind of an encrypted key)
2 - Back end server generates a token (ideal for a given time period) and sends back to the ionic app.
3 - There after, in every request ionic sends the token. (ideally in the request header)
To save the token temporary , you can use a simple storage solutions like
ng-storage or sqlite
have a read here
For our company app we use a digest access authentication(https://en.wikipedia.org/wiki/Digest_access_authentication) with our ionic app and our node server that is hooked up to a sql database. Once the user is authenticated we send them a jwt (javascript web token). We can then store that webtoken locally (if they check the option for auto login) or they can re-authenticate whenever the app is reopened and we give them another web token. This has so far proven to be a safe and efficient method of user authentication. Here is a tutorial for using json web tokens and angular. http://www.toptal.com/web/cookie-free-authentication-with-json-web-tokens-an-example-in-laravel-and-angularjs
I would strongly encourage you to checkout John Papa's ng-demoes, especially one with JWT token, because that is what you want to use nowadays. (Those are not specific to ionic, but rather for angular.js apps in general)
basically you have several things you need to do:
handle all the places where you need to check if user is authenticated or not and emit unauthorized event
handle event and redirect to login state/route
In above example you basically add interceptor (https://github.com/johnpapa/ng-demos/blob/master/ng-jwt/src/client/app/services/authInterceptor.js) which looks if any request to the web services failed due to not authorized and rejects the promise returned by $http request
Also
As ionic uses angularjs, for login system there isn't any browser to save cookie or session in order to authenticate for each part of application.
You indeed can use localStorage/sessionStorage to store token and add that token to all requests. That is why you better off having token based auth for your web services, rather than cookie based. (basic auth can do to, just more cumbersome)

Categories

Resources