A JBoss Project
Red Hat

Aerogear Guides Tutorials to help get you off and running.

AeroGear Android Authentication

The goal of this guide is to provide a description of how authentication works in AeroGear Android and to give developers the ability to integrate their Android application with RESTful services.

In RESTful services there are two basic parts of Authentication:

  • Logging in and Fetching a token

  • Applying the token to a request

This guide will go in depth on these two topics; however, we will also discuss briefly:

  • Registering a new user

  • Logging out of a service

API overview

Interaction with Authentication services is mediated using classes which implement the AuthenticationModule interface. AuthenticationModule is a child of PipeModule and is appended to a Pipe during configuration with PipeConfiguration.module. You can find more information about PipeModule in the pipe tutorial.

AuthenticationModules may be called by the user. In general the login method will pass tokens to a server and parse the response for any necessary keys. Logout will remove the tokens locally and call any necessary server methods. enroll will pass a user’s information to a remote service and create an account. These tasks are often implementation specific. We do have modules supporting HttpBasic and HttpDigest as part of the AeroGear framework.

AbstractAuthenticationModule is a convenience class for integrating with non AeroGear REST services. It is also useful for when you want to only support a subset of the AuthenticationModule's functionality, and it configures a THREAD_POOL_EXECUTOR for you to delegate your network calls to.

How to use it

Setting up authentication in pipe requests

// Create AuthenticationModule
HttpDigestAuthenticationConfiguration config = AuthenticationManager.config(SIMPLE_MODULE_NAME, HttpDigestAuthenticationConfiguration.class);
config.loginEndpoint("testLogin").logoutEndpoint("testLogout").baseURL(SIMPLE_URL)

AuthenticationModule simpleAuthModule = config.asModule();


// Add AuthenticationModule to Pipe
RestfulPipeConfiguration pipeConfig = PipeManager.config("autobots", RestfulPipeConfiguration.class);
pipeConfig.withUrl(CONTROLLER_URL);
pipeConfig.module(simpleAuthModule);

Using Authentication

While the application is not logged in, AuthenticationModule will stay out of the way. However, interacting with authentication is this simple.

login
authenticationModule.login("myUsername", "myPassword", myCallback);

Alternatively, if your login needs extra data you can also submit a map.

loginWithCustomKeys
Map<String, String> loginData = new HashMap<String, String>();
loginData.put("username", "ag");
loginData.put("password", "awesome");

authenticationModule.login(loginData, myCallback);
logout
authenticationModule.logout(myCallback);
enroll
HashMap<String, String> userData = new HashMap<String, String>();
userData.put("firstname", "AeroGear");
userData.put("email", "aerogear-dev@lists.jboss.org");
userData.put("username", "ag");
userData.put("password", "awesome");

authenticationModule.enroll(userData, myCallback);

Authentication Types

We currently provide two AuthenticationModule implementations. HttpBasic and HttpDigest.

AuthenticationConfiguration config = AuthenticationManager.config(SIMPLE_MODULE_NAME, HttpBasicAuthenticationConfiguration.class);
AuthenticationModule simpleAuthModule = config.baseURL(SIMPLE_URL).asModule();
AuthenticationConfiguration config = AuthenticationManager.config(SIMPLE_MODULE_NAME, HttpDigestAuthenticationConfiguration.class);
AuthenticationModule simpleAuthModule = config.baseURL(SIMPLE_URL).asModule();

Take a look at the complete example in our cookbook app

Using Authentication: Custom Applications

AeroGear Android's Authentication API provides a framework for supporting many other RESTful services. Obviously this guide cannot cover all of them, but we will review custom authentication with one third party service, Reddit.

To retrieve the tokens Reddit requires for accessing a user's data we must log in as that user. Reddit's login service consumes a HTTP POST at the URL http://www.reddit.com/api/login/%username with the Content-Type of application/x-www-form-urlencoded. The request body is required to also include the parameters user, passwd, and api_type. It returns a JSON response with parameters "json.data.modhash" and "json.data.cookie". These parameters are extracted as part of the login method and passed to the Pipe implementation from the getAuthorizationFields method.

Every Pipe request against the Reddit service from now on, will include these authorisation parameters as part of the request.

RedditAuthenticationModule

public class RedditAuthenticationModule extends AbstractAuthenticationModule {

    private String authToken = "";
    private String modHash = "";

	@Override
    public void login(final String username, final String password,
		    final Callback<HeaderAndBody> callback) {
        THREAD_POOL_EXECUTOR.execute(new Runnable() {
		private Exception exception;
		private HeaderAndBody result;

		@Override
		public void run() {
		        try {
		        	HttpProvider provider =
					new HttpRestProvider( new URL(String.format("http://www.reddit.com/api/login/%s", username)) );
		        	provider.setDefaultHeader("User-Agent", "AeroGear StoryList Demo /u/secondsun");
		        	provider.setDefaultHeader("Content-Type", "application/x-www-form-urlencoded");

				result = provider.post(String.format("user=%s&api_type=json&passwd=%s",username,password);

				String json = new String(result.getBody());
				JsonObject authenticationObject = new JsonParser().parse(json).getAsJsonObject()
										  .get("json").getAsJsonObject()
										  .get("data").getAsJsonObject();

				modHash = authenticationObject.get("modhash").getAsString();
				authToken = authenticationObject.get("cookie").getAsString();

				isLoggedIn = true;
		        } catch (Exception e) {
		            exception = e;
		        }

			if (exception == null) {
		            callback.onSuccess(this.result);
		        } else {
		            callback.onFailure(exception);
		        }

		}


	});


	}

    public AuthorizationFields getAuthorizationFields() {

        AuthorizationFields fields = new AuthorizationFields();
        fields.addHeader("User-Agent", "AeroGear StoryList Demo /u/secondsun");
        if (isLoggedIn) {
            fields.addHeader("Cookie", "reddit_session="+authToken);
            fields.addQueryParameter("uh", modHash);
        }
        return fields;
    }

}

Take a look at the complete example in AGReddit

redhatlogo-wite