Integrating GaitAuth™ into Your Android App

GaitAuth™ is an SDK offered by UnifyID that allows you to authenticate your users based on how they move. This post demonstrates the process of adding GaitAuth to a simple Android app.

The UnifyID Developer Portal has high-level documentation that covers the basics of the GaitAuth SDK integration process. There are also auto-generated JavaDocs available for the specific details. The goal of this post is to meet the two in the middle and give some more color to the integration process. By the end of the post we’ll have built a sample Android app that uses GaitAuth to train and test a GaitModel. Along the way, we’ll also explore relevant best practices and important implementation details.

The Sample App

All of the sample app code is available on GitHub. To get a feel for the training and testing process you can build the app on your phone and try it for yourself. If you want to get right to building your own app, you can treat the repository as a collection of helpful code snippets. You can also use the code to follow along with this post in depth. Not all of the code is shown in this post, the code that is shown has been abbreviated for simplicity’s sake. Links to the original code on GitHub are provided at the top of the snippets.

The sample app closely mirrors the functionality of the GaitAuth SDK. On the starting screen you are presented with the option to create or load a model. You’ll want to create a new model when you first use the app. In future uses, you can use the load option to skip training. After creating a model you’re ready to collect data and train the model. First, turn on collection (it will continue to collect even if the phone is locked or the app is backgrounded or closed). Once you’ve collected some features you can add them to the model. After you’ve collected enough data you can train the model. While you wait for the model to train (which may take a few hours), you can manually refresh its status.

If the model fails to train you’ll need to start over by pressing the trashcan icon in the top left corner. When the model successfully trains you’re ready to test it. Turn on feature collection and walk around for a while. When you are ready, stop collecting features and score them. This will graph the scores and show you an authentication decision.

Now that we know what the sample app does, let’s go build it.

Configuration & Initialization

Adding GaitAuth to our Gradle configuration is a good starting point. We’ll also need to request some permissions in the Android Manifest. We can follow the steps outlined in the Developer Portal documentation to take care of that.

Before the GaitAuth SDK can be used anywhere in the app it must be initialized. The initialization is trivial; always initializing it before using it is harder. In something straightforward like this sample app we can simply initialize it in the onCreate method of the MainActivity.

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/MainActivity.java#L144
if (GaitAuth.getInstance() == null) {
    // First initialize the UnifyID Core SDK
    UnifyID.initialize(getApplicationContext, SDK_KEY, USER, new CompletionHandler() {
        @Override
        public void onCompletion(UnifyIDConfig config) {
            // Second initialize the GaitAuth SDK
            GaitAuth.initialize(context, config);
            // Save these values for debugging purposes
            Preferences.put(Preferences.CLIENT_ID, config.getClientId());
            Preferences.put(Preferences.INSTALL_ID, config.getInstallId());
            Preferences.put(Preferences.CUSTOMER_ID, config.getCustomerId());
            startGaitAuthService(context);
            route();
        }
    });
}

When initialization succeeds we squirrel away a couple of relevant details in the Shared Preferences (the Preferences class hides the idiosyncrasies of the Shared Preferences API). These will come in handy for debugging. You can view them by tapping on the info icon in the top right corner of the sample app. We also start a foreground service — more on this later. Finally, we call route which determines what the app does next.

In an app with a more complex workflow, initialization of the GaitAuth SDK may not be so simple. In these scenarios we recommend you wrap the SDK in a class that protects its usage. With some simple synchronization this wrapper can ensure that the SDK is never used uninitialized.

Two important points remain. First, remember that the SDK key is a sensitive value and should be protected. In the sample app we ask the user to enter the SDK key the first time they use the app. For an app in production, something like Android Keystore can be used. Second, the user value has a few important stipulations on it. It must be unique, immutable, and should be unrelated to any personally identifiable information. We don’t recommend using things like email addresses or phone numbers for the user value.

The GaitModel

Now that we’ve gotten through the drudgery of initialization it’s time to talk about the star of the show — the GaitModel. In a sense the sample app can be viewed as a tool for managing the lifecycle of a GaitModel. It creates a new model, loads training data into it, initiates training, and then tests the model. For this reason, the sample app’s routing is based on the status of the current GaitModel.

The sample app uses a single-activity/multiple-fragment architecture where each fragment is a different screen. In the MainActivity after the initialization of the GaitAuth SDK the following routing code is run.

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/MainActivity.java#L185
private void route() {
    // Load the id of the current GaitModel
    String modelId = Preferences.getString(Preferences.MODEL_ID);
    if (Strings.isNullOrEmpty(modelId)) {
        showFragment(new SelectModelFragment());
    } else {
        loadModel(modelId);
    }
}

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/MainActivity.java#L287
private void loadModel(String modelId) {
    AsyncTask.execute(() -> {
        model = GaitAuth.getInstance().loadModel(modelId);
        Preferences.put(Preferences.MODEL_ID, modelId);
        renderFragmentBasedOnModelStatus(model.getStatus());
    });
}

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/MainActivity.java#L255
private void renderFragmentBasedOnModelStatus(GaitModel.Status status) {
    switch (status) {
        case CREATED:
            showFragment(FeatureCollectionFragment.build(gaitAuthService.isTraining()));
            break;
        case TRAINING:
            showFragment(new ModelPendingFragment());
            break;
        case FAILED:
            showFragment(ModelErrorFragment.newInstance(model.getReason()));
            break;
        case READY:
            showFragment(TestingFragment.build(gaitAuthService.isTesting()));
            break;
        default:
            // treat it as a failure
            showFragment(ModelErrorFragment.newInstance("unknown model status"));
            break;
    }
}

First the method route looks for the id of the current GaitModel and asynchronously loads it with the help of loadModel. After the model is loaded, renderFragmentBasedOnModelStatus is called. A simple switch statement then sends the user to the screen matching the current state of the model.

The method route will not find a model id on a user’s first time through the app or if the reset button was pressed. In these cases the user is immediately sent to the SelectModelFragment. From here, when the user clicks on the “Create Model” button, onCreateModelPressed is executed. It builds a new GaitModel, saves the model id in the shared preferences, and sends the user to the FeatureCollectionFragment. Alternatively, the user can opt to load a pre-existing model which leverages the same loadModel method.

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/MainActivity.java#L315
public void onCreateModelPressed() {
    AsyncTask.execute(() -> {
        model = GaitAuth.getInstance().createModel();
        Preferences.put(Preferences.MODEL_ID, model.getId());
        showFragment(new FeatureCollectionFragment());
    });
}

Feature Collection

So we have a GaitModel locked and loaded, but now what? The model is useless without training data so let’s start there. A GaitModel is trained on a collection of GaitFeatures which are data points collected from the user’s movement. These GaitFeatures are given to the model via the add method which has the signature void GaitModel.add(Collection<GaitFeature> features). Later during training, only the features explicitly added to the model will be used.

Now that we know how to use the features, how do we actually collect them? This is achieved by registering a FeatureEventListener that will fire the onNewFeature callback for every feature collected. Correctly managing feature collection requires tackling two key issues: feature storage and backgrounding.

Storing Features

In a naive implementation of feature collection, every time a new feature was received it would be immediately added to the GaitModel. There are two problems with this. First, adding features to the GaitModel may use network resources or trigger other expensive operations and thus is inefficient to call frequently. Second, if the model fails when training you will need to recollect all new data for the new model since you didn’t persist it anywhere.

The sample app solves the feature storage problem with a thread-safe FeatureStore class. This class exposes a method with the signature void add(GaitFeature feature), which serializes the feature and appends it to a file on disk. At a future time (when the user clicks the “Add Feature” button) all of the features can be loaded from disk, deserialized and returned via the method getAll with the signature List<List<GaitFeature>> getAll(). Note that it returns the features partitioned into multiple lists. This is because adding thousands of features to a model at once should be avoided. Finally, there is an empty method to clear the file after adding features. This prevents adding features twice. Deleting the features after using them reintroduces the persistence problem though. The sample app does it anyways to avoid re-adding features to the model in a simple manner.

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/GaitAuthService.java#L163
public void onNewFeature(GaitFeature feature) {
    featureStore.add(feature);
    int count = Preferences.getInt(Preferences.FEATURE_COLLECTED_COUNT) + 1;
    Preferences.put(Preferences.FEATURE_COLLECTED_COUNT, count);
}

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/MainActivity.java#L363
public int onAddFeaturesPressed() {
    FeatureStore featureStore = FeatureStore.getInstance(this);
    List<List<GaitFeature>> chunks = featureStore.getAll();
    int uploadedCounter = 0;

    for (List<GaitFeature> chunk: chunks) {
        model.add(chunk);
        uploadedCounter += chunk.size();
    }
    if (uploadedCounter > 0) { // only truncate file after we uploaded something
        featureStore.empty();
    }
    return uploadedCounter;
}

In a production application there are many improvements you would want to make to FeatureStore. First and foremost, it should implement some form of in-memory buffering. Writing to disk for every feature you collect is slow and can lead to poor battery-life. Second, it should rotate files to avoid size limitations and corruption. Third, it should not clear the file after adding the features to the model. Rather, it should keep track of what features have been added and only add the new ones.

Backgrounding

The second key issue to solve for feature collection is backgrounding. It would not be wise to register the FeatureEventListener on the app’s main thread. As soon as the user closed the app, GaitFeatures would no longer be collected. Android services can help us solve this problem. Services provide a way to execute a long-running operation in the background. There are two relevant types of Android services: background and foreground. A background service needn’t provide any indication to the user that it is running, but is more likely to be shut down by the OS if resources are scarce. A foreground service must present a notification to the user indicating its presence the entire time it is alive. But, it is unlikely to be killed by the OS.

