Authenticating the user to a remote server

If your app shares sensitive data with a server over the internet you need to make sure that:

  1. Your app only connects to the real server and not an attacker’s server.

  2. The user of your app is only able to access their data on the server.

  3. Other users or attackers are not able to access the user’s data on the server.

Ensuring the first is usually done using certificates through use of an HTTPS or SSL connection which we will discuss in the next step.

The second and third encapsulate the idea that a user should be able to access their data, and only their data. Enforcing this is ultimately the responsibility of the server, but in order for the server to do this, your app will be required to pass some form of user credential to the server.

Authentication and authorisation

At this point we need to introduce two related, but distinct concepts:

  1. Authentication: the process of proving who you are.

  2. Authorisation: the authority to perform a particular action.

In order for your app to perform a particular action on the server (access user data for example) your app will need to have authorisation. To acquire authorisation, your app, or an agent acting on its behalf, will have to authenticate itself by providing the user’s credentials to the server.

Notice here we allow the possibility that it is not your app that performs the authentication directly with the server, but that some third party agent might do that, and acquire the authorisation your app needs for you.

Typically the agent will authenticate themselves with the server by presenting the user’s credentials, and in return the server will pass them a token that provides authorisation to access a particular resource on the server. The agent will then pass the token to your app which can then use the token to access the resource.

The temporary URI permissions associated with a Content Provider can be thought of as a kind of authorisation token. The permission authorises access to a particular URI and can be passed, like a token, to another app component.

Advantages of authorisation tokens

Authorisation tokens have a lot of advantages over direct use of the user’s credentials:

  1. Apps need never know the user’s credentials, and therefore can never leak or steal them.

  2. The authorisation provided by a token can be restricted to only allow access to a subset of the resources associated with the user’s account.

  3. Tokens can be given fixed lifetimes and made to expire after a set period of time.

  4. Tokens can be tied to particular apps.

  5. Lost or stolen tokens can be revoked by the server without having to change the user’s password.

Privacy and tokens

The distinction between authentication and authorisation can become blurred. For example, my university electronic ID card acts as both the credential by which I authenticate myself, and the authorisation token by which I gain access to the university. However, this need not always be the case.

Authorisation tokens need not contain the identity of the user to which they were originally granted, and this can be important for privacy or confidentiality. Obviously the server that issued the token will know the user it was issued for, but the client app that presents the token to the server, the so-called bearer of the token, need not know the identity of the user they are acting on the behalf of.

The Android Account Manager

This all sounds a bit complicated, but the good news is that Android provides a standard mechanism for authenticating a user and acquiring an authorisation token, the AccountManager class.

For common web services like Google and Twitter etc., the AccountManager class already knows how to authenticate with those services, and an app can use AccountManager to request a token to access the user’s account.

The user’s account details (username and password) are stored by the AccountManager (hopefully protected by the device’s secure hardware!), and an app can ask the user to select which account they would like to use, and the app then requests a token from the AccountManager using getAuthToken(). The AccountManager is responsible for acquiring the token from the server.

If the service is not one of the types that AccountManager already knows about, perhaps it is one provided by your own servers, then you can implement your own authenticator for AccountManager to use when accessing accounts of that type. The details of how to do this are beyond the scope of this course.

The Android documentation contains more details on how to use AccountManager, and how to create custom authenticators.

Using our token

Ok, so we now have a token, or perhaps a username and password if our server does not use tokens, but how do we use them?

Well that depends upon the server, and the protocol that it supports. Typically these days, the server will be a web server of some sort, and we will communicate with it using HTTP (hopefully secured HTTPS).

As HTTP is a stateless protocol the user’s credentials, or the authorisation token, need to be sent to the server with every request. These are passed as HTTP headers.

HTTP headers can be added or set by the addRequestProperty() and setRequestProperty() methods of the URLConnection object returned by the call to openConnection() (on the URL object).

The exact format of the HTTP header required will depend upon the exact protocol required by the server. The Android documentation shows how to do this for Google’s services.

Notes for Nerds: In the case of HTTP basic authentication (username and password), Android supports the standard Java Authenticator class that simplifies setting the necessary HTTP header. This is done by calling the static Authenticator.setDefault() method with a custom instance of the Authenticator class in which the getPasswordAuthentication() method is overridden to return the username and password. The Android documentation contains more details.

Share this article:

This article is from the free online course:

Secure Android App Development

University of Southampton