Managing Push Subscriptions with Installation Objects

When a device registers for push notifications via the client SDK, the push service works behind the scenes to manage the device’s subscriptions. Although the Parse push console allows you to send push notifications from your browser and gives some visibility into this subscription data, developers occasionally need to access this data from outside of the client SDK for operations like
uploading iOS device tokens.

Today, we are introducing the ability for developers to view and modify their app’s subscription data through “Installation” objects, each of which corresponds to an installation of your app on a device. Installation objects are automatically created and modified when SDK push methods like subscribeToChannel and unsubscribeFromChannel are called, and are fetched by the getSubscribedChannels SDK method. You can now read and write this data from outside of the SDK by visiting your app’s data browser or by using your master key in the REST API. For example, by creating new installation objects you can import existing iOS device tokens into your Parse app, and by doing queries against
installation objects you can see how many devices are subscribed to a given push channel.

As always, let us know what you think!

Brian Jacokes
April 30, 2012

AnyWall: An Example Geolocation App with Tutorial

Today, we’re thrilled to announce the release of AnyWall, an iOS geolocation game that is built entirely on Parse. It’s a published app that you can download from the app store and immediately play with. Best of all, we’ve shared the source and included a comprehensive tutorial that shows you how to build AnyWall from scratch.

Getting started with your own copy of AnyWall on your Parse account is easy. Just follow the directions to create an app and add your keys to the Xcode project and you’ll be up and running in no time. Fork it, tweak it, and make it your own. We’re excited to see what AnyWall inspires you to build.

At Parse, we’re big believers in learning through doing. Often, the best way to get up to speed with a new language or platform is simply diving into existing code, understanding how it works, and then making your own changes. This is why in addition to our guides and API references, we also publish a selection of tutorials to bolster your knowledge.

And, this is just the start. We’ll be publishing more tutorials and sample applications. The mobile development world is still young, and we love to give back to the community with helpful resources that not only show you how to use Parse, but how to employ best practices in mobile app development.

James Yu
April 26, 2012

Protect Your App By Limiting User Authentication Methods

Here at Parse, we’re always looking for new ways to help you protect access to your application’s sensitive data. Today we’ve added a new feature to the Settings page for your Parse applications:

With these settings, you can limit the ways that new users can be created for your application. For example, with these settings you can disable anonymous user accounts, require login through Facebook, or restrict login to users that supply a username and password.

For application developers that use Facebook or Twitter login, please add your application IDs and consumer keys to these settings to ensure that only users that have authorized your Facebook and Twitter applications are able to log in as a Parse user.

Please take advantage of these settings and continue to follow the principle of least privilege whenever possible.

David Poll
April 24, 2012

A Beautiful Login Screen For Your Mobile App

Writing a login view for a mobile app is typically a lot of work. The complexity originates partially from the the multitude of login options your mobile app may support; username/password, Facebook, Twitter are among the popular choices. In addition, the login controller needs to handle the cases when the device is offline, when the user forgets his username/password, or when the server is down. Worst of all, just before you think you are done, you need to write a similar controller for sign up.

The above considerations make writing a login screen a daunting task.
Today, we are going to change that with the release of a drop-in view controller which handles all these edge cases for you.

Welcome to PFLogInViewController in the Parse framework. With this class, creating a functional login view controller literally takes a minute. All you need to do is to create it and present it modally:

PFLogInViewController *logInController = [[PFLogInViewController alloc] init];
logInController.delegate = self;
[self presentModalViewController:logInController animated:YES];

With these few lines of code, you will get a beautiful login screen, which is shown below. By default, it comes with login functionalities that include username/password field, a password forgotten button, and a sign up button.


Default PFLogInViewController

PFLogInViewController with all elements

Reskinned PFLogInViewController

What if you also want to support Facebook and Twitter? The PFLogInViewController class is configurable, which means you can turn any feature on and off:

PFLogInViewController *logInController = [[PFLogInViewController alloc] init];
logInController.delegate = self;
logInController.fields = PFLogInFieldsDefault 
                | PFLogInFieldsFacebookButton | PFLogInFieldsTwitterButton;
[self presentModalViewController:logInController animated:YES];

Now you are getting a login view controller that works with Facebook and Twitter. It looks great, and it works on the iPhone, iPad, portrait and landscape.

