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

Commit 2b986f3a authored by Nihar Thakkar's avatar Nihar Thakkar
Browse files

Implement SSO for Google accounts

parent fce9e8fa
Loading
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"/>
+73 −8
Original line number Diff line number Diff line
@@ -3,19 +3,33 @@ package io.eelo.mail.account;

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";
public class K9OAuth2TokenProvider extends OAuth2TokenProvider {

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

    private AccountManager accountManager;
    private String authToken = null;

    private AndroidAccountOAuth2TokenStore gmailTokenProviderWithAccountSystem;
    private K9OAuth2AuthorizationCodeFlowTokenProvider authorizationCodeFlowTokenProvider;
@@ -32,7 +46,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;
@@ -41,13 +55,16 @@ public class K9OAuth2TokenProvider extends OAuth2TokenProvider
        return null;
    }


    @Override
    public String getToken(String email, long timeoutMillis)
            throws AuthenticationFailedException, OAuth2NeedUserPromptException
    {
        Account gmailAccount = getAccountFromManager(email);
            throws AuthenticationFailedException, OAuth2NeedUserPromptException {
        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);
        }
@@ -55,6 +72,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);
+8 −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 −3
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;
@@ -43,6 +44,7 @@ import io.eelo.mail.K9;
import io.eelo.mail.Preferences;
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.controller.MessagingController;
import io.eelo.mail.mail.AuthType;
import io.eelo.mail.mail.TransportUris;
@@ -93,6 +95,10 @@ import io.eelo.mail.mailstore.StorageManager;
import io.eelo.mail.preferences.SettingsExporter;
import de.cketti.library.changelog.ChangeLog;

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
{
@@ -460,9 +466,44 @@ public class Accounts extends K9ListActivity implements OnItemClickListener
        }
        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;
        }
+42 −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);
    }
}