blog-banner

Android App Integration with Drupal for OAuth

  • Drupal
  • Drupal Planet

Android Mobile App Integration With Drupal

When you build an Android app for an existing Drupal website that allows its users to log in using their social media account, it is important to include such features in your app as well. Instead of using app-specific APIs, we can use WebView to achieve the login mechanism. Let me explain the method that I followed,

1) Setup Drupal menu paths for social login(s).

2) From the android app, use a web view that can call Drupal path for social login.

3) Drupal side completes the authentication and sends back an identification token to Android.

4) Android app uses the token to make further calls to the Drupal site. Drupal side authenticates users by this token.

Drupal Side

First, we need to define an entry point for social login,

function MY_MODULE_menu() {
    $items = array();
    $items['api/login/%'] = array(
      'access callback'  => TRUE,
      'page callback'     => '_MY_MODULE_oauth_login',
      'page arguments' => array(2),
      'type'              => MENU_CALLBACK,
    );
    return $items;
  }
 

This will receive all social login requests. If you are going to use the services module instead, you could do so and apply this code as needed. Now define the callback function,

function _MY_MODULE_oauth_login($type) {
  $_SESSION['app_login_attempt'] = 1;
  if ($type == 'google') {
    if (module_exists('gauth_login')) {
      gauth_login_user_login_submit();
    }
  }
  else if ($type == 'twitter') {
    if (module_exists('twitter_signin')) {
      twitter_signin_redirect();
    }
  }
}
I use gauth and Twitter modules for the OAuth implementation. The methods gauth_login_user_login_submit() and  twitter_signin_redirect() belong to respective modules. Now the main part, on successful authentication, send back the details to the Android app using hook_init().
function MY_MODULE_init() {
  $global $user;
  if (isset($_SESSION['app_login_attempt']) && $user->uid >0)) {
    $token = _MY_MODULE_generate_token($user->uid);
    $id = _MY_MODULE_update_token($token, $user->uid);    
    unset($_SESSION['app_login_attempt']);
    $js = "android.setToken('{$token}')";
    print "";
    exit;
  }
}

Note the "android.setToken()", which we will discuss below. Methods _MY_MODULE_generate_token and _MY_MODULE_update_token are the mechanisms that I used to identify users. REST API should not use the session details of Drupal. Hence we need to use some token-based identification method, which we are not going to deal with here much.

Android side

I assume you have created the necessary layout files and activity with click handlers for social buttons,

Button googleSignInButton = (Button) findViewById(R.id.loginGoogle);
googleSignInButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(getApplicationContext(), BrowserActivity.class);
        intent.putExtra("type", "google");
        startActivity(intent);
    }
});

On clicking the button, we start a new activity called BrowserActivity which is going to open the webview,

public class BrowserActivity extends Activity {
    private WebView webView;
    public String token="";
    public String type="";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = getIntent();
        type = intent.getStringExtra("type");

        setContentView(R.layout.activity_browser);
        webView = new WebView(this);
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webView.addJavascriptInterface(this, "android");
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url)
            {
                return false;
            }
        });
        webView.requestFocusFromTouch();
        webView.loadUrl(Navigation.domain+"/api/login/" + type + "?app=1");
        setContentView(webView);
    }

    /** Allow the JavaScript to pass some data in to us. */
    @JavascriptInterface
    public void setToken(String t) {
        token = t;
        //We have got the token, save it/do whatever you need.
    }
}
 

The line webView.addJavascriptInterface(this, "android") enables the bridge between javascript and android by which they can share data. For more details on this read androidcookbook.com. shouldOverrideUrlLoading() method that returns "false" makes any further URL openings happen in the same web view, otherwise, it will open the default web browser of Android which will remove any sessions from the previous call.

The beauty of the method is, you can include other social logins by adding another condition _MY_MODULE_oauth_login() method. In case you need us to help with Android app development or Drupal development, feel free to contact us.
Get awesome tech content in your inbox