Adding User support to your PhoneGap application

This post is more than 2 years old.

A few days ago I wrapped up my series on integrating support with PhoneGap. Now that I've got a good handle on the basics, I thought I'd begin exploring some of the other features. Today I'm going to share an example of adding User support.

Before we get into the code, let's talk a bit high level about what Parse does for User management. Even if Parse did absolutely nothing, you could still easily create "User" types and do your own authentication. But Parse actually provides support for pretty much every User-related need you can think of.

  • First off, Parse supports "User" as a special type of object data. Using this object type will give you a few built-in properties and other features as well.
  • Parse has special methods for registering and logging in.
  • Parse supports automatically encrypting passwords for you.
  • Parse handles email information as well, and will block users who attempt to register with an email address already used. To be clear, email addresses are not required for working with users, but if you do choose to use them, Parse ensures they are unique.
  • Speaking of emails, you can also enable email verification for your users. Parse handles sending the email. Parse handles responding to the verification on the web site. Finally, Parse's API supports recognizing when a user needs verification and doesn't have it yet.
  • If you do use emails with your users, Parse supports a password reset workflow. They don't document what this looks like, but I took screen shots and will share them below.
  • Lastly, Parse can also automatically cache user credentials on the client. This is done in LocalStorage and is encrypted in case someone gets access to the machine.

That's the high level overview, so let's get into the code. For my demo, I decided to build an application that supported registering new users, logging in existing users, and storing simple "Note" objects. These Note objects should be tied to a user so that I can't read someone else's notes. I began by creating a simple home screen.

Clicking on the Register button takes you to a simple form.

As I mentioned above, Parse has a special User type. At minimum, it requires a username and password. Email is supported too, and has special consequences. You can also add anything else you want as well, including birthday, gender, and so on. For my demo I just went with the basics. Let's look at the code that handles the submission of this form.

The beginning of this function is pretty boilerplate. Get the values, do some basic validation, etc. Note though the creation of the Parse.User() object. This differs from regular Parse object creation. The API to set values though is the same.

