diff --git a/mobile/AndroidManifest.xml b/mobile/AndroidManifest.xml
index 942e160b..d7e54c57 100644
--- a/mobile/AndroidManifest.xml
+++ b/mobile/AndroidManifest.xml
@@ -8,9 +8,11 @@
         android:minSdkVersion="14"
         android:targetSdkVersion="17" />
 
-    
     
     
+    
+    
+    
 
     
+
diff --git a/mobile/res/values/strings.xml b/mobile/res/values/strings.xml
index ac731228..5639c5a6 100644
--- a/mobile/res/values/strings.xml
+++ b/mobile/res/values/strings.xml
@@ -55,4 +55,6 @@
     Faction
     Info
     Debug
+    Choose account to login
+    Login failed.
 
\ No newline at end of file
diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_DeviceAccountLogin.java b/mobile/src/com/cradle/iitc_mobile/IITC_DeviceAccountLogin.java
new file mode 100644
index 00000000..ba0ce3d1
--- /dev/null
+++ b/mobile/src/com/cradle/iitc_mobile/IITC_DeviceAccountLogin.java
@@ -0,0 +1,189 @@
+package com.cradle.iitc_mobile;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+import android.widget.Toast;
+
+/**
+ * this class manages automatic login using the Google account stored on the device
+ */
+public class IITC_DeviceAccountLogin implements AccountManagerCallback {
+    /**
+     * Adapter to show available accounts in a ListView. Accounts are read from mAccounts
+     */
+    private class AccountAdapter extends BaseAdapter {
+        @Override
+        public int getCount() {
+            return mAccounts.length;
+        }
+
+        @Override
+        public Account getItem(int position) {
+            return mAccounts[position];
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            LayoutInflater inflater = mActivity.getLayoutInflater();
+            View v = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
+
+            TextView tv = (TextView) v.findViewById(android.R.id.text1);
+            tv.setText(mAccounts[position].name);
+
+            return tv;
+        }
+    }
+
+    private Account mAccount;
+    private AccountAdapter mAccountAdapter;
+    private AccountManager mAccountManager;
+    private Account[] mAccounts;
+    private IITC_Mobile mActivity;
+    private String mAuthToken;
+    private AlertDialog mProgressbar;
+    private WebView mWebView;
+
+    /**
+     * This listener is invoked when an item in the account list is selected. (It is also used when the 'cancel' button
+     * is clicked, (in which case `index` is <0)
+     */
+    private DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
+        @Override
+        public void onClick(DialogInterface dialog, int index) {
+            if (index >= 0 && index < mAccounts.length) {
+                mAccount = mAccounts[index];
+                startAuthentication();
+            }
+            dialog.cancel();
+        }
+    };
+
+    public IITC_DeviceAccountLogin(IITC_Mobile activity, WebView webView, WebViewClient webViewClient) {
+        mActivity = activity;
+        mWebView = webView;
+        mAccountManager = AccountManager.get(activity);
+        mAccountAdapter = new AccountAdapter();
+
+        // dialog that serves as a progress bar overlay
+        mProgressbar = new AlertDialog.Builder(mActivity)
+                .setCancelable(false)
+                .setView(mActivity.getLayoutInflater().inflate(R.layout.dialog_progressbar, null))
+                .create();
+    }
+
+    /**
+     * display all available accounts to the user
+     */
+    private void displayAccountList() {
+        AlertDialog.Builder builder = new AlertDialog.Builder(mActivity)
+                .setTitle(R.string.choose_account_to_login)
+                .setSingleChoiceItems(mAccountAdapter, 0, onClickListener)
+                .setNegativeButton(android.R.string.cancel, onClickListener);
+
+        AlertDialog dialog = builder.create();
+        dialog.show();
+    }
+
+    /**
+     * called when something failed. Shows a toast message. Classic login is still available
+     */
+    private void onLoginFailed() {
+        Toast.makeText(mActivity, R.string.login_failed, Toast.LENGTH_SHORT).show();
+    }
+
+    /**
+     * called to start authenticating using AccountManager.
+     * 
+     * After a token is created, AccountManager will call the run() method.
+     */
+    private void startAuthentication() {
+        mProgressbar.show();
+
+        mAccountManager.getAuthToken(mAccount, mAuthToken, null, mActivity, this, null);
+    }
+
+    /**
+     * called by IITC_Mobile when the authentication activity has finished.
+     */
+    public void onActivityResult(int resultCode, Intent data) {
+        if (resultCode == Activity.RESULT_OK)
+            // authentication activity succeeded, request token again
+            startAuthentication();
+        else
+            onLoginFailed();
+    }
+
+    /**
+     * called by AccountManager
+     */
+    @Override
+    public void run(AccountManagerFuture value) {
+        mProgressbar.hide();
+
+        try {
+            Intent launch = (Intent) value.getResult().get(AccountManager.KEY_INTENT);
+            if (launch != null) {
+                // There is a reason we need to start the given activity if we want an authentication token.
+                // (Could be user confirmation or something else. Whatever, we have to start it)
+                // IITC_Mobile will call it using startActivityForResult
+                mActivity.startLoginActivity(launch);
+                return;
+            }
+
+            String result = value.getResult().getString(AccountManager.KEY_AUTHTOKEN);
+            if (result != null) {
+                // authentication succeded, we can load the given url, which will redirect back to the intel map
+                mWebView.loadUrl(result);
+                mActivity.loginSucceded();
+            } else {
+                onLoginFailed();
+            }
+        } catch (Exception e) {
+            onLoginFailed();
+        }
+    }
+
+    /**
+     * start authentication
+     * 
+     * if we already have a username (e.g. because the existing login has timed out), we can directly start
+     * authentication if an account with that username is found.
+     */
+    public void startLogin(String realm, String accountName, String args) {
+        mAccounts = mAccountManager.getAccountsByType(realm);
+        mAccountAdapter.notifyDataSetChanged();
+        mAuthToken = "weblogin:" + args;
+
+        if (mAccounts.length == 0) {
+            return;
+        }
+
+        for (Account account : mAccounts) {
+            if (account.name.equals(accountName)) {
+                mAccountManager.getAuthToken(account, mAuthToken, null, mActivity, this, null);
+                return;
+            }
+        }
+
+        displayAccountList();
+    }
+}
diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java
index 9af53094..e937c686 100644
--- a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java
+++ b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java
@@ -2,7 +2,13 @@ package com.cradle.iitc_mobile;
 
 import java.io.IOException;
 