The following tutorial takes a more in-depth look at the new class:

Read more in our iOS guide. As always, any feedback is welcome.

Andrew Wang
April 23, 2012

Discovering a Major Security Hole in Facebook’s Android SDK

Today, I bring to you a tale of a simple mistake with huge potential repercussions for users. The issue today is Facebook’s, and they handled the situation well, but it could easily have been any skilled developer. In this post, you’ll see how one seemingly innocuous line of code could have allowed malicious Android apps to impersonate you on your acebook account.

Background

Parse includes tools that make it easier to add Facebook support to your application. Developers can use Parse to present a Facebook-managed authentication flow and ask the user to grant specific permissions. To implement this feature, we use Facebook’s Android SDK to get an authorized access token from Facebook.

With this access token it is possible to post messages to the user’s wall, access the user’s profile and friends lists, collect email addresses, and so on. These are all legitimate uses of an access token by an application with no malicious intent. The user has the ability to revoke an application’s permissions at any time, and if the user chooses not to grant permissions to one application, it can still grant those permissions to another application that it trusts.

Another useful developer tool, provided by the Android platform, is logcat, which is essentially a device-wide diagnostic log to which applications and system processes can write. Applications can capture this log for debugging purposes, which when coupled with a bug or crash report can provide a huge amount of insight into the cause of the problem.

One of the permissions an Android app can request is the “Read Sensitive Log Data” extended permission, which allows an application to read from the system’s various log files. This allows it to discover general information about what you are doing with the device, potentially including personal or private information. As a result, users should only grant this permission to apps they trust.

Most Android developers use logcat, and Facebook is no exception. But what happens when an SDK is just slightly too trusting of a built-in tool like logcat?

Discovery

While working on adding Facebook integration to Parse’s Android SDK, I discovered an odd behavior in my test application. Whenever I logged in through the Facebook SDK, a line like this would appear in my logcat viewer:

In plain text, I could see the entire access token that had just been granted after logging in, encoded into a URL.

It wasn’t immediately apparent to me that this was a problem. After all, this was coming from code that my app was running. As long as I was the only one who could see it, no harm was done. But I knew that logcat was essentially a public diagnostic bulletin board for Android applications, so I tried running a few other apps that use the Facebook SDK – big apps from developers like Foursquare, Zynga, and Sony – and observed that they also printed this line after I logged in.

Still, this wasn’t a serious issue if logcat was only visible when debugging was enabled for the device, or accessible only through Android’s developer tools on a PC. However, I knew of a handy little android app called CatLog on the Android market, which is an on-device logcat viewer. My intuition was that CatLog would allow me to see the same information as I was getting while debugging my application, and that if CatLog could do it, I could write a simple app that uses a similar technique to scrape the output of the Facebook SDK in order to “steal” Facebook access tokens from the user of the device.

Sure enough, CatLog displayed the access token for the world to see, and alarm bells went off in my head. To verify that this was an exploitable security vulnerability, I checked that with only an access token, I could access Facebook’s graph API and start pulling down data for that user. Facebook’s own Graph API Explorer made testing this theory easy. The security hole was real.

This was a serious issue, and not just something that would keep me awake at night as a Facebook user. By using an unmodified version of the Facebook SDK with Parse, we were exposing our developers and their apps’ users to the same vulnerability – something with potentially broad repercussions.

Reporting the issue

Before I reported this vulnerability to Facebook, I wanted to be absolutely sure that I had found a real issue. So the night after making my discovery, I sat down to write a quick proof-of-concept application that would exploit this, detecting (in real time), extracting, and using Facebook access tokens silently in the background on my Android phone.

I called my app “FacebookThief”, and just an hour or so later, I had a working proof of concept. In less than 20 lines of non-boilerplate code, I could masquerade as any Facebook user that logged into any app on the device that used the Facebook SDK. It wouldn’t even be clear that my app was the culprit. If my app posted to a user’s profile using the stolen access token, it would show up as though it came from the application from which it was stolen!

The next morning I reported the vulnerability to Facebook, linking to FacebookThief and its source. Facebook responded like professionals. Within a few hours, a Facebook security expert contacted me to let me know they were working to verify the issue, and within 24 hours, they had corrected the issue in the Facebook SDK.