The sample app takes the most straightforward approach. In the onCreate method of the MainActivity a foreground service is created regardless of whether or not the service will be used. This avoids complex state management and synchronization issues that arise when dynamically building a service. In the onCreate method the activity binds to the service. And in the onStop method it unbinds from the service. This gives the activity direct access to the feature collection service.

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/MainActivity.java#L104
protected void onStop() {
    super.onStop();
    if (gaitAuthServiceBound.get()) {
        unbindService(gaitAuthServiceConnection);
        gaitAuthServiceBound.set(false);
    }
}

You may want to handle services differently in a production app. For example, you may only want to start the service when you are actually collecting features. If you go this route make sure to take special care in synchronizing the usage of the GaitAuth SDK.

Final Considerations

That was a lot of details. Let’s take a step back for a moment and consider the entire training process. Feature collection for training is the most critical stage for the GaitAuth SDK. To get good authentication results you need to have a well trained model. The Developer Portal documentation has a number of suggestions on how to best do this.

Training the Model

The hard work of feature collection was well worth the effort. We now have a plethora of GaitFeatures to train with. We’re nearly ready to use our GaitModel, but first we need to train it. Thankfully, training is easy. When a user clicks on the “Train Model” button the method below is called. In a background thread it kicks off the training process for the model and sends the user to the ModelPendingFragment.

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/MainActivity.java#L397
public void onTrainModelPressed() {
    AsyncTask.execute(() -> {
        try {
            model.train();
            showFragment(new ModelPendingFragment());
        } catch (GaitModelException e) {
            showToast("Failed to start training model.");
        }
    });
}

At the pending model screen a user can manually refresh the status of a model while they wait for it to train.

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/MainActivity.java#L436
public void onRefreshPressed() {
    AsyncTask.execute(() -> {
        try {
            model.refresh();
            renderFragmentBasedOnModelStatus(model.getStatus());
        } catch (GaitModelException e) {
            showToast("Failed to refresh model status.");
        }
    });
}

After refreshing the status of the model, our old friend renderFragmentBasedOnModelStatus is called to bring the user to the right screen given the model’s status. If the training failed for some reason the ModelErrorFragment will load. From there the user has no choice other than to reset and start over. After a successful training, the user will be presented with the TestingFragment. And of course, if the model status is still TRAINING after a refresh then no navigation will occur.

Testing the Model

The hard work is over now — we’ve trained a GaitModel and can now reap the benefits. All of the testing functionality is managed by the Authenticator interface. When you instantiate an Authenticator you pass it a GaitModel and a scoring policy. Once created, it automatically starts collecting features. You can ask it for an authentication decision at any time and it will say if the user is authenticated or unauthenticated. In the scenario where this is not enough data to make a decision it will return inconclusive. When the user presses the “Start Collection” button onStartCollectionBtnPressed is called. It in turn tells the foreground service to create a new Authenticator object.

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/MainActivity.java#L338
public void onStartCollectionBtnPressed() {
    try {
        gaitAuthService.startFeatureCollectionForTesting(model);
    } catch (GaitAuthException e) {
        showToast("Failed to start feature collection for testing.");
    }
}

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/GaitAuthService.java#L213
public void startFeatureCollectionForTesting(GaitModel model) throws GaitAuthException {
    GaitQuantileConfig config = new GaitQuantileConfig(QUANTILE_THRESHOLD);
    authenticator = GaitAuth.getInstance().createAuthenticator(config, model);
}

A quick aside on the GaitQuantileConfig policy and how it works. In short it will authenticate the user if at least X percent of scores in the session scored Y or more (learn more about scores here). X is known as the quantile and Y is the score threshold. GaitQuantileConfig sets the quantile to 50% by default and in the sample app the score threshold is set to 0.8. The table below shows three example sessions with these numbers. The first session has 60% of scores at or above the 0.8 score threshold, and therefore has an authenticated result. However, the second and third sessions only have 40% and 20% of scores that meet the 0.8 score threshold, and therefore they produce an unauthenticated result.

You can customize more than just the quantile and score threshold of the GaitQuantileConfig. The method setMinNumScores lets you configure how many scores are required for an authentication decision to be made. Any attempt to authenticate with a number of scores less than this minimum will return inconclusive. Similarly, setMaxNumScores configures the maximum amount of scores that will be considered. If there are more scores than the maximum, the most recent scores will be chosen. Finally, setMaxScoreAge determines how old of scores can be used. Scores older than the given age will not be used for an authentication decision.

Back to the action. The sample app requires the user to stop collecting features before they can score them. Note that this is not a requirement of the GaitAuth SDK and is only done to simplify state management. The Authenticator has a stop method which helps us do this. Clicking the “Stop Collection” button kicks off this sequence of events.

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/MainActivity.java#L349
public void onStopCollectionBtnPressed() {
    gaitAuthService.stopFeatureCollectionForTesting();
}

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/GaitAuthService.java#L223
public void stopFeatureCollectionForTesting() {
    if (authenticator != null) {
        authenticator.stop();
    }
}

Now the user can press the “Score Features” button. This entails getting the authenticator from the foreground service and then getting an authentication status from the authenticator. Then it sends the user to the ScoreFragment. The authenticator also returns the individual scores that lead to the authentication decision. ScoreFragment puts these in a graph to help visualize the decision. How you use the authenticator will be highly dependent on the specifics of your use case.

// https://github.com/UnifyID/gaitauth-sample-app-android/blob/470932205438dd2ce43dc6bad586df90c72cc800/app/src/main/java/id/unify/gaitauth_sample_app/MainActivity.java#L469
public void onScoreFeaturesPressed() {
    Authenticator authenticator = gaitAuthService.getAuthenticator();
    
    authenticator.getStatus(new AuthenticationListener() {
        @Override
        public void onComplete(AuthenticationResult authenticationResult) {
            showFragment(scoreFragment);
        }

        @Override
        public void onFailure(GaitAuthException e) {
            showToast("Failed to get scores.");
        }
    });
}

Conclusion

And just like that we’ve integrated GaitAuth into a simple Android application. For more implementation details you can explore the code in depth on GitHub. If you build something with GaitAuth, let us know on social media. We’d love to hear about it. Finally, reach out to us if you have any trouble integrating.

Integrating Trusted Registration for PushAuth™

Welcome to the final post of the Power of PushAuth™ blog series. In this post, we will enhance the basic website we created in the Building a Web Application with PushAuth™ post by integrating trusted registration to provide a way for the mobile SDK to only register authorized users.

For a detailed explanation on trusted registration, please refer to the following:

In this tutorial, we will integrate trusted registration into a web application so that a user, upon signup, is given a 4 digit “pairing code” they can enter in the mobile app. After this, the mobile client added will be the only one who is able to receive login request push notifications.

The end result of this blog post will be almost identical to the publicly available sample web application used in the previous blog post that introduced trusted registration.

Setup

To follow this tutorial, you will need:

This tutorial assumes a basic familiarity with the Rails framework. Also, the starting point of this guide is the Rails app we built in the Building a Web Application with PushAuth™ post. If you have not followed this previous post to build the web application from scratch, you can clone the pushauth-sample-server in our GitHub repository as the starting point. If you choose to use the GitHub project as a starting point, make sure to initialize the project by following the steps in README of the project.

Step 1 – Provide a pairing code for users

Database Setup

First, we need to add new data to the User table in the database to keep track of an integer pairing code and a boolean which tracks whether or not the code has been used.

Let’s generate a migration to add these columns:

$ rails generate migration add_verification_code_to_users verification_code:integer

The newly generated migration should look like this:

# db/migrate/{some_date}_add_verification_code_to_users.rb

class AddVerificationCodeToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :verification_code, :integer
  end
end

We also want to add a column to keep track of whether each pairing code has been used. This column should default to false so that we don’t have to set it when we create a user. Add this line under the other add_column line from the migration file:

add_column :users, :verification_used, :boolean, default: false

Run bundle exec rails db:migrate, and we should have the appropriate database setup.

User Model

Let’s add some business logic to our User model so that we can ensure the consistency of our table.

We want to add validation to the username such that it must be unique, and we want to add a before_create hook that generates a random verification code for a new User. While we’re at it, we may as well make a function that tries to use up a validation code, and returns whether or not it was a success.

# app/models/user.rb

class User < ApplicationRecord
  has_secure_password

 validates :username, presence: true, uniqueness: { case_sensitive: false }

 before_create :generate_verification_code

 def consume_verification_code(provided_code)
   if provided_code == self.verification_code && !self.verification_used
     self.update_attributes(verification_used: true)
   end
 end

 private

 def generate_verification_code
   self.verification_code = SecureRandom.rand(1000...9999)
 end
end

A quick note about consume_verification_code: in absence of any statements following the if, Ruby will return a boolean corresponding to the evaluated condition, so this will return true if and only if the code was correct and had not been used before.

Users Controller and View

Now, let’s make a UsersController so that we can implement user registration:

$ rails generate controller Users

In UsersController, we will add three actions

  • new : a signup form
  • create : the endpoint to which the signup data is sent
  • post_signup : the page displaying the verification code to the user
# app/controllers/users_controller.rb

class UsersController < ApplicationController
  skip_before_action :authorized

  def new
    @user = User.new
  end

  def create
    @user = User.new(params.require(:user).permit(:username, :password))

    if @user.save
      session[:signup_username] = @user.username
      session[:signup_verification_code] = @user.verification_code
      redirect_to post_signup_users_path
    else
      render :new
    end
  end

  def post_signup
    @username = session[:signup_username]
    @pairing_code = session[:signup_verification_code]
  end
end

Now, let’s add some new views.

app/views/users/new.html.erb for the signup page:

# app/views/users/new.html.erb

