I'm working on a fun little project that will hopefully see the light of day sometime soon. It involves a bunch of things that are new to me, and digging more in-depth on some other things that I've been using for a while. One of the new things is using the Icenium Everlive service to store my data for me. Everlive is a "back-end as a service" that stores JSON documents in the cloud, allowing me to read, write, update and delete the information through a RESTful API or through various SDKs that are available.
I'm loving Everlive so far - it's easy to get a project up and running, and the SDK makes it simple to work with. In the process of setting this up and working with it, though, I noticed that every time I refreshed my browser I would be logged out of my app. I asked the Everlive team about this and they said that the SDK doesn't cache the user credentials between page refreshes. Since I'm building a single-page app, this isn't too much of a problem. The user is logged in and the JavaScript code stays alive while they use the app. But if they did hit refresh or navigate somewhere else and then come back, they would be logged out. This isn't the behavior that I want for my app, so I added my own code to cache the user credentials using Kendo UI's view-models (the observable object) and the Kendo UI LocalStorage DataSource adapter from the Kendo UI labs.
Getting an Everlive app up and running is easy. Once you've created your app on the Everlive site, you only need one line of code to get the SDK configured for your app:
new Everlive("my api key");
You don't even need to assign this to a variable, since the
SDK will store the current instance in Everlive.$
, making
it easy to access whenever you need it.
Authentication with Everlive is equaly as simple. Every app
that you create in Everlive has a Users type already, and
you can add users through the Everlive website to start
with. Once you have a user in your project's data, and
you have Everlive initialized, make a call to the Users.login
method. You'll need to supply a username, password and optional
callback methods for success and failure.
Everlive.$.Users.login("some user", "some password", successCallback, failureCallback);
If the login was successful, the successCallback
will be called,
providing an access token and a few other bits of the current
user's credentials.
If the login failed, the failureCallback
will be called, proving
a reason for the failure.
Setting up the view-model is simple enough - define an object
as a kendo.observable
. In this case I'm going to provide a
default empty object for a credentials
attribute on the observable.
There are multiple pieces of information that come back from the
login success callback, and it will be easier to store it all, this
way.
var user = kendo.observable({ credentials: {} });
Now when the success callback fires, grab the .result
and
stuff it in to the user
object.
var user = kendo.observable({ credentials: {} }); Everlive.$.Users.login("me", "secret", function(data){ user.set("credentials", data.result); });
LocalStorage is a modern browser tool that allows you to store data in the browser on a computer. The data is stored in a way that allows the browser to retrieve it again, later - even after you have closed the browser and re-opened it. This gives you a lot of opportunity to create individual user settings and other things that are specific to a particular user and browser on a computer. It also makes things like storing the authentication token from Everlive really easy.
To get the data saved so that it can be retrieved later, grab the
LocalStorage DataSource adapter
and drop it in to the project. Then add this to the user
object
as a datasource. To ensure the credentials are stored in
local storage at the same time that they are stuffed in to the
user object, create a method called
storeCredentials
.
var user = kendo.observable({ // default empty credentials credentials: {}, // configure the local-storage adapter dataSource: new kendo.data.extensions.LocalStorageDataSource({ itemBase: "myApp-users", schema: { model: { id: "Id" } } }), // encapsulate storing the credentials // in the view-model and localstorage storeCredentials: function(creds){ // wrap the credentials in an observable var credentials = kendo.observable(creds); // set and store the credentials this.set("credentials", credentials); this.dataSource.add(credentials); this.dataSource.sync(); } }); // perform the login and store the result // in the user view-model Everlive.$.Users.login("me", "secret", function(data){ user.storeCredentials(data.result); });
Note: if you want to reduce the data stored in the localstorage, you can override the toJSON method on the view-model, to return only the data you want to store.
Now when you log in, the current user will be stored in the local storage of your browser. But this is only half the steps you need. When the user refreshes the page, you will also need to read the localstorage to see if you need to pull the current user out or not.
The code that initializes Everlive needs to account for the
current user, if there is one stored in localstorage. Once again,
a method will be added to the user
object to retrieve the
data, if it exists.
var user = kendo.observable({ // ... existing methods and config, here // load the credentials out of // the localstorage, and populate // the user object appropriately loadCredentials: function(){ // read the data and retrive it // from the datasource this.dataSource.read(); var credentials = this.dataSource.view()[0]; // set the data on this user if (credentials){ this.set("credentials", credentials); } // return the loaded credentials so they // can be used immediately return this.get("credentials"); } });
Adjust the code that initializes Everlive, to account for the current user if there is one.
var credentials = user.loadCredentials(); new Everlive({ apiKey: "my api key", token: credentials.get("access_token") });
Now when the user refreshes the page, and they have previously logged in, the will still be logged in. At least, the access token will still be available.
Having an access token available does not guarantee the user is logged in. It only means you have an access token. It also doesn't mean that you have all of the user information - things like their name, email, etc.
To verify, 100%, that the user is
logged, and to retrieve the rest of the user information that
your app will need, you have to call
the Users.currentUser()
method on the Everlive instance. This
method will reach out to the server with the current access token
and retrieve the rest of the info about the user.
Everlive.$.Users.currentUser(function(data){ data.result; // the user info }, function(error){ error; // error info if no current user });
After calling this function and providing the needed success and failure callbacks, you will have knowledge of whether or not the user is authenticated. You will also have the user's information if they are authenticated.
About the Author
Derick Bailey is a Developer Advocate for Kendo UI, a developer, speaker, trainer, screen-caster and much more. He's been slinging code since the late 80’s and doing it professionally since the mid 90's. These days, Derick spends his time primarily writing javascript with back-end languages of all types, including Ruby,