Of course, we immediately integrated the new version of the SDK into Parse.

The trouble with client software

All of this happened mid-February, and trust me, I would’ve loved to shout to the rooftops after making this discovery. But as the severity of the issue sank in, I really began to empathize with what Facebook had on their hands here.

The Facebook Android SDK is software that runs on the client and is built into other applications, so Facebook has no real way to push this update out to all of its developers. Each application developer that consumes this SDK would need to update their applications and push that update out to users. But that’s hundreds or thousands of apps and developers, each with its own user base that needs to move off of the old, vulnerable versions of the apps. Each developer has to manually pull down the latest Facebook SDK, incorporate it into their applications, and push out updates (through various app stores and approval processes) before this problem can be eradicated from the ecosystem. This is something that could linger forever as apps with the vulnerability stop being supported.

Client SDK development poses some unique challenges. You don’t really have control over updates to your own software, so every release has a permanence that is out of your control. At Parse, we’re keenly aware of this, and take great pains to ensure that our SDK doesn’t leave lasting holes in our developers’ apps.

Facebook asked me to wait to disclose this issue until they had a chance to work with major application developers to get updates to their apps pushed out. They have informed me that all of the major developers that use the Android Facebook SDK have now shipped versions that correct this issue.

Fortunately, there has been no evidence that this has been exploited in the wild.

One line of code

Ultimately, this bug came down to one line of code in the Facebook SDK:

Log.d("Facebook-authorize", "Login Success! access_token="
        + getAccessToken() + " expires="
        + getAccessExpires());

It’s a wolf in sheep’s clothing. Logcat is not a safe place to put sensitive data, but it’s easy to mistakenly assume that only developers will see this.

Any Android application that has the “READ SENSITIVE LOG DATA” permission has access to this data. There are legitimate reasons to request this permission, but users should be wary of any app that requests this permission unnecessarily.

The moral of the story

It’s important to take situations like this seriously. It puts users at risk, and this is a problem that’s not isolated to Facebook – it affects any Android developer that has chosen to use the Facebook SDK. So please, take heed:

  • Users: Make sure you keep your apps updated. When security fixes come out, don’t wait –
    update!
  • Developers: Please think carefully about any data that you make public. Logcat is not a safe place to put sensitive information, even if it makes debugging much more convenient. Protect yourself and your users – err on the side of sanitizing data that might be sensitive.
  • Parse developers: We’re looking out for you! Parse updated its SDK to fix this hole within a day of discovering it. We’ve contacted the developers at risk, but if you’re on any version after 0.4.32, you’re already protected.

Update: Users can protect themselves by downloading the latest version of their applications and uninstalling any untrustworthy apps. Fortunately, there has been no evidence that this has been exploited in the wild, but we remind all users to always exercise caution when granting apps permissions.

David Poll
April 10, 2012

Introducing App Email Settings

We added a new section to your app settings page called “Email Settings.” These settings let you fine-tune the ways Parse may email customers on behalf of your app. We wanted to show you the new features in this setting:

Reply-to Email Addresses


The new Email Settings section of App Settings

Want to add a bit more personalization to your user experience? You can now configure the “reply-to” address that users are emailed from when they request a password reset or are asked to verify their email address.

Email Verification

Let’s suppose you wrote the next big personal finance app. A feature which emails monthly finance statements to the user could be very useful, but is very dangerous if the user mistyped his or her email address. Now Parse can try to verify email addresses for you.

Email verification adds the emailVerified boolean value to your User objects. When a user is created with an email or the user’s email is changed, emailVerified is set to false and the user is emailed a link. When the user clicks that link, emailVerified is set to true. Users which were created before email verification was on or which were created without an email will not have the emailVerified key.

Email verification makes it easy to reserve portions of your application for users who have verified email addresses:

- (void)giveCakeToUser:(PFUser *)user
{
    if (![[user objectForKey:@"emailVerified"] boolValue]) {
        // Refresh to make sure the user did not recently verify
        [user refresh];
        if (![[user objectForKey:@"emailVerified"] boolValue]) {
            [self redirectWithMessage:@"You must verify your email address for cake"];
            return;
        }
    }
    // This is a triumph.
    [self warnUserAboutCakeAvailability];
}