-import com.cradle.iitc_mobile.R;
+import android.app.ActionBar;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.res.Configuration;
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
@@ -13,21 +19,18 @@ import android.os.Bundle;
 import android.os.Handler;
 import android.os.StrictMode;
 import android.preference.PreferenceManager;
-import android.app.ActionBar;
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-import android.content.res.Configuration;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
+import android.view.Window;
 import android.view.WindowManager;
+import android.webkit.WebView;
 import android.widget.Toast;
 
 public class IITC_Mobile extends Activity {
 
+    private static final int REQUEST_LOGIN = 1;
+
     private IITC_WebView iitc_view;
     private boolean back_button_pressed = false;
     private OnSharedPreferenceChangeListener listener;
@@ -38,11 +41,15 @@ public class IITC_Mobile extends Activity {
     private boolean fullscreen_mode = false;
     private boolean fullscreen_actionbar = false;
     private ActionBar actionBar;
+    private IITC_DeviceAccountLogin mLogin;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        // enable progress bar above action bar
+        requestWindowFeature(Window.FEATURE_PROGRESS);
+
         // TODO build an async task for url.openStream() in IITC_WebViewClient
         StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
                 .permitAll().build();
@@ -354,4 +361,42 @@ public class IITC_Mobile extends Activity {
     public IITC_WebView getWebView() {
         return this.iitc_view;
     }
+
+    /**
+     * It can occur that in order to authenticate, an external activity has to be launched. (This could for example be a
+     * confirmation dialog.)
+     */
+    public void startLoginActivity(Intent launch) {
+        startActivityForResult(launch, REQUEST_LOGIN); // REQUEST_LOGIN is to recognize the result
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        switch (requestCode) {
+            case REQUEST_LOGIN :
+                // authentication activity has returned. mLogin will continue authentication
+                mLogin.onActivityResult(resultCode, data);
+                break;
+
+            default :
+                super.onActivityResult(requestCode, resultCode, data);
+        }
+    }
+
+    /**
+     * called by IITC_WebViewClient when the Google login form is opened.
+     */
+    public void onReceivedLoginRequest(IITC_WebViewClient client, WebView view,
+            String realm, String account, String args) {
+        mLogin = new IITC_DeviceAccountLogin(this, view, client);
+        mLogin.startLogin(realm, account, args);
+    }
+
+    /**
+     * called after successful login
+     */
+    public void loginSucceded() {
+        // garbage collection
+        mLogin = null;
+    }
 }
diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java
index 866d1f38..b3a752a3 100644
--- a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java
+++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java
@@ -2,6 +2,7 @@ package com.cradle.iitc_mobile;
 
 import android.annotation.SuppressLint;
 import android.annotation.TargetApi;
+import android.app.Activity;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.net.ConnectivityManager;
@@ -39,14 +40,29 @@ public class IITC_WebView extends WebView {
         this.js_interface = new IITC_JSInterface(c);
         this.addJavascriptInterface(js_interface, "android");
 
-        // our webchromeclient should share geolocation with the iitc script
-        // allow access by default
         this.setWebChromeClient(new WebChromeClient() {
+            /**
+             * our webchromeclient should share geolocation with the iitc script
+             * 
+             * allow access by default
+             */
             @Override
             public void onGeolocationPermissionsShowPrompt(String origin,
                     GeolocationPermissions.Callback callback) {
                 callback.invoke(origin, true, false);
             }
+
+            /**
+             * display progress bar in activity
+             */
+            @Override
+            public void onProgressChanged(WebView view, int newProgress) {
+                super.onProgressChanged(view, newProgress);
+
+                // maximum for newProgress is 100
+                // maximum for setProgress is 10,000
+                ((Activity) getContext()).setProgress(newProgress * 100);
+            }
         });
 
         webclient = new IITC_WebViewClient(c);
diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java
index f606d5ac..6f75ab6f 100644
--- a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java
+++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java
@@ -133,6 +133,14 @@ public class IITC_WebViewClient extends WebViewClient {
         handler.proceed();
     };
 
+    /**
+     * this method is called automatically when the Google login form is opened.
+     */
+    @Override
+    public void onReceivedLoginRequest(WebView view, String realm, String account, String args) {
+        ((IITC_Mobile) context).onReceivedLoginRequest(this, view, realm, account, args);
+    }
+
     // plugins should be loaded after the main script is injected
     @Override
     public void onPageFinished(WebView view, String url) {