The signUp method is what handles user creation. The first argument you can ignore (as I did in the code). Look at the result handlers though. For a successful creation, I store a copy in the global scope (that currentUser object was defined earlier) and then simply load the main application page. (You can ignore the "cylon" call there - I'll explain that in a note at the end.)

The error function will get called for all possible cases you can imagine. User already exists? You get an error. Email address already exists? You get an error. You get both an error code and a message. Oddly the message is all lowercase. In production applications I'd probably use the code and handle the messages yourself, but to keep things simple I used it as is. Here is an example.

Let's switch now to the login form. Here's a screen cap.

As you can see, I've got both a login form here as well as a reset password form. Note that while Parse requires a username, the email address is optional. You can also skip asking a user for a username and just ask for their email address. You still store it as a username, but if you want to make the email address the username, that is very much supported as well. Let's tackle login first.

As before, we've got a bit of simple form field grabbing and checking in the first half of the function. The logIn function is where the fun is. You pass in the authentication values and then handle the success or failure. For the most part we handle this the exact same way as registration. If we're good, store a copy of the user and then load the notes page. Otherwise, report the error. In case you're curious, the messages here are lowercase as well.

So what about password reset? The code for that is equally as simple.

As before, almost half of the code is simple DOM manipulation. The Parse API has a simple method to call and our work is done. In case you're curious, this is the email you get:

"notebook" is the name I gave the application. Normally you would have something much more descriptive.

Once clicked, you end up on a pretty simple page on

And finally, you get this when done:

So just to be clear, at no point did you need to actually email your user. You didn't need to set up an email account. Nor did you need to set up a web server. I do think should perhaps offer a bit of customization here, perhaps for paying customers. I'd imagine it would be nice to be able to include an application logo of some sort, and perhaps add a bit of verbiage to the screens.

Oops! I just checked, and yes, gives you access to modify the email templates as well as the web page templates. Kick. Ass. This is paid-level access only (specifically Pro/Enterprise), but the options definitely exist. They even have a way to host the files on your own server (well, host an iframe) so users never see a URL.

That's login, registration, and password reset. I hope you agree - it's damn simple. I mentioned earlier that Parse can cache authentication information on the client. You can write code to check for this easily enough:

This is an optional feature though and you do not have to make use of it. As I said, it makes use of LocalStorage. I had a key named this:


with a value of:


Ok - we've covered registration and authentication. What about data? You've got a few options here.

First off - Parse has a rich access control feature. You can provide various access levels (ACLs) on every piece of data in the system. Parse also supports Groups as well, but I'm not covering that in this entry. At a basic level, if you want to create an object that only the current user can read, it takes one line of code:

someObject.setACL(new Parse.ACL(currentUser));

While this works, you also have another option, which is to simply add a "owner" type property. So for example:

someObject.set("creator", currentUser);

Personally, I think it makes sense to use both. You're explicitly saying "Ray made this" as well as "Only Ray can read this". Together it makes getting your data to a specific user that much safer.

To test this, I added a simple form that allowed you to write some text, the note this application was built to support.

And here is the code that handles creating the object. As I said, I made use of both methods of linking the data to the user.

Conversely, getting my notes requires simply adding the current user as a filter. Because of the ACL, if a hacker (or script kiddie, like me), modifies the user values somehow or just does a query without the filter, the ACLs will kick in and ensure I can't read someone else's content.

And... that's it. Before I leave you though, let me share a few tips. First, you want to read the official docs yourself. I didn't cover everything so take a look yourself.

Secondly, Users are called out in your dashboard. You can even manually change passwords there, which was helpful during testing.

Thirdly, don't forget what I said in my last series. You have options to block anonymous users from doing anything with your application at all.

Lastly - also supports Facebook and Twitter integration. That's what I'll be covering in my next entry.

Full code of my ugly, but usable, demo application is below.

Ok, a quick side note. You can stop reading now if you want and won't miss a thing. When I built this application, I wanted a simple way to handle having a 'single page' frame for my application. By that I mean, when you clicked the Login button for example I wanted to do an Ajax-call for the content and load it in. In other words, once you hit index.html, you never actually leave that. jQuery Mobile is perfect for that. But... I kinda wanted to try something different. I wanted JQM-like navigation with zero UI changes. I whipped up something I called Cylon. Dumb name, I know. But it was kinda fun to build. I doubt if I'll open source it (well, technically, you can grab the source in the zip and use it if you want) but I wouldn't mind any feedback on the code if you want to give it a shot.

Download attached file.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by bender posted on 11/1/2012 at 3:13 AM

Hi, awesome blog. Can you please tell if its possible to download data that is hosted on parse (in case you move to your own server)

Comment 2 by Tom posted on 11/1/2012 at 3:42 AM

Hi Ray:

Awesome introduction to Phonegap+Parse User. Is there any possibility that you would cover Phonegap+ParseFacebookUtils?

Comment 3 by sam posted on 11/2/2012 at 1:02 AM

awesome article! I would love to see this incorporated with Facebook authentication as well..

Comment 4 by Raymond Camden posted on 11/2/2012 at 1:02 AM

Bender: Absolutely. That's one of the best features. If you are worried about Parse going bankrupt or just want to keep a copy, you can export data right from the dashboard. I thought they had an API as well, but I don't see it.

Tom: I plan on covering Facebook and Twitter next.

Comment 5 by Brandon posted on 11/8/2012 at 9:37 AM

Great blog! I've found a number of your blog postings very helpful.
Have you done any in-app purchases with phonegap and parse yet?

Comment 6 by Raymond Camden posted on 11/8/2012 at 5:21 PM

Nope, not yet. Ecom stuff is a bit harder to test normally. ;)

Comment 7 by Tim B posted on 11/10/2012 at 1:50 AM

I tried opening the zip package in chrome but the ajax didn't work. Packaging it into a phonegap app then opening it in the android emulator made it work. Is there any way to run it from a browser?

Comment 8 by Raymond Camden posted on 11/10/2012 at 1:54 AM

If you can't run it from a local web server, try with this Chrome command line:

(obviously this is for Mac, you can tweak for PC)

open -a /Applications/Google\ --args --allow-file-access-from-files --disable-web-security

Comment 9 by Tim B posted on 11/10/2012 at 1:58 AM

K, I tried the command line but no luck. I went ahead and looked at the cylon.js file. It looks like its only listening for touch events and since I can only send click events in chrome it won't work unless I switch it to jquery mobile or tweak the js.

Comment 10 by Raymond Camden posted on 11/10/2012 at 1:59 AM

Oh, in Chrome, open dev tools, go to settings. There is an option to emulate touch.

Comment 11 by Tim B posted on 11/10/2012 at 2:10 AM

Sweet that worked.

Also the app isn't allowing me to register or login, no errors. It appears as though its not communicating with Parse. Do I need to recreate your DB and enter my own Parse API Keys. Or is it a matter of adding the parse android jar to my phonegap app and redeploy?


