Worklight v6: use multiple JSON stores concurrently in app - ibm-mobilefirst

Is it possible to use two or more JSON stores in a Worklight app at the same time (without switching back and forth)? When I initialize a second JSON store with a username/password, collections in the "default" JSON store that were initialized properly become inaccessible.
Given that many functions in the JSON store api does not let you specify a target store, I am guessing that using multiple stores concurrently is not possible. If this is true, then how does one address the use case where it is necessary to:
Encrypt sensitive user data, and
Need access to non-sensitive data before user is authenticated.

The username field you pass to init is basically the file name for the store, for example:
WL.JSONStore.init(..., {username: 'store1'})
You will have store1.sqlite on disk, no encryption. If you want to switch to another store simply call:
WL.JSONStore.closeAll()
The closeAll function will kill all database accessors. Then you can start a second store with a password, for example:
WL.JSONStore.init(..., {username: 'store2', password: '123'})
That will create a store2.sqlite file encrypted with 256-bit AES encryption.
If you want to switch back to store1, simply call WL.JSONStore.closeAll() and then WL.JSONStore.init(..., {username: 'store1'}).
Currently you can not access store1 and store2 at the same time. You can open a feature request here.
The .sqlite files are mentioned here if you want to see them on the file system, and a bit of their internal structure is mentioned here. The code snippets above don't show it, but make sure you take into account that most JSONStore API functions are async, read more here.

Related

How to store a user object in a web application?

I'm building my first 'bigger' web-app (only for learning purposes & my portfolio) with the vue.js-framework. I want to implement (for the fist ever time) the possibility to login using Google's API. My question is: where would I 'store' the user-obj? It should contain information like the user-id, name, email, ... . Would I store that obj in a Vuex store in my case? Or do I not even need to store such an object as the API provide all these information?
Well, it totally depends on the needs of your project and the information that is being stored.
If the information being returned in your user object doesn't contain any sensitive information that can be used by potential hijackers to steal other information then you could always store it in local storage, cookies or runtime variables in your code. Normally, vuex store is used for manipulating the local storage. This really helps when you are accessing the data from local storage via multiple components or nested components.
But if you have sensitive information being returned from the authentication authority, like the user id or user hash string then you might not want to store them in your local storage.
Additionally, you should only use this when:
You want to keep a track of user details even when the user closes and re-opens the browser
Passing the data set from one component to all other components is not really feasible
You need to keep the state of the data set synced in all components, so if it changes in one place, it will auto-reflect in the other place.
You need to frequently access the same dataset and it doesn't really change often, so as to avoid multiple api calls to back end server.
One scenario, I can think of is of the JWT token authentication. If you're not familiar with this approach, we usually authenticate the user and store his token in the local storage via vuex and all the api calls in all the components and views start using this same token as bearer token in the requests. When the token expires a new token is fetched and updated in local storage and the change is automatically reflected in all other places.
So it makes sense to check the needs of your project/code. If your project demands the use of the returned user object and it's safe to store it, please go ahead by all means!

Ways to store Client ID and Secret securely for automated executions in Google Scripts

