Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14c58b7c authored by Nihar Thakkar's avatar Nihar Thakkar Committed by Sumit Pundir
Browse files

Implement SSO for Google accounts

parent c8f5837a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
        android:normalScreens="true"
        android:smallScreens="true"/>

    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
+72 −4
Original line number Diff line number Diff line
@@ -6,18 +6,33 @@ import java.util.Map;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;

import io.eelo.mail.activity.Accounts;

import io.eelo.mail.mail.AuthenticationFailedException;
import io.eelo.mail.mail.OAuth2NeedUserPromptException;
import io.eelo.mail.mail.oauth.OAuth2TokenProvider;

import static io.eelo.mail.account.OAuthConstants.ACCOUNT_EMAIL_ID_KEY;
import static io.eelo.mail.account.OAuthConstants.AUTH_TOKEN_TYPE;
import static io.eelo.mail.account.OAuthConstants.EELO_ACCOUNT_TYPE;
import static io.eelo.mail.account.OAuthConstants.GOOGLE_ACCOUNT_TYPE;

public class K9OAuth2TokenProvider extends OAuth2TokenProvider {

    private static final String GOOGLE_ACCOUNT_TYPE = "com.google";
    private static final String OFFICIAL_GOOGLE_ACCOUNT_TYPE = "com.google";

    private AccountManager accountManager;
    private String authToken = null;

    private AndroidAccountOAuth2TokenStore gmailTokenProviderWithAccountSystem;
    private K9OAuth2AuthorizationCodeFlowTokenProvider authorizationCodeFlowTokenProvider;
@@ -34,7 +49,7 @@ public class K9OAuth2TokenProvider extends OAuth2TokenProvider {
    }