Comment 12 by Raymond Camden posted on 11/10/2012 at 2:19 AM

It should work. DO you see anything in console?

Comment 13 by Tim B posted on 11/10/2012 at 2:26 AM

Nope, the console is clear, no errors. However I just deployed it in the android emulator and its working. Just not working in chrome, I guess.

Comment 14 by Raymond Camden posted on 11/10/2012 at 2:31 AM

Weird, I did all my testing there. Well, just happy you got it.

Comment 15 by Tim B posted on 11/10/2012 at 2:32 AM

Maybe its a pc thing :)

Anyways, thanks!

Comment 16 by Pete posted on 11/14/2012 at 3:17 PM

Parse keeps on getting better, I haven't looked into the User side of things yet, but reading this is making me wonder why I bother with a MySQL database at all any more.

I know you can do basic queries with Parse, can you get really complicated with Joins and Subqueries?

I'm leaning towards ditching my server and just having simple web site hosting and using Parse for everything else.

Comment 17 by Pete posted on 11/14/2012 at 4:01 PM

Ok, so I read through the docs, relational objects and queries are all possible and look pretty easy to do.

I need to be using Parse more.

Comment 18 by Raymond Camden posted on 11/14/2012 at 5:26 PM

Glad you like it. :) I still plan on doing Twitter/FB integration soon - just have other stuff in the pipeline.

Comment 19 by Justin posted on 11/15/2012 at 12:42 PM

Great site and great tutoials.

How would I make it so that once the user is logged in, they can see all the notes? Sort of like a rough forum.

Comment 20 by Raymond Camden posted on 11/15/2012 at 7:56 PM

Justin, I talk about getting "your" content at the end of the blog entry - does it not make sense?

Comment 21 by Alex posted on 12/20/2012 at 11:11 PM

Still looking forward for your promised <-> Phongap login integration through parse facebook user management without the need to open a Website. Its not that easy... but would be incredible usefull

Comment 22 by Raymond Camden posted on 12/20/2012 at 11:14 PM

Still planning it. Life got super busy. I had hoped things would slow down before XMas, but I've got some big presentations right after the break. It may not be done till mid Jan.

Comment 23 by sam posted on 3/14/2013 at 2:57 AM

Are you still going to do a FaceBook or Open Id integration?

Comment 24 by Raymond Camden posted on 3/14/2013 at 3:43 PM

I still _want_ to. Just not sure when.

Comment 25 by Steve posted on 4/23/2013 at 9:02 PM

Really good stuff. Considering having a free version of my app -- which currently calls a .net Web API service to do look up some values on my SQL Server (hosted) db and perform some math before sending results back to phone.

As for a paid version of the app, Parse seems to be a good way to have a db of paid users and to handle authentication, keeping the Web API & SQL Server stuff as is.

Comment 26 by Rigel posted on 5/27/2013 at 6:56 PM

Hi I am trying to use parse-1.2.7 with ember tool. when I include Parse from cdn it works fine. But when I download a copy it gives me error of list of dependencies like failed to require LocalStorage, xmlhttprequest. I am using LAMP. I am noob can you give me some pointer.

Comment 27 by Raymond Camden posted on 5/28/2013 at 2:52 AM

I'm sorry, but I don't use Ember.

Comment 28 by Pratik posted on 6/21/2013 at 4:12 PM

Hi I am trying to do the same thing using , can u please help me with this ? how can we create same thing using and


Comment 29 by Raymond Camden posted on 6/21/2013 at 5:33 PM

I don't know Can you read their docs and share your experience?

Comment 30 by Pratik posted on 6/24/2013 at 10:47 AM

Hi Raymond ,
I tried the this tutorial on phonegap build . i am getting an error saying "connection to server was unsuccessful "

Comment 31 by Raymond Camden posted on 6/24/2013 at 4:40 PM

You got that on PhoneGap Build, or did you get it when you ran the app?

Comment 32 by Pratik posted on 6/24/2013 at 7:31 PM

Yes i did this in phonegap build ...but was unable to get through login and registration screen ..and was not able to see any data in ..
I am trying to do user support but a slight difference in the third page ..i mean instead of uploading and saving notes ..i want to upload music files .

Comment 33 by Pratik posted on 6/25/2013 at 1:36 AM

