From e62688f0d67edd7119e82a5cbfe6b8815721df2f Mon Sep 17 00:00:00 2001 From: Martin Hibdon Date: Tue, 3 Dec 2013 14:08:34 -0800 Subject: [PATCH] Add configuration for oauth providers There is now an xml file that holds parameters for oauth providers, and entries in providers.xml can specify that they can use oauth. Change-Id: Ibce5b207f83ce9c773f8f713be9e73bb068070ed --- .../emailcommon/VendorPolicyLoader.java | 17 ++++ res/xml/oauth.xml | 61 +++++++++++++ .../activity/setup/AccountSettingsUtils.java | 91 ++++++++++++++++++- 3 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 res/xml/oauth.xml diff --git a/emailcommon/src/com/android/emailcommon/VendorPolicyLoader.java b/emailcommon/src/com/android/emailcommon/VendorPolicyLoader.java index 7221551b4..f78b8a405 100644 --- a/emailcommon/src/com/android/emailcommon/VendorPolicyLoader.java +++ b/emailcommon/src/com/android/emailcommon/VendorPolicyLoader.java @@ -192,6 +192,22 @@ public class VendorPolicyLoader { return result; } + public static class OAuthProvider implements Serializable { + private static final long serialVersionUID = 8511656164616538990L; + + public String id; + public String label; + public String authEndpoint; + public String tokenEndpoint; + public String refreshEndpoint; + public String responseType; + public String redirectUri; + public String scope; + public String clientId; + public String clientSecret; + public String state; + } + public static class Provider implements Serializable { private static final long serialVersionUID = 8511656164616538989L; @@ -207,6 +223,7 @@ public class VendorPolicyLoader { public String outgoingUri; public String outgoingUsername; public String note; + public String oauth; /** * Expands templates in all of the provider fields that support them. Currently, diff --git a/res/xml/oauth.xml b/res/xml/oauth.xml new file mode 100644 index 000000000..f721e615c --- /dev/null +++ b/res/xml/oauth.xml @@ -0,0 +1,61 @@ + + + + + + + + diff --git a/src/com/android/email/activity/setup/AccountSettingsUtils.java b/src/com/android/email/activity/setup/AccountSettingsUtils.java index 550566382..ac85db5f5 100644 --- a/src/com/android/email/activity/setup/AccountSettingsUtils.java +++ b/src/com/android/email/activity/setup/AccountSettingsUtils.java @@ -20,6 +20,7 @@ import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.res.XmlResourceParser; +import android.net.Uri; import android.text.Editable; import android.text.TextUtils; import android.widget.EditText; @@ -29,6 +30,7 @@ import com.android.email.SecurityPolicy; import com.android.email.provider.AccountBackupRestore; import com.android.emailcommon.Logging; import com.android.emailcommon.VendorPolicyLoader; +import com.android.emailcommon.VendorPolicyLoader.OAuthProvider; import com.android.emailcommon.VendorPolicyLoader.Provider; import com.android.emailcommon.provider.Account; import com.android.emailcommon.provider.EmailContent.AccountColumns; @@ -112,7 +114,89 @@ public class AccountSettingsUtils { return cv; } - /** + /** + * Create the request to get the authorization code. + * + * @param context + * @param provider The OAuth provider to register with + * @param emailAddress Email address to send as a hint to the oauth service. + * @return + */ + public static Uri createOAuthRegistrationRequest(final Context context, + final OAuthProvider provider, final String emailAddress) { + final Uri.Builder b = Uri.parse(provider.authEndpoint).buildUpon(); + b.appendQueryParameter("response_type", provider.responseType); + b.appendQueryParameter("client_id", provider.clientId); + b.appendQueryParameter("redirect_uri", provider.redirectUri); + b.appendQueryParameter("scope", provider.scope); + b.appendQueryParameter("state", provider.state); + b.appendQueryParameter("login_hint", emailAddress); + return b.build(); + } + + /** + * Search for a single resource containing known oauth provider definitions. + * + * @param context + * @param id String Id of the oauth provider. + * @return The OAuthProvider if found, null if not. + */ + public static OAuthProvider findOAuthProvider(final Context context, final String id) { + return findOAuthProvider(context, id, R.xml.oauth); + } + + /** + * Search for a single resource containing known oauth provider definitions. + * + * @param context + * @param id String Id of the oauth provider. + * @param resourceId ResourceId of the xml file to search. + * @return The OAuthProvider if found, null if not. + */ + public static OAuthProvider findOAuthProvider(final Context context, final String id, + final int resourceId) { + // TODO: Consider adding a way to cache this file during new account setup, so that we + // don't need to keep loading the file over and over. + // TODO: need a mechanism to get a list of all supported OAuth providers so that we can + // offer the user a choice of who to authenticate with. + try { + final XmlResourceParser xml = context.getResources().getXml(resourceId); + int xmlEventType; + OAuthProvider provider = null; + while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT) { + if (xmlEventType == XmlResourceParser.START_TAG + && "provider".equals(xml.getName())) { + String providerId = getXmlAttribute(context, xml, "id"); + try { + if (TextUtils.equals(id, providerId)) { + provider = new OAuthProvider(); + provider.id = id; + provider.label = getXmlAttribute(context, xml, "label"); + provider.authEndpoint = getXmlAttribute(context, xml, "auth_endpoint"); + provider.tokenEndpoint = getXmlAttribute(context, xml, "token_endpoint"); + provider.refreshEndpoint = getXmlAttribute(context, xml, + "refresh_endpoint"); + provider.responseType = getXmlAttribute(context, xml, "response_type"); + provider.redirectUri = getXmlAttribute(context, xml, "redirect_uri"); + provider.scope = getXmlAttribute(context, xml, "scope"); + provider.state = getXmlAttribute(context, xml, "state"); + provider.clientId = getXmlAttribute(context, xml, "client_id"); + provider.clientSecret = getXmlAttribute(context, xml, "client_secret"); + return provider; + } + } catch (IllegalArgumentException e) { + LogUtils.w(Logging.LOG_TAG, "providers line: " + xml.getLineNumber() + + "; Domain contains multiple globals"); + } + } + } + } catch (Exception e) { + LogUtils.e(Logging.LOG_TAG, "Error while trying to load provider settings.", e); + } + return null; + } + + /** * Search the list of known Email providers looking for one that matches the user's email * domain. We check for vendor supplied values first, then we look in providers_product.xml, * and finally by the entries in platform providers.xml. This provides a nominal override @@ -158,6 +242,11 @@ public class AccountSettingsUtils { provider.label = getXmlAttribute(context, xml, "label"); provider.domain = domain.toLowerCase(); provider.note = getXmlAttribute(context, xml, "note"); + // TODO: Maybe this should actually do a lookup of the OAuth provider + // here, and keep a pointer to it rather than a textual key. + // To do this probably requires caching oauth.xml, otherwise the lookup + // is expensive and likely to happen repeatedly. + provider.oauth = getXmlAttribute(context, xml, "oauth"); } } catch (IllegalArgumentException e) { LogUtils.w(Logging.LOG_TAG, "providers line: " + xml.getLineNumber() +