<%= form_for @user, class: "form-signin" do |f| %>
<% if @user.errors.any? %>
    <div class="error_messages">
      <h2>Form is invalid</h2>
      <ul>
        <% @user.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>
  <%= f.label :username, class: "sr-only" %>
  <%= f.text_field :username, class: "form-control", placeholder: "Username", autofocus: true %>

  <%= f.label :password, class: "sr-only" %>
  <%= f.password_field :password, class: "form-control", placeholder: "Password" %>

  <%= f.submit "Sign up!", {class: ["btn", "btn-lg", "btn-primary", "btn-block"]} %>
<% end %>

app/views/users/post_signup.html.erb displays the pairing code.

# app/views/users/post_signup.html.erb

<p>
Thanks for registering! Please enter the following in our app:
</p>

<pre>
  Username: <%= @username %>
  Pairing code: <%= @pairing_code %>
</pre>

And finally, we add our routes:

# config/routes.rb
# somewhere within the main do...end block

  resource :users, only: [:new, :create] do
    get "post_signup"
  end

We now want to add signup links from a couple different pages:

Replace the Welcome! Please <%= link_to "log in", "login" %>. line in app/views/application/home.html.erb with the following:

Welcome! Please <%= link_to "log in", "login" %> or <%= link_to "sign up", new_users_path %>.

And add this to the bottom of app/views/sessions/new.html.erb:

Don't have an account yet? Sign up <%= link_to "here", new_users_path %>!

At this point, you should be able to test the new signup flow by running bundle exec rails server.

Step 2 – Implement Trusted Registration Webhook Endpoint

When the user enters their name and pairing code in the app, the UnifyID PushAuth™ service will send a POST request to the Rails app for permission to add a device. On the Developer Dashboard, you can set up the endpoint URL. A detailed explanation on how the trusted registration webhook endpoint works can be found in the previous blog post.

We will make an endpoint for user verification at /users/trust, which checks if a given user and a challenge token (i.e., the pairing code for this sample website) match with our database records.

# app/controllers/users_controller.rb
# add these lines right under "class UsersController < ApplicationController"

  skip_before_action :authorized
  skip_before_action :verify_authenticity_token, only: :trust
  http_basic_authenticate_with name: Rails.application.credentials.unifyid[:basic_username],
    password: Rails.application.credentials.unifyid[:basic_password],
    only: :trust
    
  def trust
    @user = User.find_by(username: params[:user])
    if @user && @user.consume_verification_code(params[:challenge].to_i)
      head :ok
    else
      head :unauthorized
    end
  end 

Let’s take a look at these in a bit more detail:

  skip_before_action :verify_authenticity_token, only: :trust

By default, Rails has cross-site request forgery protection for forms, which means that a form that submits data via POST will have an authenticity token that makes it difficult for attackers to manipulate your browser into performing unauthorized requests. You can read more about this before_action here.
For our use case, however, the UnifyID service will not know the proper authenticity token, so we relax that requirement on the trust action.

  http_basic_authenticate_with name: Rails.application.credentials.unifyid[:basic_username],
    password: Rails.application.credentials.unifyid[:basic_password],
    only: :trust

This adds HTTP Basic Authentication to the /user/trust endpoint in order to make sure the request is from the UnifyID PushAuth™ service. Note that you will have to add basic_username and basic_password entries to the Rails application credentials (bundle exec rails credentials:edit).

Finally, we can add our route:

# config/routes.rb

  resource :users, only: [:new, :create] do
    post "trust"

    get "post_signup"
  end

And there you have it! We’ve added user signup, and we have secured mobile client registration to to UnifyID PushAuth™ service. The end result should look like our pushauth-sample-server-reg project in GitHub, which was introduced in the Power of Trusted Registration blog post.

This concludes the Power of PushAuth™ blog series. Thanks for following along, and feel free to reach out to us if you have any questions, comments, or suggestions!

The Power of Trusted Device Registration

Welcome once again to the Power of PushAuth™ blog series! This post builds on the previous posts by providing an extension of our sample project with feature and security enhancements.

The Problem of Unchecked Device Registration

In the “Is push authentication perfect?” section of the first post in the series, we pointed out some shortcomings of relying on push authentication as a means to authenticate users. Recall the following from that section:

“There’s also the issue of trusting a device to be associated with its true user during registration, as well as not allowing attackers to register devices under the true user’s account.”

The first iteration of the open source sample project did not provide a solution to this problem. With that initial, simple implementation of PushAuth, there was virtually no confidence in the devices registered under a given username. If an attacker were able to obtain the SDK key and one or more usernames registered on the server, they could configure the app on their phone and fraudulently accept or reject push notification login attempts. This security hole allows attackers to impersonate true users and access their resources in the website, or to lock a true user out of accessing their own resources. Not great, considering this is supposed to be a method of increasing the security of the authentication flow.

Trusted Device Registration

The extension presented in this post, however, does include trusted device registration! It also provides the added feature of user registration in the website. Remember that the initial project required users to be created in the console. Only users whose username and password were inserted to the database in that manner were able to log in to the website and receive push notifications. Now users register in the website directly. Once a user signs up in the website, they configure the sample app on their phone in order to authorize future login attempts. This is where trusted device registration comes into play.

What’s different for the user?

After dictating what username and password to associate with a new user, the website displays a four-digit pairing code. The user is instructed to enter that pairing code in the sample app with their chosen username. If the values match, then the user will receive push notifications during login attempts and be able to respond accordingly. If the username and pairing code do not match, then registration of that mobile device fails. This means they will not be able to receive push notifications to confirm or deny login attempts. An attacker will not know that unique pairing code, so they are unable to impersonate a user in the app.

How does this work?

The PushAuth sample server now has a verification endpoint, /users/trust, which accepts webhook requests from UnifyID’s PushAuth service. UnifyID’s server makes an HTTP POST request to a configured target URL, which is set in the project’s dashboard. The request body contains the username and the pairing code. The /users/trust endpoint looks up the given username and determines if the provided pairing code matches the server-generated code displayed during that user’s registration. If the request returns 200, then the user is considered verified and the device trusted. However, if the request returns anything else, the user is not considered verified and device registration fails.

The webhook target URL must use the https scheme and requests use the ‘Basic’ HTTP Authentication scheme, which can be used to validate requests. Further, the four-digit alphanumeric code generated by the server is single-use. These details collectively make it harder for an attacker to impersonate users. An attacker does not have access to the pairing code during initial sign up and they also cannot reuse the pairing code, thus ensuring that devices registered with users are trusted to belong to the true user.

Note: The way we chose to implement trusted device registration with a pairing code is by no means the only method of implementing trusted registration via webhook.

What are the limitations?

If you remember from our first post in the series, there will seemingly always be security holes in a login flow. This enhancement is no exception. For one, the pairing code is only displayed during user registration. What if the user accidentally closes out the tab and then has no way to pair their device? Or what if something happens with the device or app on their device and they have no way to reconfigure an app to be tied to their user? There’s also the concern of in-person over-the-shoulder access to the pairing code, where an attacker could see the four digits and enter the code on their phone before the true user is able to do so. However, just like before, there are solutions to those problems as well; they just aren’t included here. The extension we provide is certainly a big security improvement and patches one of the larger holes that existed in the initial sample project.

Developer Changes

Now that we’ve gone over the concept of trusted device registration and the value it adds to the PushAuth sample project, we’ll walk you through the actual changes from a developer’s perspective. The new repositories can be found here:

We have videos on the UnifyID YouTube channel to walk you through the full end-to-end flow of adding PushAuth to a website login flow with trusted registration.

Trusted Registration Webhook

First and foremost, you’ll need to enable trusted registration for your project in the dashboard. Reference the Setting up Trusted Registration section of our documentation to do so.

The server needs to be publicly available for the target URL to be used. If you want to follow along the tutorial without hosting the web server, we suggest using ngrok to expose the sample rails server running locally on your machine to the internet. The steps shown in this post will do that.

$ ngrok http 3000

Session Status                online
Account                       morganfrisby (Plan: Free)
Version                       2.3.35
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://9c6b07ea6861.ngrok.io -> http://localhost:3000
Forwarding                    https://9c6b07ea6861.ngrok.io -> http://localhost:3000

The target URL is the https URL forwarding to your local server, with /users/trust appended. For example:

Once you add the target URL, trusted registration is enabled for your project. The username and password displayed are used in HTTP Basic Authentication. The username value is set to unifyid, and the password is an auto-generated random string. This value can be rotated, should it become compromised.

Now that the trusted registration webhook is set up in the dashboard, you’re ready to move on to setting up the server.

Server Setup

Other than that, server setup more or less follows the instructions from the first tutorial. Since users are now registered on the website, there is no need to create users in the console during server setup. The other change is the addition of basic_username and basic_password to the credentials file, which are the values found in your project dashboard under the Trusted Registration Webhook section, shown above.

The streamlined steps to spin up the server are now:

$ git clone https://github.com/UnifyID/pushauth-sample-server-reg.git
$ cd pushauth-sample-server-reg
$ bundle install
$ yarn install --check-files
$ bundle exec rails db:migrate

$ EDITOR=vim rails credentials:edit
unifyid:
  server_api_key: <your_key_goes_here>
  basic_username: <basic auth username for /users/trust webhook endpoint>
  basic_password: <basic auth password for /users/trust webhook endpoint>

$ bundle exec rails server

Feel free to reference the detailed tutorial in our previous post for more context around those commands, or the technical details blog post to understand how the server was built. Our next post in the series will provide the technical details of the trusted registration extension of the sample server.

You can see the new website screenshots here (notice the pairing code in the third screenshot):

Sample App Setup

