Skip to main content
knackforge blog knowledge base

Android app integration with Drupal for OAuth

When you build Android app for an existing Drupal website which allows it's users to login 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 android app, use webview 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 Drupal site. Drupal side authenticates user by this token.

Drupal side

First we need to define 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 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 module 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 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 "<script>".$js."</script>";
    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 here much. 

Android side

I assume you have created 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 thisread androidcookbook.com. shouldOverrideUrlLoading() method that returns "false" makes any further URL openings happen in same webview, otherwise it will open default web browser of Android which will remove any sessions from 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 on Android app development or Drupal development, feel free to contact us.