    private Account getAccountFromManager(String emailAddress) {
        android.accounts.Account[] accounts = accountManager.getAccountsByType(GOOGLE_ACCOUNT_TYPE);
        android.accounts.Account[] accounts = accountManager.getAccountsByType(OFFICIAL_GOOGLE_ACCOUNT_TYPE);
        for (android.accounts.Account account : accounts) {
            if (account.name.equals(emailAddress)) {
                return account;
@@ -47,8 +62,13 @@ public class K9OAuth2TokenProvider extends OAuth2TokenProvider {
    @Override
    public String getToken(String email, long timeoutMillis)
	    throws AuthenticationFailedException, OAuth2NeedUserPromptException {
        Account gmailAccount = getAccountFromManager(email);
        getTokenFromAccountManager(email);
        Log.i("OAuth token value", authToken);
        if (authToken != null) {
            return authToken;
        }

	Account gmailAccount = getAccountFromManager(email);
        if (gmailAccount != null) {
            return gmailTokenProviderWithAccountSystem.getToken(email, gmailAccount, timeoutMillis);
        }
@@ -56,6 +76,54 @@ public class K9OAuth2TokenProvider extends OAuth2TokenProvider {
        return authorizationCodeFlowTokenProvider.getToken(email, timeoutMillis);
    }

    private void getTokenFromAccountManager(String emailId) {
        android.accounts.Account[] eeloAccounts = accountManager.getAccountsByType(
                EELO_ACCOUNT_TYPE);
        android.accounts.Account[] googleAccounts = accountManager.getAccountsByType(
                GOOGLE_ACCOUNT_TYPE);

        ArrayList<Account> accounts = new ArrayList<>();
        for (Account eeloAccount : eeloAccounts) {
            accounts.add(eeloAccount);
        }
        for (Account googleAccount : googleAccounts) {
            accounts.add(googleAccount);
        }

        if (accounts.size() > 0) {
            for (Account account : accounts) {
                String accountEmailId = accountManager.getUserData(account,
                        ACCOUNT_EMAIL_ID_KEY);
                if (emailId.equals(accountEmailId)) {
                    final CountDownLatch countDownLatch = new CountDownLatch(1);
                    accountManager.getAuthToken(account, AUTH_TOKEN_TYPE, new Bundle(),
                            null, new AccountManagerCallback<Bundle>() {
                                @Override
                                public void run(AccountManagerFuture<Bundle>
                                                        accountManagerFuture) {
                                    try {
                                        authToken = accountManagerFuture.getResult().getString(
                                                AccountManager.KEY_AUTHTOKEN);
                                        countDownLatch.countDown();
                                    } catch (Exception e) {
                                        authToken = null;
                                    }
                                }
                            }, null);
                    try {
                        countDownLatch.await();
                    }
                    catch (Exception e)
                    {
                        authToken = null;
                    }
                }
            }
        } else {
            authToken = null;
        }
    }

    @Override
    public void invalidateToken(String email) {
        Account gmailAccount = getAccountFromManager(email);
+9 −0
Original line number Diff line number Diff line
package io.eelo.mail.account;

public class OAuthConstants {
    public static final String EELO_ACCOUNT_TYPE = "bitfire.at.davdroid.eelo";
    public static final String GOOGLE_ACCOUNT_TYPE = "bitfire.at.davdroid.google";
    public static final String ACCOUNT_EMAIL_ID_KEY = "email_id";
    public static final String AUTH_TOKEN_TYPE = "oauth2-access-token";
}
+44 −4
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import android.accounts.AccountManager;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
@@ -74,6 +75,7 @@ import io.eelo.mail.R;
import io.eelo.mail.activity.compose.MessageActions;
import io.eelo.mail.activity.misc.ExtendedAsyncTask;
import io.eelo.mail.activity.misc.NonConfigurationInstance;
import io.eelo.mail.activity.setup.GoogleAccountCreator;
import io.eelo.mail.activity.setup.AccountSettings;
import io.eelo.mail.activity.setup.Prefs;
import io.eelo.mail.activity.setup.WelcomeMessage;
@@ -100,6 +102,9 @@ import io.eelo.mail.view.ColorChip;
import de.cketti.library.changelog.ChangeLog;
import timber.log.Timber;

import static io.eelo.mail.account.OAuthConstants.ACCOUNT_EMAIL_ID_KEY;
import static io.eelo.mail.account.OAuthConstants.EELO_ACCOUNT_TYPE;
import static io.eelo.mail.account.OAuthConstants.GOOGLE_ACCOUNT_TYPE;

public class Accounts extends K9ListActivity implements OnItemClickListener {

@@ -397,9 +402,44 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
        if (ACTION_IMPORT_SETTINGS.equals(intent.getAction())) {
            onImport();
        } else if (accounts.size() < 1) {
            // Don't show the welcome message, proceed to account setup instead
	    // WelcomeMessage.showWelcomeMessage(this);
               AccountManager accountManager = AccountManager.get(this);

            try
            {
                android.accounts.Account[] eeloAccounts = accountManager.getAccountsByType(
                        EELO_ACCOUNT_TYPE);
                android.accounts.Account[] googleAccounts = accountManager.getAccountsByType(
                        GOOGLE_ACCOUNT_TYPE);

                if (eeloAccounts.length > 0 || googleAccounts.length > 0)
                {
                    for (android.accounts.Account eeloAccount : eeloAccounts) {
                        String emailId = accountManager.getUserData(eeloAccount,
                                ACCOUNT_EMAIL_ID_KEY);
                        //TODO Add /e/ accounts
                    }

                    for (android.accounts.Account googleAccount : googleAccounts) {
                        String emailId = accountManager.getUserData(googleAccount,
                                ACCOUNT_EMAIL_ID_KEY);
                        GoogleAccountCreator.createAccount(this, emailId);
                    }

                    Toast.makeText(this, "Found accounts signed-in on device",
                            Toast.LENGTH_LONG).show();

                    Accounts.listAccounts(this);
                }
                else
                {
                    AccountSetupActivity.actionNewAccount(this);
                }
            }
            catch (SecurityException e)
            {
                AccountSetupActivity.actionNewAccount(this);
            }

	    finish();
            return;
        }
+43 −0
Original line number Diff line number Diff line
package io.eelo.mail.activity.setup;

import android.content.Context;

import io.eelo.mail.Account;
import io.eelo.mail.K9;
import io.eelo.mail.Preferences;
import io.eelo.mail.controller.MessagingController;

public class GoogleAccountCreator {
    public static void createAccount(Context context, String emailId) {
        Preferences preferences = Preferences.getPreferences(context);

        AccountConfigImpl accountConfig = new AccountConfigImpl(preferences);
        accountConfig.setEmail(emailId);
        accountConfig.setDescription(emailId);
        accountConfig.setTrashFolderName("[Gmail]/Trash");
        accountConfig.setArchiveFolderName("[Gmail]/All Mail");
        accountConfig.setDraftsFolderName("[Gmail]/Drafts");
        accountConfig.setInboxFolderName("INBOX");
        accountConfig.setSentFolderName("[Gmail]/Sent Mail");
        accountConfig.setSpamFolderName("[Gmail]/Spam");
        accountConfig.setAutoExpandFolderName("INBOX");
        accountConfig.setStoreUri("imap+ssl+://XOAUTH2:" + emailId.substring(0,
                emailId.indexOf("@")) + "%40gmail.com:@imap.gmail.com");
        accountConfig.setTransportUri("smtp+ssl+://" + emailId.substring(0,
                emailId.indexOf("@")) + "%40gmail.com::XOAUTH2@smtp.gmail.com");

        Account account = preferences.newAccount();
        account.loadConfig(accountConfig);

        MessagingController.getInstance(context).listFoldersSynchronous(account, true, null);
        MessagingController.getInstance(context)
                .synchronizeMailbox(account, account.getInboxFolderName(), null, null);

        account.save(preferences);

        preferences.setDefaultAccount(account);

        K9.setServicesEnabled(context);
    }
}