I'm writing a Google Script that will call an external API and pull the resulting data into a Google Sheet. The API requires a Client ID and Secret value for authorization, and I need to keep those values secure. I would also like to trigger the script to run periodically (basically, I'm trying to automate the updating of this sheet as much as possible).
I'm no data security expert, but keeping the Client ID and Secret hardcoded seems like a terrible idea. Most of the search results I've found recommend using the Properties Service to store those values, but in order to set those properties I'd have to hardcode them in the same script, correct? If so, that doesn't solve the security problem.
Other recommendations involve prompting the user to enter the credentials to authorize each run of the script. This solves the security requirement, but I want this process to be as automatic as possible. If I'm opening the script and providing my credentials each time it runs, then I may as well skip the triggered executions.
Are there any other solutions? For context, I am the only person who needs to access this script and no one else should be able to access the Client ID and Secret.
Since you are the only one who has access to the script (having View access to the spreadsheet doesn't allow users to look at the bound script), hardcoding the Client ID and Secret shouldn't be a problem. Just don't give them Edit access to the spreadsheet.
If you don't want to hard-code the data directly anyway, you have some alternatives:
Using Properties Service:
Use Properties Service, as you mentioned. You could, for example, set the Client ID by running this once (in the legacy IDE, you can set these properties manually too):
function setClientId() {
var props = PropertiesService.getScriptProperties();
props.setProperty('Client ID', '{YOUR_CLIENT_ID}');
}
Once the property was set, you can remove '{YOUR_CLIENT_ID}', or even the whole function, if you don't want to keep it hard-coded. The script could then retrieve the stored property the following way:
function getClientId() {
var props = PropertiesService.getScriptProperties();
return props.getProperty('Client ID');
}
Using library:
Another option could be to store this information in a different script, to be used as a library (see Gain access to a library):
var CLIENT_ID = "YOUR_CLIENT_ID";
var SECRET = "YOUR_SECRET";
And then import this library in your main script (see Add a library to your script project). In the sample below LIBRARY is the library Identifier name:
Code.gs (from main script):
function getData() {
const clientId = LIBRARY.CLIENT_ID;
const secret = LIBRARY.SECRET;
// ...
}
Note:
Please note that, even if you don't hard-code your data directly, anyone who can execute your script can potentially retrieve this data. For example, they could log what's returned by getClientId().
If the script has access to some data, users who can execute the script can access this data too.

Shopify app access token - how to make it more secure?

When store owner installs my app I save access tokens into database for later use. Having access tokens from store is huge security responsibility because anybody with these tokens can modify stores from any domain/address, there is no ip or domain lock.
What method could I use to make this more secure? I was thinking to save tokens offline and then upload it only when needed (in case I need to make some global updates for all stores), then delete it again. In case when merchant access app configuration within admin, I would just save it into session. Is there any better method?
Good question.
I save them in a database as well but I encode them with a separate key from the Shopify App password. That way even if someone have access to the database because of some backdoor entrance he won't be able to use them. That said if someone have access to the code he will be able to figure out how to decrypt it since he will have access to the key.
That said I make sure that each and every request is authenticated before I show any response from the server. Since I'm using NodeJS as the back-end I make sure that there are no global variables that can be accessed or modified from different stores. Everything is neatly scoped in separated functions so that the session is scoped for the current store and no other ones will be able to dirty the other store session.
In addition I make sure that there is a webhook that fires when the client uninstall his app in order to clear my database from any information regrading his store.
I know some people are using sessions for this ( online method ) but they pose other problems that I didn't like so I stuck with a database ( offline ) since that is the quicker way to access the App instead of multiply redirects in order to save the session.
As for proposals I can give you a few tips that I learn on my way while building a few basic Apps. ( I'm not an expert on the subject by any means )
don't rely on any cookies when it comes to sensible information
authenticate every request that comes from the front-end
don't trust the user and validate any input that comes from the front-end
don't over-complicate your setup, while it's good to have high security it's bad if it makes your app slow for the user and you lose customers
look to other ready to use popular solutions that can guide you to the correct path
don't get greedy with the App scopes, only request the scopes that you need for you app
remember to clean up after yourself when it's possible but don't over do it ( too many Apps modify the code of customers and break it only to prevent any way to clean it afterwards ) Example use the ScriptTag API instead of a liquid snippet using the Asset API. If you have to use the Asset API add only the parts that you know that won't break a site. Creating a variable is ok if you are using var if the site supports IE11 creating a variable using const or let is not OK or using vanilla JS is OK but using jQuery without knowing for sure that the site has it installed globally is not OK.
More insights on the matter can be seen here:
https://help.shopify.com/en/api/getting-started/authentication/oauth/api-access-modes
https://community.shopify.com/c/Shopify-APIs-SDKs/Best-way-to-store-shops-that-have-installed-my-app-and-their/m-p/402972

Express: Using Passport to authenticate using a session

I am using Express 4 with Node.js - I have successfully implemented Passport to authenticate with a username/password. But how do I get Passport to authenticate with just session information?
How would I create a custom Passport strategy to take the session info and compare it with a particular user's info?
I am looking for this:
passport.use(new SessionStrategy(function(req,res,done){
if(req.session blah blah blah){
???
}
});
);
I really have no idea what the best way to do this is. Perhaps I store the user's latest session information on the backend-database. So instead of finding a user with their username, I find a user with the sessionid?
One answer seems to be the following:
This is the code to put the session-id into a cookie and retrieve the data when the user comes back. No strategy required.
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
You have two options :
Use persistent session store
JSON Web Token
For implementing persistent session, you can use MongoDB session store or Redis Session store.
If you want to use redis then make use of connect-redis npm package. If you want to use MongoDb as session store then make use of connect-mongo npm package
There are some settings which you need to do in you app.js/server.js. In one of my demo i am using Redis Session store with PassportJS, if you are looking for example, feel free to look here.
If you want to use JSON web tokens, there are many different implementations available. I am using jsonwebtoken. I implemented this using PassportJS, ExpressJS and AngularJS in front End. For example look here. Tokens are encoded and stored in browser's local storage with a secret key.
I would suggest you to go for JSON web tokens, read it in detail because that is how most of the major web apps are developed.
Both of my examples are working prototype. Let me know if you need more help.
The ideal way to do this is to store a user ID in the session (or a JWT as #NarendraSoni mentioned). The main idea is to store as little useful information as possible in the session, as you should treat it like it's publicly available to everyone.
If you do store just a user ID, for instance, then each time you receive a request (req.session.userId, for instance), you could simple execute a database query to retrieve that user by the ID.
This is fast (especially if you use a server-side cache like memcached or redis), and causes very little latency. It's also secure, and prevents leaking user information to the browser.
If you're looking for a simpler way to handle this stuff in your app, you might want to check out my authentication library: express-stormpath. It does all of this stuff out of the box, is very secure, and provides lots of helper utilities to get you going faster: you can store custom data in accounts (like mongo), you can restrict users based on permissions, you can do API authentication, etc.

Worklight Online + Offline Authentication

I'm trying to achieve the following through Worklight.
My app has two sets of features. One set of features can be accessed only when the app is connected to the server and the user is authenticated. Another set of features can be accessed offline but they require data from an encrypted JSONStore.
I have a JSONStore on the client device which is initialized using a password. Therefore, the data in the store will be encrypted. Also, this JSONStore is synced to a database on the server through an adapter.
I have also setup another adapter which authenticates the user by using another set of credentials stored in a database. The user can be authenticated only when the app is online.
What I want to do is to unify these two approaches so that the user needn't enter two sets of credentials to access these two different sets of features. One possible solution that came to my mind is just to encrypt the JSONStore and perform the adapter authentication without the intervention of the user. But I don't think that it's secure.
Any advice or approach to solve this issue?
The following is just an idea, I'm not a security expert.
Requirements:
To use the offline features you must have been online and authenticated at least one time.
Your application must have an login view to input some credentials (e.g. username/email and password).
Steps:
First time the user inputs the correct credentials and successfully authenticates with the server: hash the credentials. For example: var myHash = md5(loginField.getUser() + loginField.getPassword()). You can find md5 JavaScript libraries on Github.
Use that hash to initialize the store. For example: WL.JSONStore.init(..., {password: myHash}).
Send the hash to the backend over HTTPS, you will need it if the user changes his/her credentials. No need to save the credentials or the hash on the device (loginField = null; myHash = null). Alternatively, you could just generate the hash on the server and store it, without having the client send it back, just make sure both client and server are using the same hashing algorithm.
When working offline, ask the user for his/her credentials, hash them and use it to access data inside the store.
If the user changes his/her credentials (e.g. via the web interface for your application), the hash will be different and store won't init. However, the user should've successfully authenticated with the server with the new/valid credentials. Ask the server for the old hash, init the store with the old hash, and change the password to init the store to the new hash based on the new/valid credentials. For example: WL.JSONStore.changePassword(oldHash, newHash).
Optional: You may want to consider using a salt. For example: var salt = Math.random(), myHash = md5(loginField.getUser() + loginField.getPassword() + salt).
You will need to store the salt somewhere so you can re-generate the hash once the user returns to the application. You should be able to init another unencrypted store to persist it. For example WL.JSONStore.init(..., {username: 'metadata'}).then(function(){/*add salt to store*/}). More information regarding using two stores here.