Read more in our iOS, Android, or REST guides.

One More Thing…

Good news everyone! Our REST API now supports requesting password resets!

These new features help make the conversation between you and your users more fluid. As always, any feedback is welcome.

Thomas Bouldin
April 3, 2012

Protect User Data With New Parse Features

April Fools’ Day has come and gone, so you can rest assured that the bevy of new features coming your way today is the real deal.

We’re excited to announce 3 new features that will help you protect your Parse-powered application’s data – available today in both our Android and iOS SDKs:

  • Anonymous Users
  • Automatic User Creation
  • Default ACLs

Anonymous Users

Keeping track of your users can be a frustrating task – particularly when you don’t want to have to force the user to sign up in order to user your application. And now that you can’t use UDIDs for this purpose, managing a user without forcing them to log in can be downright difficult. Never fear – Parse is here!

The latest version of the Parse SDK includes PFAnonymousUtils
and ParseAnonymousUtils,
which make it easy to create users without requiring a user name and password. Creating an anonymous user works just like creating a Facebook or Twitter user:

[PFAnonymousUtils logInWithBlock:^(PFUser *user, NSError *error) {
    if (error) {
      NSLog(@"Anonymous login failed.");
    } else {
      NSLog(@"Anonymous user logged in.");
    }
}];

Users that are logged in anonymously are just like any other PFUser – you can provide ACLs for them, save and store data on them, and create relations to them.

Anonymous users are special, however, in that once logged out, the user cannot be recovered – a new user will need to be created, and the original user (and its associated data) will be orphaned.

An anonymous user can be “claimed” or converted into a regular user, keeping the user’s data intact, by calling signUp on the user or linking it to an existing service.

You can learn more about anonymous users from our iOS and Android guides.

Automatic User Creation

Being able to explicitly create anonymous users is handy, but sometimes you need access to a user immediately at application startup, and having to wait for a network call to create the user before assuming that a user is present can add an unnecessary burden to working with user data.

To improve this workflow and allow you to start working with a user object for your application immediately at application start, we have also added automatic user creation:

[PFUser enableAutomaticUser];

After enabling automatic user creation, you can safely assume that currentUser will never be empty. You can start setting fields on the user, setting ACLs based upon it, and otherwise using its value as though it were a full-fledged anonymous user (note: the user’s objectId and username will be nil). The first time the user is saved (or an object with a relation or ACL referring to the user is saved), the user will be automatically created on our servers.

Default ACLs

Parse’s access control mechanism, PFACL, has long been the way to control access to newly-created objects. As a developer, the onus has been on you to ensure that every object created is given an appropriate ACL.

While this is still the case today, protecting the data in your application has just become much easier. It is now possible to set a default ACL for your application so that all objects created after the ACL has been set will automatically be initialized with the proper access controls.

You can initialize your default ACLs like this:

[PFACL setDefaultACL:defaultACL withAccessForCurrentUser:YES];

To read more about default ACLs, see our iOS and Android guides on the subject.

Protecting Your Data by Default

Each of the features we’ve added today is useful in its own right, but ultimately the goal is to make it as easy as possible for developers to set the right access controls on their (and their users’) data.

We strongly recommend that you build your applications to restrict access to data as much as possible. With this in mind, we recommend that you enable automatic anonymous user creation and specify a default ACL based upon the current user when your application is initialized. Explicitly set public writability (and potentially public readability) on an object-by-object basis in order to protect your data from unauthorized access.

Consider adding the following code to your application startup:

For iOS (in application:didFinishLaunchingWithOptions:):

[PFUser enableAutomaticUser];
PFACL *defaultACL = [PFACL ACL];
// Optionally enable public read access while disabling public write access.
// [defaultACL setPublicReadAccess:YES];
[PFACL setDefaultACL:defaultACL withAccessForCurrentUser:YES];

For Android (in Application.onCreate()):

ParseUser.enableAutomaticUser();
ParseACL defaultACL = new ParseACL();
// Optionally enable public read access while disabling public write access.
// defaultACL.setPublicReadAccess(true);
ParseACL.setDefaultACL(defaultACL, true);

Please keep secure access to your data in mind as you build your applications for the protection of both you and your users.

David Poll
April 2, 2012

Archives

Categories

RSS Feed Follow us Like us