Nothing changes from the developer’s perspective for the iOS and Android sample apps; simply clone the updated repositories and follow the same instructions from earlier in the blog series. Those two posts can be found here:

The iOS sample app screens will look like:

The Android sample app screens now look like:

That’s it! Thanks for following along with the Power of PushAuth™ blog series. The next, and final, post will include the technical details of adding trusted registration to the sample project. Until then, feel free to reach out to us with questions or comments at https://unify.id/contact-us/.

Building a Web Application with PushAuth™

Welcome back to the Power of PushAuth™ blog series! This is the fifth post of the Power of PushAuth™ blog series. The first post of the series was a comprehensive guide to push authentication. The subsequent three posts comprised an end-to-end sample implementation of PushAuth™ in a simple user login flow:

  1. Web Server tutorial
  2. iOS Mobile App tutorial
  3. Android Mobile App tutorial

In this post, we will create a sample website from scratch using Rails, and will integrate PushAuth™ APIs into the user login flow. Along the way, we will also provide technical details on how the website interacts with PushAuth™ APIs, which can help readers incorporate PushAuth™ into any existing website. The end result of this tutorial will be similar to the sample web server we deployed in Web Server tutorial.

Setup

To follow this tutorial, you will need:

This tutorial assumes a basic familiarity with the Rails framework.

Step 1: Make basic Rails app with simple session-based authentication

First, we will create website with a simple username/password authentication, without incorporating UnifyID PushAuth™. Step 2 will integrate PushAuth™ into the website we create in Step 1.

Project Initialization

$ rails new push_auth_demo
$ cd push_auth_demo

Let’s add the bcrypt gem to our Gemfile by uncommenting this line in Gemfile:

gem 'bcrypt', '~> 3.1.7'

Now, we will run bundle install to update the Gemfile.lock.

Next, we can add the User model to our database; each User will have a username and a password hash.

$ rails generate model user username:uniq password:digest 
$ rails db:migrate

Now, we can generate the controller for handling sessions.

$ rails generate controller sessions new create destroy

Controller Logic

The basic idea of session-based authentication is pretty simple:

  • When a user logs in, session[:user_id] is set to be the unique index of the corresponding User in the database.
  • When no one is logged in, session[:user_id] should be unset.

