![]() |
Many mobile applications today connect to external web services to access some type of data. These web services may be a third-party data provider, such as Twitter, or it may be an in house service for connecting to a corporate calendar, for example. In many of these cases, to access that data through the web service, you must authenticate and authorize an application on your mobile device. The goal of the spring-android-auth module is to address the need of an Android application to gain authorization to a web service. There are many types of authorization methods and protocols, some custom and proprietary, while others are open standards. One protocol that is rapidly growing in popularity is OAuth. OAuth is an open protocol that allows users to give permission to a third-party application or web site to access restricted resources on another web site or service. The third-party application receives an access token with which it can make requests to the protected service. By using this access token strategy, a user's login credentials are never stored within an application, and are only required when authenticating to the service. The initial release of the spring-android-auth module provides OAuth 1.x and 2.0 support in an Android application by utilizing Spring Social. It includes a SQLite repository, and Android compatible Spring Security encryption. The Spring Social project enables your applications to establish Connections with Software-as-a-Service (SaaS) Providers such as Facebook and Twitter to invoke Service APIs on behalf of Users. In order to make use of Spring Social on Android the following classes are available. The
If your device and application are used by multiple people, then a
The Spring Security Crypto library is not currently supported on Android. To take advantage of the encryption tools in Spring Security, the Android specific class,
There are a few methods for including external jars in your Android app. One is to manually download them and include them in your app's In order to use RestTemplate in your Android application, you must include the following Spring jars in the
Each Spring Social provider may have additional dependencies. For example, to use Spring Social Twitter, the following jars are required.
If you are building your project with Ant, Ant will automatically include any jars located in the
Add the spring-android-auth artifact to your classpath. See the Spring for Android and Maven section for more information. <dependency> <groupId>org.springframework.android</groupId> <artifactId>spring-android-auth</artifactId> <version>${spring-android-version}</version> </dependency>
The transitive dependencies are automatically imported by Maven, but they are listed here for clarity. <dependency> <groupId>org.springframework.android</groupId> <artifactId>spring-android-rest-template</artifactId> <version>${spring-android-version}</version> </dependency> <dependency> <groupId>org.springframework.android</groupId> <artifactId>spring-android-core</artifactId> <version>${spring-android-version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-crypto</artifactId> <version>${spring-security-crypto-version}</version> <exclusions> <!-- Exclude in favor of Spring for Android Core --> <exclusion> <artifactId>spring-core</artifactId> <groupId>org.springframework</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.social</groupId> <artifactId>spring-social-core</artifactId> <version>${spring-social-version}</version> <exclusions> <!-- Exclude in favor of Spring for Android RestTemplate --> <exclusion> <artifactId>spring-web</artifactId> <groupId>org.springframework</groupId> </exclusion> </exclusions> </dependency>
To use the Spring Social Twitter provider, you can add it to your classpath. Note the exclusions in this dependency. Commons Logging is built into Android, and many of the Spring Social provider libraries are built with support for Spring Web, which is not needed on Android. <dependency> <groupId>org.springframework.social</groupId> <artifactId>spring-social-twitter</artifactId> <version>${spring-social-version}</version> <exclusions> <exclusion> <!-- Provided by Android --> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> </exclusions> </dependency>
Similarly, you can use the Spring Social Facebook provider by adding it to your classpath. Again note the exclusions. <dependency> <groupId>org.springframework.social</groupId> <artifactId>spring-social-facebook</artifactId> <version>${spring-social-version}</version> <exclusions> <!-- Provided by Android --> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> </exclusions> </dependency>
Both the Spring Social Twitter and Facebook libraries transitively depend on the
Jackson JSON processor. Again, if you are not using Maven, you will need to include these in your <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>${jackson-version}</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-core-asl</artifactId> <version>${jackson-version}</version> </dependency>
Below are several usage examples that illustrate how to use Spring for Android with Spring Social. The following examples are based on a sample Android application, which has Facebook and Twitter examples using Spring Social. You can retrieve the source code for the sample app with Git: $ git clone git://github.com/spring-projects/spring-android-samples.git
Context context = getApplicationContext();
SQLiteOpenHelper repositoryHelper = new SQLiteConnectionRepositoryHelper(context);
This example show how to set up the To establish a ConnectionFactoryRegistry connectionFactoryRegistry; SQLiteOpenHelper repositoryHelper; ConnectionRepository connectionRepository; The
connectionFactoryRegistry = new ConnectionFactoryRegistry();
You can create a
// the App ID and App Secret are provided when you register a new Facebook application at facebook.com String appId = "8ae8f060d81d51e90fadabaab1414a97"; String appSecret = "473e66d79ddc0e360851dc512fe0fb1e"; // Prepare a Facebook connection factory with the App ID and App Secret FacebookConnectionFactory facebookConnectionFactory; facebookConnectionFactory = new FacebookConnectionFactory(appId, appSecret); Similarly, you can also create a
// The consumer token and secret are provided when you register a new Twitter application at twitter.com String consumerToken = "YR571S2JiVBOFyJS5MEg"; String consumerTokenSecret = "Kb8hS0luftwCJX3qVoyiLUMfZDtK1EozFoUkjNLUMx4"; // Prepare a Twitter connection factory with the consumer token and secret TwitterConnectionFactory twitterConnectionFactory; twitterConnectionFactory = new TwitterConnectionFactory(consumerToken, consumerTokenSecret) After you create a connection factory, you can add it to the registry. Connection factories may be later retrieved from the registry in order to create new connections to the provider. connectionFactoryRegistry.addConnectionFactory(facebookConnectionFactory); connectionFactoryRegistry.addConnectionFactory(twitterConnectionFactory); The final step is to prepare the connection repository for storing connections to the different providers. // Create the SQLiteOpenHelper for creating the local database Context context = getApplicationContext(); SQLiteOpenHelper repositoryHelper = new SQLiteConnectionRepositoryHelper(context); // The connection repository takes a TextEncryptor as a parameter for encrypting the OAuth information TextEncryptor textEncryptor = AndroidEncryptors.noOpText(); // Create the connection repository ConnectionRepository connectionRepository = new SQLiteConnectionRepository(repositoryHelper, connectionFactoryRegistry, textEncryptor); Spring Social supports encrypting the user's OAuth connection information within the String password = "password"; String salt = "5c0744940b5c369b"; TextEncryptor textEncryptor = AndroidEncryptors.text(password, salt); connectionRepository = new SQLiteConnectionRepository(repositoryHelper, connectionFactoryRegistry, textEncryptor); During development you may wish to avoid encryption so you can more easily debug your application by viewing the OAuth data being saved to the database. This TextEncryptor textEncryptor = AndroidEncryptors.noOpText();
connectionRepository = new SQLiteConnectionRepository(repositoryHelper,
connectionFactoryRegistry, textEncryptor);
The following steps illustrate how to establish a connection to Twitter. A working example is provided in the sample application described earlier. The first step is to retrieve the connection factory from the registry that we created earlier. TwitterConnectionFactory connectionFactory;
connectionFactory = (TwitterConnectionFactory) connectionFactoryRegistry.getConnectionFactory(Twitter.class);
Fetch a one time use request token. You must save this request token, because it will be needed in a later step. OAuth1Operations oauth = connectionFactory.getOAuthOperations(); // The callback url is used to respond to your application with an OAuth verifier String callbackUrl = "x-org-springsource-android-showcase://twitter-oauth-response"; // Fetch a one time use Request Token from Twitter OAuthToken requestToken = oauth.fetchRequestToken(callbackUrl, null); Generate the url for authorizing against Twitter. Once you have the url, you use it in a WebView so the user can login and authorize your application. One method of doing this is provided in the sample application. String authorizeUrl = oauth.buildAuthorizeUrl(requestToken.getValue(), OAuth1Parameters.NONE); Once the user has successfully authenticated and authorized the application, Twitter will call back to your application with the oauth verifier. The following settings from an AndroidManifest illustrate how to associate a callback url with a specific Activity. In this case, when the request is made from Twitter to the callback url, the TwitterActivity will respond. <activity android:name="org.springframework.android.showcase.social.twitter.TwitterActivity"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="x-org-springsource-android-showcase" android:host="twitter-oauth-response" /> </intent-filter> </activity> The Activity that responds to the callback url should retrieve the Uri uri = getIntent().getData();
String oauthVerifier = uri.getQueryParameter("oauth_verifier");
Once you have the oauth_verifier, you can authorize the request token that was saved earlier. AuthorizedRequestToken authorizedRequestToken = new AuthorizedRequestToken(requestToken, verifier);
Now exchange the authorized request token for an access token. Once you have the access token, the request token is no longer required, and can be safely discarded. OAuth1Operations oauth = connectionFactory.getOAuthOperations(); OAuthToken accessToken = oauth.exchangeForAccessToken(authorizedRequestToken, null); Finally, we can create a Twitter connection and store it in the repository. Connection<TwitterApi> connection = connectionFactory.createConnection(accessToken); connectionRepository.addConnection(connection); The following steps illustrate how to establish a connection to Facebook. A working example is provided in the sample application described earlier. Keep in mind that each provider's implementation may be different. You may have to adjust these steps when connecting to a different OAuth 2.0 provider. The first step is to retrieve the connection factory from the registry that we created earlier. FacebookConnectionFactory connectionFactory;
connectionFactory = (FacebookConnectionFactory) connectionFactoryRegistry.getConnectionFactory(Facebook.class);
Specify the redirect url. In the case of Facebook, we are using the client-side authorization flow. In order to retrieve the access token, Facebook will redirect to a success page that contains the access token in a URI fragment. String redirectUri = "https://www.facebook.com/connect/login_success.php";
Define the scope of permissions your app requires. String scope = "publish_stream,offline_access,read_stream,user_about_me";
In order to display a mobile formatted web page for Facebook authorization, you must pass an additional parameter in the request. This parameter is not part of the OAuth specification, but the following illustrates how Spring Social supports additional parameters. MultiValueMap<String, String> additionalParameters = new LinkedMultiValueMap<String, String>(); additionalParameters.add("display", "touch"); Now we can generate the Facebook authorization url to be used in the browser or web view OAuth2Parameters parameters = new OAuth2Parameters(redirectUri, scope, null, additionalParameters);
OAuth2Operations oauth = connectionFactory.getOAuthOperations();
String authorizeUrl = oauth.buildAuthorizeUrl(GrantType.IMPLICIT_GRANT, parameters);
The next step is to load the generated authorization url into a webview within your application. After the user logs in and authorizes your application, the browser will redirect to the url specified earlier. If authentication was successful, the url of the redirected page will now include a URI fragment which contains an access_token parameter. Retrieve the access token from the URI fragment and use it to create the Facebook connection. One method of doing this is provided in the sample application. AccessGrant accessGrant = new AccessGrant(accessToken);
Connection<FacebookApi> connection = connectionFactory.createConnection(accessGrant);
connectionRepository.addConnection(connection);
|