Hello , i think i am going wrong somewhere.
i also tried this by downloading the source code zip file .. updated the application id and js key from parse . but still wen i run the app on my phone ..i can see the first screen and when i click registration , fill my details and hit register button then it again takes me back to the first screen with login and registration button , the same thing happens even when i click login on first screen ..and as soon as i fill details and hit login button it takes me back to first screen .

Please help me


Comment 34 by Raymond Camden posted on 6/25/2013 at 5:26 PM

I'd suggest running this via the Ripple emulator so you can use the Chrome debug tools. That's all I can recommend from here.

Comment 35 by Pratik posted on 6/25/2013 at 7:15 PM

Thank you Raymond ..
I tried your another stuffs u blogged regarding integrating parse with phonegap ..
all those tutorials worked even the offline support with parse but I am just unable to get this run successfully.

I am not getting the point where I am going wrong ..Please suggest me. .


Comment 36 by Raymond Camden posted on 6/25/2013 at 7:19 PM

Pratik, did you see my comment? You need to try running this using Ripple and use Chrome's debug tools to try to diagnose what the error may be. I've got a blog post on using Ripple as well as ones that talk about Chrome Dev Tools. I can't just tell you what's wrong.

Comment 37 by Pratik posted on 6/25/2013 at 7:21 PM

When i tested this in my android phone , i was not able to see any validation messages or error messages related to username and not even reset password thing is not working ..
and mainly I am not getting any data in parse .

Comment 38 by Pratik posted on 6/25/2013 at 7:24 PM

Ok Raymond , Will test this in ripple and will check and get back to you.

Thank you

Comment 39 by Pratik posted on 6/25/2013 at 9:11 PM

Hello Raymond ,

I tested the code in ripple emulator and this is the error message i am getting -
"Validation Failed"

"Config.xml file could not be found in the application's root or is malformed xml"

and in developers tools ..

the error I am getting is this .
"Uncaught type error : cannot read property 'type' of undefined"
inside this function

function deviceready() {
console.log("device ready to roll");
if(navigator.connection.type == Connection.UNKNOWN ||
Uncaught TypeError: Cannot read property 'type' of undefined
navigator.connection.type == Connection.NONE) {
//handle user being offline
} else {
console.log("Initialize Parse");

Comment 40 by Raymond Camden posted on 6/26/2013 at 11:39 PM

Ensure you are using the latest PhoneGap SDK/JS file.

Comment 41 by John posted on 5/20/2014 at 1:11 AM

I know this is an old post, but I came across it and tried it out but haven't been able to get it to work yet. I've tested on a local server with ripple, and even tested on a live server with ripple and the browser on my phone. I connected my account to it and whenever I enter my username/password and hit login it just refreshes to the login page.

Any idea what could be causing that?


Comment 42 by Raymond Camden posted on 5/20/2014 at 1:20 AM

Do you see anything in the console?

Comment 43 by John posted on 5/20/2014 at 1:21 AM

No, that's the weird thing, nothing is thrown in the console, it just goes right back to the first page. I even updated to the latest version of Zepto.js

Comment 44 by Raymond Camden posted on 5/20/2014 at 1:24 AM

Maybe add 'preserve log' to your console settings and see if it is being cleared away. Is it online where I can run it? I can just fire deviceready manually.

Comment 45 by John posted on 5/20/2014 at 1:27 AM

I've got it hosted online here:

I basically just changed the App key and JS key then uploaded it to see if it worked or not, since the custom one I built based off your tutorial wasn't working.


Comment 46 by Raymond Camden posted on 5/20/2014 at 7:08 AM

You want to make sure you install the connection plugin for PhoneGap. Did you ?

Comment 47 by John posted on 5/20/2014 at 4:05 PM

That could be what is causing the issue then, I don't know what that means, I was trying to run everything from the web, not run it through phonegap to create a stand alone app.

Comment 48 by Raymond Camden posted on 5/20/2014 at 4:08 PM

You need to read my blog article on PG3 and plugins:

Comment 49 by Eugene posted on 2/6/2016 at 4:09 PM

Hi Raymond! Do you happen to have the full demo code around?

Comment 50 (In reply to #49) by Raymond Camden posted on 2/6/2016 at 5:07 PM

I've put it here now: http://static.raymondcamden....

Note - I do NOT recommend doing anything with Parse now. Facebook is killing it off.

Comment 51 (In reply to #50) by Eugene posted on 2/6/2016 at 5:44 PM

Thanks Raymond! I'm counting on someone to deploy a commercial offering off their open source server. Worst case Azure made it possible to deploy the server on your own.