We’ll start with writing the Application controller, where we have a couple of simple page actions:

  • GET / (application#home) renders a page that shows links to other pages and actions
  • GET /restricted (application#restricted) renders a page that is only accessible when logged in.

A few helper functions will live here as well:

  • current_user should either return a User object, or nil if there’s no one logged in.
  • logged_in? should return whether someone is logged in
  • authorized is an action that is called before loading pages that require the a user to be logged in.
# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  before_action :authorized
  helper_method :current_user
  helper_method :logged_in?

  skip_before_action :authorized, only: [:home]

  def current_user
    User.find_by(id: session[:user_id])
  end

  def logged_in?
    !current_user.nil?
  end

  def authorized
    unless logged_in?
      redirect_to login_path, alert: "You must be logged in to perform that action."
    end
  end
end

Now, we’ll handle users logging in or out through the Sessions controller.

  • GET /login (sessions#new) action displays a login page unless the user is already logged in
  • POST /login (sessions#create) will authenticate the user and set the session.
  • DELETE /logout (sessions#destroy) action will clear the user’s session cookie.
# app/controllers/sessions_controller.rb

class SessionsController < ApplicationController
  skip_before_action :authorized, except: [:destroy]

  def new
    redirect_to root_path if logged_in?
  end

  def create
    @user = User.find_by("lower(username) = ?", params[:username].downcase)
    if @user && @user.authenticate(params[:password])
      session[:user_id] = @user.id
      redirect_to root_path, notice: "Successfully logged in!"
    else
      redirect_to login_path, alert: "Sorry, that didn't work."
    end
  end

  def destroy
    session[:user_id] = nil
    redirect_to root_path, notice: "Successfully logged out."
  end
end

We also need to add routes for these actions.

# config/routes.rb

Rails.application.routes.draw do
  root "application#home"

  get "restricted", to: "application#restricted"

  get "login", to: "sessions#new"

  post "login", to: "sessions#create"

  delete "logout", to: "sessions#destroy"
end

Views

home page where you can click on the link to log in/out:

<!-- app/views/application/home.html.erb -->

<h1> Welcome! </h1>

<% if logged_in? %>
  Welcome, <%= current_user.username %>. <br />
  <%= link_to "Log out", logout_path, method: :delete %> <br />
  Click <%= link_to "here", restricted_path %> to see a super secret page!
<% else %>
  Please <%= link_to "log in", login_path %>.
<% end %>

restricted page to test access control:

<!-- app/views/application/restricted.html.erb -->

Shhh, this page is a secret!

sessions#new renders simple login form:

<!-- app/views/sessions/new.html.erb -->

<h1>Login</h1>

<%= form_tag "/login", {class: "form-signin"} do %>
  <%= label_tag :username, nil, class: "sr-only" %>
  <%= text_field_tag :username, nil, class: "form-control", placeholder: "Username", required: true, autofocus: true %>

  <%= label_tag :password, nil, class: "sr-only" %>
  <%= password_field_tag :password, nil, class: "form-control", placeholder: "Password", required: true%>

  <%= submit_tag "Log in", {class: ["btn", "btn-lg", "btn-primary", "btn-block"]} %>
<% end %>

Lastly, we’ll modify the default template to include a navigation bar at the top and flash messages for notice and alert from controllers:

<!-- Replace the contents of the <body> tag in app/views/layouts/application.html.erb with the following -->

    <nav class="navbar navbar-dark bg-dark">
      <a class="navbar-brand" href="/">
        <span class="logo d-inline-block align-top"></span>
        UnifyID PushAuth Sample
      </a>
    </nav>
    <% if flash[:notice] %>
      <div class="alert alert-primary alert-dismissible fade show" role="alert">
        <%= flash[:notice] %>
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
          <span aria-hidden="true">×</span>
        </button>
      </div>
    <% end %>
    <% if flash[:alert] %>
      <div class="alert alert-danger alert-dismissible fade show" role="alert">
        <%= flash[:alert] %>
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
          <span aria-hidden="true">×</span>
        </button>
      </div>
    <% end %>

    <main role="main" class="container">
      <div class="main-content">
        <%= yield %>
      </div>
    </main>

Styling

We can add styling to our website by simply adding bootstrap. The views we created above already use class names that are recognized by bootstrap.

First, add bootstrap and some of its dependencies.

$ yarn add bootstrap jquery popper.js

Then, add the following to the end of app/javascript/packs/application.js:

import 'bootstrap'
import 'stylesheets/application.scss'

Next, make a file called app/javascript/stylesheets/application.scss and add this:

@import "~bootstrap/scss/bootstrap";

Optionally, you may add your own custom CSS files as well. See an example in our sample code.

At this point, you should be able to run rails server and navigate to http://localhost:3000 to interact with the basic authentication server! You can create sample users as follows:

$ bundle exec rails console
> User.create(:username => "<your_username>", :password => "<your_password>").save
> exit

Step 2 – Integrate with UnifyID PushAuth™ APIs

Now that we have a website with a simple username/password authentication, let’s incorporate UnifyID PushAuth™ APIs to further enhance security.

Interface to PushAuth™ APIs

First, let’s tell Rails about your UnifyID API key.

Run rails credentials:edit and add the following

unifyid:
  server_api_key: <Your UnifyID API Key created from dashboard>

Next, add the following to config/application.rb, after the config.load_defaults line:

config.x.pushauth.base_uri = "https://api.unify.id"

Let’s also add the httparty gem to easily make HTTP/S requests. To do this, add the following to your Gemfile and run bundle install:

gem 'httparty', '~> 0.18.0'

Now, we will make a file called app/services/push_auth.rb which contains the interface for our Rails app to interact with the PushAuth™ APIs:

  • create_session method calls POST /v1/push/sessions to initiate PushAuth™ session (API doc).
  • get_session_status method calls GET /v1/push/sessions/{id} to retrieve the status of PushAuth™ session (API doc).
# app/services/push_auth.rb

class PushAuth
  include HTTParty
  base_uri Rails.configuration.x.pushauth.base_uri

  @@options = {
    headers: {
      "Content-Type": "application/json",
      "X-API-Key": Rails.application.credentials.unifyid[:server_api_key]
    }
  }

  def self.create_session(user_id, notification_title, notification_body)
    body = {
      "user" => user_id,
      "notification" => {
        "title" => notification_title,
        "body" => notification_body
      }
    }
    post("/v1/push/sessions", @@options.merge({body: body.to_json}))
  end

  def self.get_session_status(api_id)
    get("/v1/push/sessions/#{api_id}", @@options)
  end
end

Controller Logic Modification

Now, we will modify the login flow to incorporate PushAuth™ as the second factor authentication. The new login flow will consist of the following:

  1. The client submits the username and password via a POST request to /login (sessions#create)
  2. The controller validates that the user exists and the password matches. If not, it displays an error message.
  3. Upon successful username/password authentication, the controller creates a PushAuth™ session and redirects to GET /mfa (sessions#init_mfa)
  4. The Javascript in /mfa page repeatedly queries GET /mfa/check (sessions#check_mfa), which checks the PushAuth™ session status until the session status is no longer pending.
  5. Upon receiving a non-pending session status, the client submits a request to PATCH /mfa/finalize (sessions#finalize_mfa) that completes the login process.

First, let’s replace the create action in app/controllers/sessions_controller.rb:

  def create
    @user = User.find_by("lower(username) = ?", params[:username].downcase)
    if @user && @user.authenticate(params[:password])
      session[:pre_mfa_user_id] = @user.id

      pushauth_title = "Authenticate with #{Rails.application.class.module_parent.to_s}?"
      pushauth_body = "Login request from #{request.remote_ip}"

      response = PushAuth.create_session(@user.username, pushauth_title, pushauth_body)

      session[:pushauth_id] = response["id"]

      redirect_to mfa_path
    else
      redirect_to login_path, alert: "Sorry, that didn't work."
    end
  end

Next, let’s also add check_mfa and finalize_mfa actions in this controller:

  def check_mfa
    status = PushAuth.get_session_status(session[:pushauth_id])["status"]

    render plain: status
  end

  def finalize_mfa
    case PushAuth.get_session_status(session[:pushauth_id])["status"]
    when "accepted"
      session[:user_id] = session[:pre_mfa_user_id]
      session[:pushauth_id] = nil
      session[:pre_mfa_user_id] = nil
      flash.notice = "Successfully logged in!"
    when "rejected"
      session[:pre_mfa_user_id] = nil
      flash.alert = "Your request was denied."
    end
  end

We also want to make sure that only users who completed the password authentication are able to access actions for the PushAuth™ authentication. Thus, within sessions_controller we will add:

# app/controllers/sessions_controller.rb

# Add this just under the skip_before_action line
  before_action :semi_authorized!, only: [:init_mfa, :check_mfa, :finalize_mfa]

# And add this after action methods
  private
  def semi_authorized
    session[:pre_mfa_user_id] && session[:pushauth_id]
  end

  def unauthorized
    redirect_to login_path, alert: "You are not authorized to view this page."
  end

  def semi_authorized!
    unauthorized unless semi_authorized
  end

Views

Now, we need a page that uses AJAX to determine whether the PushAuth™ request has been completed.

First, let’s add a line in our application template that allows us to add content inside the <head> tag.
Add this to app/views/layouts/application.html.erb, right before the </head> tag:

<%= yield :head %>

Next, let’s add the Javascript code we want to run on the init_mfa page:

// app/javascript/packs/init_mfa.js

import Rails from "@rails/ujs";
let check_status = window.setInterval(function() {
  Rails.ajax({
    type: "GET",
    url: "/mfa/check",
    success: function(r) {
      if (r !== "sent") {
        Rails.ajax({
          type: "PATCH",
          url: "/mfa/finalize",
          success: function() {
            window.clearInterval(check_status);
            window.location.href = "/";
          },
          error: function() {
            console.log("Promoting PushAuth status failed.");
          }
        });
      }
    },
    error: function() {
      console.log("Checking for PushAuth status failed.");
    }
  });
}, 2000);

This will poll /mfa/check every 2 seconds, until the Rails app reports that the PushAuth™ request has been accepted, rejected, or expired. At this point, the browser will ask the Rails app to complete the login process by submitting a /mfa/finalize request.

Now, let’s add a view file for init_mfa that includes the Javascript above.

<!-- app/views/sessions/init_mfa.html.erb -->

<% content_for :head do %>
  <%= javascript_pack_tag 'init_mfa' %>
<% end %>

<div class="spinner-border" role="status" ></div>

Waiting for a response to the push notification...

Finally, we will add new mfa routes.

# Add these to config/routes.rb

  get "mfa", to: "sessions#init_mfa"

  get "mfa/check", to: "sessions#check_mfa"

  patch "mfa/finalize", to: "sessions#finalize_mfa"

Congratulations! We have now integrated UnifyID’s PushAuth™. The final result should function just like the pushauth-sample-server project, which we introduced in our How to Implement PushAuth™: Web Server post. Please reach out to us if you have any questions, comments or suggestions, and feel free to share this post.

How to Implement PushAuth™: Android Mobile App

This post is part of the Power of PushAuth™ blog series. The first post of the series was a comprehensive guide to push authentication. The next three posts of the series comprise an end-to-end sample implementation of PushAuth in a simple user login flow. The tutorial breakdown is as follows:

  1. Web Server tutorial
  2. iOS Mobile App tutorial
  3. Android Mobile App tutorial (this post)

The tutorial in this post builds on the web server from the first tutorial. With your web server set up and running, you now need a mobile app to receive and respond to notifications. This post will help you build the Android mobile app to do so; then you will be able to leverage the power of PushAuth for login requests!

Setup

To follow this tutorial, you will need:

  • An Android device running Android 7.0 or higher
  • A computer with Android Studio 4.0 installed
  • JDK 8 installed (we recommend using jabba)

Step 1 : Cloning the Project

The sample Android mobile app code for this project is provided in the pushauth-sample-app-android GitHub repository. Clone this repo to your local machine:

$ git clone https://github.com/UnifyID/pushauth-sample-app-android.git

Open Android Studio, select “Open an existing Android Studio project”, and select the directory of the cloned repository. It should look something like this:

Step 2: Set up Firebase Cloud Messaging (FCM)

Firebase Cloud Messaging (FCM) is the platform used to send notifications to Android devices. You will first need to set up Firebase in your app by following the instructions at https://firebase.google.com/docs/android/setup. After doing this, ensure that a google-services.json file is present under the app/ directory of the project in Android Studio.

Next, navigate to the Firebase project settings of your app in your browser and select the “Cloud Messaging” tab. The token labeled “Server key” is what you will need to provide to UnifyID in the next section, so copy that value.

Step 3: Providing Push Credentials to UnifyID

Now you have the Firebase Cloud Messaging (FCM) server key copied, you will provide it to UnifyID so that PushAuth can send push notifications to the sample app on your phone. You’ll provide this value in your project’s dashboard. Follow the instructions in the Developer Portal docs to do so. After you’ve done this, your project dashboard will indicate they are successfully uploaded:

Step 4: Building the Project

Now, back to Android Studio. Make sure that your Android device is plugged in to your computer, has developer tools and USB debugging enabled, and is available in the top center of Android Studio. Also make sure that the google-services.json file is located under the app/ directory of the project.

With everything set up, click the green triangle or press Control+R to run the app. The following screen should appear on your device:

Step 5: Mobile App Settings

You now have all the values necessary for configuration! Tap the gear icon in the top right corner of the sample app’s Configuration screen. For SDK key, enter your UnifyID project’s SDK key value from the Dashboard. The User string should be the same value that you used when creating a user in the web server tutorial, e.g. “Morgan”. If these values do not match, you will not be able to successfully respond to push notifications in the login flow.

After setting those values and clicking “Confirm”, the app is ready to receive your PushAuth login requests! The app will remain on the “Waiting for PushAuth requests” page until it receives a PushAuth authentication request.

Now you can go through the full login flow by entering your username and password on the login page, respond to the notification received by this app on your phone, and be successfully logged into the website.

That’s it! Now you have a simple login flow that integrates PushAuth. Stay tuned for the rest of the posts in the series, make sure to share this post and reach out to us if you have any questions, comments or suggestions!

Announcing GaitAuth™

Are Humans The “Weak Link?”

Security professionals often lament the “human element.” It is only due to human fallibility that our systems are not secure. We are not good at coming up with or keeping track of passwords. We don’t follow security guidelines. We are easily fooled by phishing or social engineering. We often act in ways that leave systems vulnerable.

It is time to flip this attitude around. Yes, humans are not machines. We are wonderfully flawed. And each of us is profoundly unique; a combination of nature and nurture, a product of our experience and circumstance, all woven together with the human spirit to form the tapestry of who we are. All of these little imperfections are not “bugs” to be fixed, but form the core of our humanity.

GaitAuth: One Small Step for Man, One Giant Leap for Authentication

Today, we are releasing a new API called GaitAuth™. It can authenticate a person based on the motion associated with their gait – the way they walk – completely passively and at a high level of accuracy. It is able to return an authentication result after only a few steps of carrying your phone. This allows you to authenticate a user using one of the most natural human actions: walking.

You may wonder how unique someone’s gait truly is. Your gait is a product of your unique physiology and years of muscle memory. And unlike static biometrics like fingerprint or facial recognition, it is dynamic and constantly changing, and it is hard for others to spoof and steal. We’ve tested our models using anonymized data from millions of mobile phones and found the accuracy of gait-based authentication can rival other biometrics like fingerprint, iris, or face. Gait also has the benefit that it continues to work even if the user is wearing a face mask or gloves.

GaitAuth is the culmination of almost four years of research and development from the UnifyID team to bring a solution that is highly accurate, efficient, robust, and secure. I’m proud of what they have been able to accomplish and the results are truly amazing.

GaitAuth Use Cases

Because GaitAuth can run passively in the background, it is useful in a wide variety of situations:

  • GaitAuth is an ideal solution where passive or continuous authentication is desired. With GaitAuth, you can detect if a device changes possession within a handful of steps and deauthenticate the user. The user also does not need to be walking to authenticate. Because GaitAuth runs passively in the background, you can also use historical information about the last time they were walking and whether the phone has left their possession since that time.
  • GaitAuth helps provide seamless access control for doors and smart locks. By using GaitAuth, a user can walk up to a door with their phone and have the door unlock automatically. If someone steals their phone, their gait signature will not match and they cannot unlock the door. In fact, GaitAuth is the only multifactor authentication technique that requires no user interaction or training – it combines something you have (your phone) with something you are (your unique gait) without requiring the user to do anything extra.
  • GaitAuth is also useful for vehicles and travel. With GaitAuth integrated into your car’s mobile app, you won’t need to carry keys to your car anymore. You can walk up to your car with your phone and the door will unlock, and even if someone grabs your phone, they won’t be able to get into your car. It is also useful for seamless authentication for the entire travel journey, from the moment you leave your door, to airport security, to boarding, to rental cars, to hotels, to dining and activities, all of which have friction due to authentication. Using GaitAuth allows many of these interactions to become much more seamless.
  • GaitAuth is a great fit for situations where workers have access to sensitive data, but are on the move and need to authenticate often, such as medical workers, airport personnel, or flight attendants. This is especially true if workers may be wearing masks or gloves, as face or fingerprint recognition may be impractical.
  • GaitAuth is also useful for cross-device authentication like automatically unlocking your computer when you approach your desk or touchless access to ATMs, kiosks, or point terminals. You can leverage the passive GaitAuth biometric signal from the phone to authenticate to other devices, without having to take out your phone.

GaitAuth is now available for both iOS and Android as a modular SDK you can link into any mobile application. It is lightweight (<2 MB), low-power, and uses only minimal network as the motion data is processed directly on the phone.

GaitAuth is the first of our public APIs we are releasing with the goal of continuous, implicit authentication, with more to come. Rather than view humans as the weak link in security, we want to use what makes us unique as humans to strengthen security. Our GaitAuth API is our first “step” towards our goal of making our experiences with security and authentication more seamless, more usable, and ultimately, more human.

How to Implement PushAuth™: iOS Mobile App

This post is part of the Power of PushAuth™ blog series. The first post of the series was a comprehensive guide to push authentication. The next three posts of the series comprise an end-to-end sample implementation of PushAuth in a simple user login flow. The tutorial breakdown is as follows:

  1. Web Server tutorial
  2. iOS Mobile App tutorial (this post)
  3. Android Mobile App tutorial

The tutorial in this post builds on the web server from the first tutorial. With your web server set up and running, you now need a mobile app to receive and respond to push notifications. This post will help you build the iOS mobile app to do so; then you will be able to leverage the power of PushAuth for login requests!

Setup

To follow this tutorial, you will need:

Step 1: Cloning the Project

The pushauth-sample-app-ios GitHub repository contains the sample iOS mobile app code for this project. Clone the repository to your local machine and open the PushAuthSample.xcworkspace file in Xcode.

$ git clone https://github.com/UnifyID/pushauth-sample-app-ios.git

Step 2: Setting Up and Running the Project

  1. In the top left section of your Xcode window, set the active scheme to PushAuthSample.
  2. Plug your phone into your computer. Your phone’s name will appear as the chosen device next to the active scheme.
  3. Navigate to the “Signing & Capabilities” section of the Xcode project settings.
  4. Check the boxes next to “Automatically manage signing” in the “Signing (Debug)” and “Signing (Release)” sections. This will simplify setup and merge the two into a single “Signing” section.
  5. Choose the “Team” value to match your Apple Developer account.
  6. Set the “Bundle Identifier” to something unique; this value will be used in the next step of the tutorial when you create the Identifier through the Apple Developer site.

After following these six steps, your settings should closely resemble the screenshot above from Xcode. Once everything is set up properly and with your phone still connected to your computer, run the project (Product > Run or Command-R). This screen will show up on your phone:

Step 3: Create an Apple Bundle Identifier

This step requires you to an Apple Developer Program Role with adequate permissions. The role-permissions are listed here.

Navigate to the Identifiers tab on the Certificates, Identifiers & Profiles page of the Apple Developer site. You’ll need to add a new identifier that matches the Bundle Identifier value you set in Xcode in step 6 above. Click the plus symbol next to the title at the top of the page; if you don’t see this symbol, you likely don’t have adequate permissions. Follow these instructions for the subsequent pages:

  1. Register a new identifier page: Keep the default selection (App IDs) and click “Continue”.
  2. Select a type page: Keep the default selection (App) and click “Continue”.
  3. Register an App ID page:
    • Description: enter an appropriate description for this project, e.g. “PushAuth Project”. This value will be displayed as the “Name” on the Identifiers page.
    • Bundle ID: Keep the selection on “Explicit” and enter the exact same value you put as the Bundle Identifier in the Xcode Signing & Capabilities page earlier.
    • Enable Push Notification capability by scrolling down on the page and selecting the checkbox next to “Push Notifications”.
    • Click “Continue”, verify everything was entered correctly, and click “Register”.

Now that you have created an identifier for this project, you can create a push notification certificate associated with this identifier.

Step 4: Create a Push Notification Certificate

UnifyID requires the APNs certificate in *.p12 format to send PushAuth requests to the app. This can be done from the same Identifiers page of the Apple Developer site that you were on in Step 3.

  1. Click on the name of the identifier you just created, e.g. “PushAuth Project”.
  2. Scroll down to the “Push Notifications” row and click on the “Configure” box. Next to this box you should see “Certificates (0)” since you haven’t yet created a certificate associated with this identifier.
  1. In the Apple Push Notification service SSL Certificates pop-up window, click on the “Create Certificate” box under “Production SSL Certificate” then click “Done”.
  1. At this point, you need to create a Certificate Signing Request (CSR) file from your Mac. Click “Learn More” and follow those instructions for doing so. Then upload that file and continue.
  1. Now that you have created a certificate, you must download it locally to export it to *.p12. Click “Download”.
  1. This will prompt you to add the certificate to Keychain Access. Choose a Keychain, e.g. “login”, to add the certificate to and click “Add”.
  1. Then find that certificate in Keychain Access. It may be useful to select the “Certificates” category and utilize the search bar to find the certificate you just added.
  1. Once you have located your certificate, right-click on it and click the option to export the certificate:
  1. Specify a name for the *.p12 file and a location to save it. Make sure the file format is set to “Personal Information Exchange (.p12)” then click “Save”.
  1. You will be prompted to password-protect the exported *.p12 file. Choose to export it without a password; simply click “OK”.

Now you have successfully created a APNs certificate in *.p12 format! This will be used by UnifyID and needs to be uploaded to your project settings through the dashboard.

Step 5: Providing Push Credentials to UnifyID

Now you have an Apple Bundle Identifier and an APNs push certificate. It’s time to provide your push credentials to UnifyID so that PushAuth can send push notifications to the sample app on your phone. Check out the Developer Portal docs here, or follow along the instructions below.

  1. Navigate to the “Push Credentials” section of your project on the Developer Dashboard.
  2. Click on “Choose File” and select the *.p12 file you generated in Step 4 of this tutorial.
  3. Choose the “Development/Sandbox APNs server” option for now since we are sending push notifications to an app that runs directly from Xcode. Later on, choose “Production APNs server” when you need to send PushAuth requests to apps distributed through the App Store or through ad-hoc means.
  4. Click “Add” to complete the upload.

Once the push credentials are successfully uploaded to your project settings, you will see the push credential information displayed:

If you find yourself needing to change the push credentials used for the project, simply click “Edit” and go through the same upload steps with the new credentials.

Step 6: Mobile App Settings

You now have all the values necessary for configuration! Open the sample app on your phone and tap the gear icon in the top right of the Configuration screen. For SDK key, enter your UnifyID project’s SDK key value from the Dashboard. The User string should be the same value that you used when creating a user in the web server tutorial, e.g. “Morgan”. If these values do not match, you will not be able to successfully respond to push notifications in the login flow.

Once you set those two values, you must allow push notifications for the app, then the app is ready to receive your PushAuth login requests!

Now you can go through the full login flow by entering your username and password on the login page, respond to the push notification received by this app on your phone, and be successfully logged in to the website.

That’s it! You now have a simple login flow that integrates PushAuth. The next post provides a tutorial for building the Android sample PushAuth mobile app. Stay tuned for the rests of the posts in the series and, as always, please share this post and reach out to us with questions, comments or suggestions.

How to Implement PushAuth™: Web Server

Welcome back to the Power of PushAuth™ blog series! The first post provided a comprehensive guide to push authentication — check it out here if you missed it. The next three posts are tutorials offering an end-to-end implementation of PushAuth™ in a simple user login flow and will be broken down as follows:

  1. Web Server tutorial (this post)
  2. iOS Mobile App tutorial
  3. Android Mobile App tutorial

The first tutorial (this post) covers a Ruby on Rails backend that provides a basic user login authentication flow with PushAuth integrated. The second and third tutorials will be instructions on how to run sample iOS and Android apps, respectively. These will be the apps that receive and respond to push notifications initiated by the login process.

By the end of these three tutorials, you will have a website where a registered user can log in with their username and password, receive a push notification on their phone, accept the login request via the push notification, and subsequently be logged in on the website. This flow is shown in the video below.

This is a very simplified version of a real-world application and login flow. You might remember some of the security issues that can be present with push authentication from the previous post, such as trusted device registration, fallback resources, or access revocation. This tutorial does not include solutions for those or user sign-up. Future posts in the series will provide extensions of this simple flow to tackle some of those issues.

Alright, let’s get started!

Setup

To follow this tutorial, you will need:

Step 1: UnifyID Account, Project, and Keys

A UnifyID project will grant you access to UnifyID’s services. In order to create a project, you’ll need to first create a UnifyID account. Once you have an account and project, go to the Developer Dashboard to create an API key and SDK key. Make sure to copy the API key value somewhere safe – you won’t be able to access it later.

This tutorial is using PushAuth project as the UnifyID project name. You can see the configured API and SDK keys on the dashboard view above.

Step 2: Cloning the Project and Installing Dependencies

The pushauth-sample-server GitHub repository contains the code for this project. Clone the repository, navigate into it, install the project dependencies that are listed in the Gemfile, and ensure your Yarn packages are up-to-date:

$ git clone https://github.com/UnifyID/pushauth-sample-server.git
$ cd pushauth-sample-server
$ bundle install
$ yarn install --check-files

Feel free to poke around the code if you’d like to get a better understanding of what’s going on under the hood. This tutorial won’t go into those details, but a future post in this series will.

Step 3: DB Setup and Running the Server

Now, initialize the database:

$ bundle exec rails db:migrate

Once the database has been initialized you can create users. To create a user, do the following (replacing <your_username> and <your_password> with the values you intend to use for username and password):

$ rails console
> User.create(:username => "<your_username>", :password => "<your_password>").save
> exit

Step 4: Server API Key Storage

This step requires the server API key value you copied in Step 1.

$ EDITOR=vim rails credentials:edit

The above command will open the credentials file in vim. You can replace vim with the name of whichever executable you are most comfortable (atom, sublime, etc.). This will decrypt and open the credentials file for editing, at which point you should add the following entry:

unifyid:
  server_api_key: <your_key_goes_here>

After saving and closing, the credentials file will be re-encrypted and your server API key value will be stored.

Step 5: Running the Server

Now you are able to run the server:

$ bundle exec rails server

Finally, connect to the server by opening http://localhost:3000/ in your browser. This will bring you to the landing page, where you can then navigate to the login page and enter your username and password from above in Step 3:

This brings you to the end of the web server tutorial. After entering the username and password on the login page, you can see that the server is polling for the push notification response before allowing or denying access to the website. Without a way to receive or respond to push notifications, you cannot successfully log in. Stay tuned for the next couple posts of this tutorial installment to complete the flow:

Thanks for following along! Please reach out to us if you have any questions, comments or suggestions, and feel free to share this post.

The Power of PushAuth™

Welcome to the first post in our series on PushAuth™, UnifyID’s push authentication service. This series, outlined below, will help you leverage push authentication to increase the security of your authorization flow.

PushAuth™ Blog Series Content

  1. Comprehensive guide to push authentication: what it is, how it works, and pros and cons of using it.
  2. An end-to-end tutorial of implementing PushAuth™ in a simple user login flow.
    1. How to Implement PushAuth™: Web Server tutorial
    2. How to Implement PushAuth™: iOS Mobile App tutorial
    3. How to Implement PushAuth™: Android Mobile App tutorial
  3. Building a Web Application with PushAuth™: Technical deep-dive into the details of building a web application with PushAuth™ integrated.
  4. The Power of Trusted Registration: A more secure extension of the simple user sign-up flow that includes user registration and trusted device registration.
  5. Integrating Trusted Registration for PushAuth™: Technical deep-dive into the details of extending the project with trusted device registration.

Push authentication is one of the most seamless and secure methods of multi-factor authentication. We want to help you understand its importance and the power it has to upgrade your security!

Table Stakes

Let’s clear up two terms that are critical to understanding what PushAuth is solving:

Authorization = allowing you access to a system

Authentication = verifying your identity

There is a great Medium article that describes those differences in more depth. You could have an authorization flow that requires no authentication, letting all users in without proving anything (please don’t do this). On the other hand, you could have an authorization flow that makes users jump through countless hoops to try to make 100% sure the true user is accessing their account. The magic is in striking a balance between these extremes, ensuring a secure authorization process without excessive user annoyance.

One more term to define before moving forward:

Multi-factor authentication = an authentication method that requires two or more pieces of proof before granting a user access to resources

Multi-factor authentication (MFA) is sometimes referred to as two-factor authentication (2FA). Here is a page on MFA basics provided by NIST.

Why use multi-factor authentication?

Before jumping into push authentication, let’s explain MFA. The three basic authentication mechanisms are:

  1. Knowledge: something you know (password, security question answers, PIN)
  2. Possession: something you have (access badge, ATM card, smartphone, hard token)
  3. Biometric: something you are (fingerprint, face, gait, voice)

As defined above, MFA uses two or more of these authentication mechanisms. There are many security benefits to using MFA. The primary benefit is increased confidence in an authorization flow. This stronger assertion on the user’s identity increases the application’s security. Using MFA mitigates the dangers of poor security habits many users have with passwords, such as writing them down, making them simple or easily-guessed, and reusing them across platforms.

Push authentication is one method of accomplishing MFA. This method usually requires a user to download an app on their phone and register it with their account. The mobile app receives push notifications during the login flow. In doing so, the user establishes two authentication mechanisms: knowledge of their username/password combination and possession of their registered device. Here is an example of using push authentication in a login flow:

A user logs in to a web application by entering their username and password. Upon clicking the button to log in, the server sends a push notification to the app (which the user has already downloaded and registered). The user unlocks their phone and authorizes the request by clicking “Accept” on the notification. The server receives this approved response and proceeds to log the user in to the web app. If the user instead clicks “Deny,” the authentication step fails and the user would not gain access to the web app.

Other types of MFA include SMS codes, phone calls, email codes or magic links, authenticator app verification codes, and hardware tokens. This PCMag article does a good job of aggregating different ways well-known companies offer MFA. In the next section we discuss the advantages push authentication has over other methods.

Why choose push authentication?

In a nutshell, push authentication increases security in a cost-effective manner without affecting usability. This section lists some of the aspects specific to push authentication that make it superior to other methods of MFA.

MFA methodFree tierCost per million
SMS100$6,540
Email1,000$20
Mobile Push Notifications1 million$0.50
  • Convenient and easy to use. We can assume that users who have smartphones are comfortable with using apps and interacting with notifications. This makes using push authentication easy for them, since there is nothing else they need to learn to use or get used to the method. Push notifications are much easier to respond to – there is no typing, clicking links, or copying codes while trying to beat the timer. Authentication happens with a simple and speedy tap on their screen.
  • Secure. The push authentication mobile app is installed securely on users’ devices, so there is no reliability on a user’s accounts with external companies. This out-of-band communication can’t be intercepted at the point of password entry, and it is encrypted from end to end between the application and the secured push authentication provider. The many insecurities of the SMS method led to the downfall of its prominence in this space.
  • Fast. Since authentication requests are sent in real time via notifications, a user can become aware of and deny fraudulent requests when they happen and promptly take action. Unlike some methods of MFA, the user must unlock their device before responding to the request. However, this is a level of friction that users are already familiar with on a day-to-day (or, more realistically, minute-to-minute) basis. For devices with TouchID or FaceID, this process is almost frictionless. This even increases the security by preventing unhindered access to authentication by an attacker.
  • No hardware to manage. Unlike with hardware tokens, push authentication utilizes users’ existing phones. Since most people consider their phone an extension of their body, this also means the hardware is unlikely to be easily or frequently misplaced. When phones are lost or broken, the responsibility is on the user, rather than the service provider, to obtain a replacement.
  • No over-the-shoulder copy-ability. Codes and magic links sent via SMS/email and codes generated in an authenticator app can all be intercepted and used to log in as an attacker. Push notifications don’t contain anything that can be copied or reproduced.

Is push authentication perfect?

Unsurprisingly, like most things, no. On a base level, push authentication requires that every user has a fully-functional smartphone. Without a smartphone, they can’t have the mobile app (and the provider needs to have an application). Without internet connection, their device can’t receive push notifications through the mobile app. In the specific cases of a user’s phone being lost, stolen, or otherwise not in their possession, push authentication will fail. Even if the device is in their possession but out of battery, waterlogged, or otherwise not functional, the same assertion applies. For the sake of argument, let’s assume that none of these scenarios are issues. Push authentication is still not “perfect.”

There are some valid security concerns surrounding the use of push authentication as a method for MFA. Smartphones themselves, where the authentication bit happens, are vulnerable to attacks and viruses. There’s also the issue of trusting a device to be associated with its true user during registration, as well as not allowing attackers to register devices under the true user’s account. Even with a trusted device, any pre-registered device is a weak point for attacker entry. You can’t ensure that users have their devices protected via a locking mechanism. If they don’t have access into their phone locked, then it’s pretty easy for an attacker to accept a notification on the user’s behalf. Finally, it’s completely possible that a user accidentally approves a fraudulent request on their device without realizing it, or realizing too late.

However, there are solutions to these problems. In the cases of a temporarily out-of-possession device, you can provide fallback resources (one-time passcodes, email or SMS delivery, security questions, etc.) as a workaround for that authentication attempt. If the device is permanently out of possession, such as a ruined or stolen phone, you can provide a method of revoking access from the old device and allowing users to self-sign up and provision the app on a new mobile device. If an attacker gains physical access to the device before access is revoked, it’s likely that the user will have yet another authentication barrier in the form of a passcode, TouchID, or FaceID. While this can be attacked as well, it still raises the bar for entry before access is revoked. With regards to users accepting fraudulent requests on their device, the push notification prompt could be extended to include a unique identifier that is expected to match a value on the web login page. The existence of this would set the expectation that a user is to confirm the value before accepting the request.

However, there’s only so much you can do as a developer. People will still make mistakes, and hackers will still gain access. The main point here is that these are things you, as a developer, should be aware of and address. All things considered – push authentication sits in a pretty great place security-wise, is incredibly low friction, and (perhaps most importantly) incredibly cost-effective. Keep an eye out for our next post of the series, which will walk you through using our open-source project to implement PushAuth yourself!

Vulnerability of deep learning-based gait biometric recognition to adversarial perturbations

PDF of full paper: Vulnerability of deep learning-based gait biometric recognition to adversarial perturbations
Full-size poster image: Vulnerability of deep learning-based gait biometric recognition to adversarial perturbations

[This paper was presented on July 21, 2017 at The First International Workshop on The Bright and Dark Sides of Computer Vision: Challenges and Opportunities for Privacy and Security (CV-COPS 2017), in conjunction with the 2017 IEEE Conference on Computer Vision and Pattern Recognition.]

Vinay Uday Prabhu and John Whaley, UnifyID, San Francisco, CA 94107

Abstract

In this paper, we would like to draw attention towards the vulnerability of the motion sensor-based gait biometric in deep learning-based implicit authentication solutions, when attacked with adversarial perturbations, obtained via the simple fast-gradient sign method. We also showcase the improvement expected by incorporating these synthetically-generated adversarial samples into the training data.

Introduction

In recent times, password entry-based user-authentication methods have increasingly drawn the ire of the security community [1], especially when it comes to its prevalence in the world of mobile telephony. Researchers [1] recently showcased that creating passwords on mobile devices not only takes significantly more time, but it is also more error prone, frustrating, and, worst of all, the created passwords were inherently weaker. One of the promising solutions that has emerged entails implicit authentication [2] of users based on behavioral patterns that are sensed without the active participation of the user. In this domain of implicit authentication, measurement of gait-cycle [3] signatures, mined using the on-phone Inertial Measurement Unit – MicroElectroMechanical Systems (IMU-MEMS) sensors, such as accelerometers and gyroscopes, has emerged as an extremely promising passive biometric [4, 5, 6]. As stated in [7, 5], gait patterns can not only be collected passively, at a distance, and unobtrusively (unlike iris, face, fingerprint, or palm veins), they are also extremely difficult to replicate due to their dynamic nature.

Inspired by the immense success that Deep Learning (DL) has enjoyed in recent times across disparate domains, such as speech recognition, visual object recognition, and object detection [8], researchers in the field of gait-based implicit authentication are increasingly embracing DL-based machine-learning solutions [4, 5, 6, 9], thus replacing the more traditional hand-crafted-feature- engineering-driven shallow machine-learning approaches [10]. Besides circumventing the oft-contentious process of hand-engineering the features, these DL-based approaches are also more robust to noise [8], which bodes well for the implicit-authentication solutions that will be deployed on mainstream commercial hardware. As evinced in [4, 5], these classifiers have already attained extremely high accuracy (∼96%), when trained under the k-class supervised classification framework (where k pertains to the number of individuals). While these impressive numbers give the impression that gait-based deep implicit authentication is ripe for immediate commercial implementation, we would like to draw the attention of the community towards a crucial shortcoming. In 2014, Szegedy et al. [11] discovered that, quite like shallow machine-learning models, the state-of- the-art deep neural networks were vulnerable to adversarial examples that can be synthetically generated by strategically introducing small perturbations that make the resultant adversarial input example only slightly different from correctly classified examples drawn from the data distribution, but at the same time resulting in a potentially controlled misclassification. To make things worse, a large plethora of models with disparate architectures, trained on different subsets of the training data, have been found to misclassify the same adversarial example, uncovering the presence of fundamental blind spots in our DL frameworks. After this discovery, several works have emerged ([12, 13]), addressing both means of defence against adversarial examples, as well as novel attacks. Recently, the cleverhans software library [13] was released. It provides standardized reference implementations of adversarial example-construction techniques and adversarial training, thereby facilitating rapid development of machine-learning models, robust to adversarial attacks, as well as providing standardized benchmarks of model performance in the adversarial setting explained above. In this paper, we focus on harnessing the simplest of all adversarial attack methods, i.e. the fast gradient sign method (FGSM) to attack the IDNet deep convolutional neural network (DCNN)-based gait classifier introduced in [4]. Our main contributions are as follows: 1: This is, to the best of our knowledge, the first paper that introduces deep adversarial attacks into this non-computer vision setting, specifically, the gait-driven implicit-authentication domain. In doing so, we hope to draw the attention of the community towards this crucial issue in the hope that further publications will incorporate adversarial training as a default part of their training pipelines. 2: One of the enduring images that is widely circulated in adversarial training literature is that of the panda+nematode = gibbon adversarial-attack example on GoogleNet in [14], which was instrumental in vividly showcasing the potency of the blind spot. In this paper, we do the same with accelerometric data to illustrate how a small and seemingly imperceptible perturbation to the original signal can cause the DCNN to make a completely wrong inference with high probability. 3: We empirically characterize the degradation of classification accuracy, when subjected to an FGSM attack, and also highlight the improvement in the same, upon introducing adversarial training. 4: Lastly, we have open-sourced the code here.

Figure 1. Variation in the probability of correct classification (37 classes) with and without adversarial training for varying ε.

Figure 2. The true accelerometer amplitude signal and its adversarial counterpart for ε = 0.4.

2. Methodology and Results

In this paper, we focus on the DCNN-based IDNet [4] framework, which entails harnessing low-pass-filtered tri-axial accelerometer and gyroscope readings (plus the sensor-specific magnitude signals), to, firstly, extract the gait template, of dimension 8 × 200, which is then used to train a DCNN in a supervised-classification setting. In the original paper, the model identified users in real time by using the DCNN as a deep-feature extractor and further training an outlier detector (one-class support vector machine-SVM), whose individual gait-wise outputs were finally combined into a Wald’s probability-ratio-test-based framework. Here, we focus on the trained IDNet-DCNN and characterize its performance in the adversarial-training regime. To this end, we harness the FGSM introduced in [14], where the adversarial example, x ̃, for a given input sample, x, is generated by: x ̃ = x + ε sign (∇xJ (θ, x)), where θ represents the parameter vector of the DCNN, J (θ, x) is the cost function used to train the DCNN, and ∇x () is the gradient function.

As seen, this method is parametrized by ε, which controls the magnitude of the inflicted perturbations. Fig. 2 showcases the true and adversarial gait-cycle signals for the accelerometer magnitude signal (given by amag(t) = √(a2x (t) + a2y (t) + a2z (t))) for ε = 0.4. Fig. 1 captures the drop in the probability of correct classification (37 classes) with increasing ε. First, we see that in the absence of any adversarial example, we were able to get about 96% ac- curacy on a 37 class classification problem, which is very close to what is claimed in [4]. However, with even mild perturbations (ε = 0.4), we see a sharp decrease of nearly 40% in accuracy. Fig. 1 also captures the effect of including the synthetically generated adversarial examples in this scenario. We see that, for ε = 0.4, we manage to achieve about 82% accuracy, which is a vast improvement of ∼ 25%.

3. Future Work

This brief paper is part of an ongoing research endeavor. We are currently currently extending this work to other adversarial-attack approaches, such as Jacobian-based Saliency-Map Approach (JSMA) and Black-Box-Attack (BBA) approach [15]. We are also investigating the effect of these attacks within the deep-feature-extraction+SVM approach of [4], and we are comparing other architectures, such as [6] and [5].

References
[1]  W.Melicher, D.Kurilova, S.M.Segreti, P.Kalvani, R.Shay, B. Ur, L. Bauer, N. Christin, L. F. Cranor, and M. L. Mazurek, “Usability and security of text passwords on mobile devices,” in Proceedings of the 2016 CHI Conference on Human Factors in Computing Systems, pp. 527–539, ACM, 2016. 1
[2]  E. Shi, Y. Niu, M. Jakobsson, and R. Chow, “Implicit authentication through learning user behavior,” in International Conference on Information Security, pp. 99–113, Springer, 2010. 1
[3]  J. Perry, J. R. Davids, et al., “Gait analysis: normal and pathological function.,” Journal of Pediatric Orthopaedics, vol. 12, no. 6, p. 815, 1992. 1
[4]  M. Gadaleta and M. Rossi, “Idnet: Smartphone-based gait recognition with convolutional neural networks,” arXiv preprint arXiv:1606.03238, 2016. 1, 2
[5]  Y. Zhao and S. Zhou, “Wearable device-based gait recognition using angle embedded gait dynamic images and a convolutional neural network,” Sensors, vol. 17, no. 3, p. 478, 2017. 1, 2
[6]  S. Yao, S. Hu, Y. Zhao, A. Zhang, and T. Abdelza- her, “Deepsense: A unified deep learning framework for time-series mobile sensing data processing,” arXiv preprint arXiv:1611.01942, 2016. 1, 2
[7]  S. Wang and J. Liu, Biometrics on mobile phone. INTECH Open Access Publisher, 2011. 1
[8]  Y. LeCun, Y. Bengio, and G. Hinton, “Deep learning,” Nature, vol. 521, no. 7553, pp. 436–444, 2015. 1
[9]  N. Neverova, C. Wolf, G. Lacey, L. Fridman, D. Chandra, B. Barbello, and G. Taylor, “Learning human identity from motion patterns,” IEEE Access, vol. 4, pp. 1810–1820, 2016. 1
[10]  C. Nickel, C. Busch, S. Rangarajan, and M. Mo ̈bius, “Using hidden markov models for accelerometer-based biometric gait recognition,” in Signal Processing and its Applications (CSPA), 2011 IEEE 7th International Colloquium on, pp. 58–63, IEEE, 2011. 1
[11]  C. Szegedy, W. Zaremba, I. Sutskever, J. Bruna, D. Erhan, I. Goodfellow, and R. Fergus, “Intriguing properties of neural networks,” arXiv preprint arXiv:1312.6199, 2013. 1
[12]  C. Szegedy, W. Liu, Y. Jia, P. Sermanet, S. Reed, D. Anguelov, D. Erhan, V. Vanhoucke, and A. Rabinovich, “Going deeper with convolutions,” in Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition, pp. 1–9, 2015. 1
[13]  N. Papernot, I. Goodfellow, R. Sheatsley, R. Feinman, and P. McDaniel, “cleverhans v1.0.0: an adversarial machine learning library,” arXiv preprint arXiv:1610.00768, 2016. 1
[14]  I. J. Goodfellow, J. Shlens, and C. Szegedy, “Explain- ing and harnessing adversarial examples,” arXiv preprint arXiv:1412.6572, 2014. 2
[15] N. Papernot, P. McDaniel, I. Goodfellow, S. Jha, Z. B. Celik, and A. Swami, “Practical black-box attacks against deep learning systems using adversarial examples,” arXiv preprint arXiv:1602.02697, 2016.