From 3e9e50e4025d14710144948c869c0c5e1ad3f48a Mon Sep 17 00:00:00 2001 From: Anton Korobko Date: Fri, 2 Nov 2018 19:32:32 +0200 Subject: [PATCH 1/2] SSO draft --- OpenEdXMobile/AndroidManifest.xml | 82 ++-- OpenEdXMobile/build.gradle | 17 +- OpenEdXMobile/default_config/config.yaml | 7 +- .../res/layout/sso_login_activity.xml | 31 ++ .../etraining/authentication/LoginAPI.java | 28 ++ .../authentication/SSOAuthActivity.java | 365 ++++++++++++++++++ .../http/constants/ApiConstants.java | 5 + .../etraining/module/analytics/Analytics.java | 1 + .../etraining/module/prefs/LoginPrefs.java | 9 +- .../etraining/module/prefs/PrefManager.java | 3 +- .../moe/etraining/social/SocialFactory.java | 5 +- .../etraining/social/SocialLoginDelegate.java | 27 +- .../sa/gov/moe/etraining/util/Config.java | 16 + .../view/MainTabsDashboardFragment.java | 3 + .../sa/gov/moe/etraining/view/Router.java | 3 +- build.gradle | 1 + 16 files changed, 557 insertions(+), 46 deletions(-) create mode 100644 OpenEdXMobile/res/layout/sso_login_activity.xml create mode 100644 OpenEdXMobile/src/main/java/sa/gov/moe/etraining/authentication/SSOAuthActivity.java diff --git a/OpenEdXMobile/AndroidManifest.xml b/OpenEdXMobile/AndroidManifest.xml index 58cad7c..2613324 100644 --- a/OpenEdXMobile/AndroidManifest.xml +++ b/OpenEdXMobile/AndroidManifest.xml @@ -36,46 +36,64 @@ android:supportsRtl="${supportsRtl}" android:theme="@style/AppTheme"> + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + diff --git a/OpenEdXMobile/build.gradle b/OpenEdXMobile/build.gradle index a743722..b4e55e7 100644 --- a/OpenEdXMobile/build.gradle +++ b/OpenEdXMobile/build.gradle @@ -2,6 +2,7 @@ import org.edx.builder.TaskHelper buildscript { repositories { +// google() jcenter() mavenCentral() maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } @@ -138,6 +139,16 @@ dependencies { compile 'com.squareup.phrase:phrase:1.1.0' compile 'com.squareup.okhttp3:okhttp:3.0.1' compile 'com.squareup.okhttp3:logging-interceptor:3.0.1' + + // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore +// compile group: 'org.apache.httpcomponents', name: 'httpcore', version: '4.4.10' + // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient +// compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.6' + // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient-android +// compile group: 'org.apache.httpcomponents', name: 'httpclient-android', version: '4.3.5.1' + + + /* Exclude dependencies defined statically at the top- * level, to prevent them from being resolved to the * latest version as a result of dynamic version @@ -267,12 +278,12 @@ android { applicationId "sa.gov.moe.etraining" // minimum version is Android 4.1 minSdkVersion 16 - targetSdkVersion 21 + targetSdkVersion 28 // versionCode getVersionCode() - versionCode 2150101 + versionCode 2150102 // versionCode getVersionCode() - versionName "2.15.01.01" + versionName "2.15.01.02" renderscriptTargetApi 22 renderscriptSupportModeEnabled true diff --git a/OpenEdXMobile/default_config/config.yaml b/OpenEdXMobile/default_config/config.yaml index 3904a3b..d2955ab 100644 --- a/OpenEdXMobile/default_config/config.yaml +++ b/OpenEdXMobile/default_config/config.yaml @@ -2,7 +2,7 @@ API_HOST_URL: 'https://edxmoe.ilearnme.com' ENVIRONMENT_DISPLAY_NAME: 'edxmoe.ilearnme.com' PLATFORM_NAME: 'MOE' PLATFORM_DESTINATION_NAME: 'edxmoe.ilearnme.com' -FEEDBACK_EMAIL_ADDRESS: 'info@raccoongang.com' +FEEDBACK_EMAIL_ADDRESS: 'support@ilearn.ws' OAUTH_ENFORCE_SECURE: true PUSH_NOTIFICATIONS: true USER_PROFILES_ENABLED: true @@ -12,4 +12,7 @@ OAUTH_CLIENT_ID: '0d7d01a1f2a866866285' MY_VIDEOS_ENABLED: true DISCUSSIONS_ENABLED: true COURSE_VIDEOS_ENABLED: true -COURSE_ENROLLMENT : { TYPE : 'native', SEARCH_BAR_ENABLED : true } \ No newline at end of file +COURSE_ENROLLMENT : { TYPE : 'native', SEARCH_BAR_ENABLED : true } +SSO_AUTH_URL: 'https://edxmoe.ilearnme.com/oauth2/authorize/?scope=openid+profile+email+permissions&state=xyz&redirect_uri=https://edxmoe.ilearnme.com/api/mobile/v0.5/?app=ios&response_type=code&client_id=0d7d01a1f2a866866285' +ACCESS_TOKEN_REQUEST_URL: 'https://edxmoe.ilearnme.com/oauth2/access_token' +ACCESS_TOKEN_REQUEST_DATA: 'client_id=0d7d01a1f2a866866285&client_secret=be3a30b12ca7f198431ae670c7160beef0c2466f&grant_type=authorization_code&code=' \ No newline at end of file diff --git a/OpenEdXMobile/res/layout/sso_login_activity.xml b/OpenEdXMobile/res/layout/sso_login_activity.xml new file mode 100644 index 0000000..c7fb6a2 --- /dev/null +++ b/OpenEdXMobile/res/layout/sso_login_activity.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/authentication/LoginAPI.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/authentication/LoginAPI.java index 0626601..e4c4a21 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/authentication/LoginAPI.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/authentication/LoginAPI.java @@ -3,6 +3,7 @@ import android.os.Bundle; import android.support.annotation.NonNull; +import com.google.android.gms.auth.api.Auth; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import com.google.inject.Inject; @@ -96,6 +97,11 @@ public AuthResponse logInUsingGoogle(String accessToken) throws Exception { return finishSocialLogIn(accessToken, LoginPrefs.AuthBackend.GOOGLE); } + @NonNull + public AuthResponse logInUsingMoe(String accessToken, AuthResponse responseObject) throws Exception { + return finishOauthlLogIn(accessToken, responseObject, LoginPrefs.AuthBackend.MOE); + } + @NonNull private AuthResponse finishSocialLogIn(@NonNull String accessToken, @NonNull LoginPrefs.AuthBackend authBackend) throws Exception { final String backend = ApiConstants.getOAuthGroupIdForAuthBackend(authBackend); @@ -115,6 +121,28 @@ private AuthResponse finishSocialLogIn(@NonNull String accessToken, @NonNull Log return data; } + @NonNull + private AuthResponse finishOauthlLogIn(@NonNull String accessToken, AuthResponse responseObject, @NonNull LoginPrefs.AuthBackend authBackend) throws Exception { + final String backend = ApiConstants.getOAuthGroupIdForAuthBackend(authBackend); +// final Response response = loginService.exchangeAccessToken(accessToken, config.getOAuthClientId(), backend).execute(); + + +// if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) { +//// TODO: Introduce a more explicit error code to indicate that an account is not linked. +// throw new AccountNotLinkedException(); +// } +// if (!response.isSuccessful()) { +// throw new HttpStatusException(response); +// } + final AuthResponse data = responseObject; +// if (data.error != null && data.error.equals(Integer.toString(HttpURLConnection.HTTP_UNAUTHORIZED))) { +// throw new AccountNotLinkedException(); +// } + finishLogIn(data, authBackend, ""); + return data; + } + + private void finishLogIn(@NonNull AuthResponse response, @NonNull LoginPrefs.AuthBackend authBackend, @NonNull String usernameUsedToLogIn) throws Exception { loginPrefs.storeAuthTokenResponse(response, authBackend); try { diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/authentication/SSOAuthActivity.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/authentication/SSOAuthActivity.java new file mode 100644 index 0000000..403a66f --- /dev/null +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/authentication/SSOAuthActivity.java @@ -0,0 +1,365 @@ +package sa.gov.moe.etraining.authentication; + +import android.content.DialogInterface; +import android.databinding.DataBindingUtil; +import android.graphics.Bitmap; +import android.os.Bundle; +import android.os.StrictMode; +import android.provider.SearchRecentSuggestions; +import android.support.annotation.NonNull; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; + +import com.google.inject.Inject; + +import org.json.JSONException; +import org.json.JSONObject; + +import okhttp3.Headers; +import okhttp3.MultipartBody; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import roboguice.RoboGuice; +import roboguice.inject.RoboInjector; +import sa.gov.moe.etraining.R; +import sa.gov.moe.etraining.base.BaseFragmentActivity; +import sa.gov.moe.etraining.databinding.ActivityLoginBinding; +import sa.gov.moe.etraining.exception.LoginErrorMessage; +import sa.gov.moe.etraining.exception.LoginException; +import sa.gov.moe.etraining.http.HttpStatus; +import sa.gov.moe.etraining.http.HttpStatusException; +import sa.gov.moe.etraining.http.constants.ApiConstants; +import sa.gov.moe.etraining.model.api.ProfileModel; +import sa.gov.moe.etraining.module.analytics.AnalyticsRegistry; +import sa.gov.moe.etraining.module.prefs.LoginPrefs; +import sa.gov.moe.etraining.module.prefs.PrefManager; +import sa.gov.moe.etraining.social.ISocial; +import sa.gov.moe.etraining.social.SocialFactory; +import sa.gov.moe.etraining.social.SocialLoginDelegate; +import sa.gov.moe.etraining.social.SocialProvider; +import sa.gov.moe.etraining.social.google.GoogleOauth2; +import sa.gov.moe.etraining.social.google.GoogleProvider; +import sa.gov.moe.etraining.task.Task; +import sa.gov.moe.etraining.util.AppStoreUtils; +import sa.gov.moe.etraining.util.Config; +import sa.gov.moe.etraining.util.StandardCharsets; +import sa.gov.moe.etraining.util.images.ErrorUtils; +import sa.gov.moe.etraining.util.observer.BasicObservable; +import sa.gov.moe.etraining.view.LoginActivity; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashMap; +import java.util.Iterator; + +import javax.net.ssl.HttpsURLConnection; + +import static sa.gov.moe.etraining.http.util.CallUtil.executeStrict; + + +public class SSOAuthActivity extends BaseFragmentActivity + implements SocialLoginDelegate.MobileLoginCallback { + + @Inject + private LoginPrefs loginPrefs; + private static final String TAG = "TAG"; + public static String SSOAuthUrl; + public static String accessTokenRequestUrl; + public static String accessTokenRequestData; + + private final String USER_AGENT = "Mozilla/5.0"; + + private final OkHttpClient client = new OkHttpClient(); + private SocialLoginDelegate socialLoginDelegate; + + private ActivityLoginBinding activityLoginBinding; + + private ISocial google, facebook; + + @NonNull + private final LoginService loginService = this.loginService; + + @NonNull + private final BasicObservable logInEvents = new BasicObservable<>(); + + @NonNull + private final AnalyticsRegistry analyticsRegistry = this.analyticsRegistry; + private WebView htmlWebView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + setContentView(R.layout.sso_login_activity); + + if (android.os.Build.VERSION.SDK_INT > 9) { + StrictMode.ThreadPolicy policy = + new StrictMode.ThreadPolicy.Builder().permitAll().build(); + StrictMode.setThreadPolicy(policy); + } + + socialLoginDelegate = new SocialLoginDelegate(this, savedInstanceState, this, environment.getConfig(), environment.getLoginPrefs()); + activityLoginBinding = DataBindingUtil.setContentView(this, R.layout.sso_login_activity); + + final RoboInjector injector = RoboGuice.getInjector(this); + final Config config = injector.getInstance(Config.class); + SSOAuthUrl = config.getSSOHostURL(); + accessTokenRequestUrl = config.getAccessTokenRequestUrl(); + accessTokenRequestData = config.getAccessTokenRequestData(); + + htmlWebView = (WebView)findViewById(R.id.login_web_view); + htmlWebView.setWebViewClient(new CustomWebViewClient()); + htmlWebView.clearCache(true); + htmlWebView.clearHistory(); + htmlWebView.loadUrl("about:blank"); + WebSettings webSetting = htmlWebView.getSettings(); + webSetting.setJavaScriptEnabled(true); + webSetting.setDisplayZoomControls(true); + htmlWebView.loadUrl(SSOAuthUrl); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.course_dashboard_menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + + //noinspection SimplifiableIfStatement + if (id == R.id.login_web_view) { + return true; + } + + return super.onOptionsItemSelected(item); + } + + @Override public void onBackPressed() { + WebView htmlWebView = (WebView)findViewById(R.id.login_web_view); + if(htmlWebView.canGoBack()) { + htmlWebView.goBack(); + } else { + super.onBackPressed(); + } + } + + private void sendPost (String accessCode) throws Exception { + + System.out.println("POST >>> >>> >>>"); + URL url = new URL(accessTokenRequestUrl); + + System.out.println("URL: " + url.toString()); + HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); + conn.setReadTimeout(10000); + conn.setConnectTimeout(15000); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + + conn.setDoInput(true); + conn.setDoOutput(true); + conn.connect(); + + OutputStream os = conn.getOutputStream(); + BufferedWriter writer = new BufferedWriter( + new OutputStreamWriter(os, "UTF-8")); + writer.write( accessTokenRequestData + accessCode); + writer.flush(); + writer.close(); + if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) { + Log.d(TAG, "HTTPS AUTH TOKEN response code is " + conn.getResponseCode()); + } + + BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String decodedString; + StringBuilder stringBuilder = new StringBuilder(); + while ((decodedString = in.readLine()) != null) { + stringBuilder.append(decodedString); + } + + String accessTokenRequestResponse = stringBuilder.toString(); + System.out.println("RESPONSE: " + accessTokenRequestResponse); + os.close(); + in.close(); + conn.disconnect(); + destroyWebView(); + if (accessTokenRequestResponse.contains("access_token")) { + HashMap responseMap = jsonToMap(accessTokenRequestResponse); + + String access_token = (String) responseMap.get("access_token"); + AuthResponse responseObject = new AuthResponse(); + + responseObject.access_token = (String) responseMap.get("access_token"); + responseObject.refresh_token = (String) responseMap.get("refresh_token"); + responseObject.expires_in = Long.valueOf((String) responseMap.get("expires_in")); + responseObject.scope = (String) responseMap.get("scope"); + responseObject.token_type = (String) responseMap.get("token_type"); + +// Long id = 1000L; +// String username = "a"; +// String email = "a@a.com"; +// String name = "aaaa"; +// ProfileModel profileModel = new ProfileModel(); +// profileModel.username = username; +// profileModel.email = email; +// profileModel.name = name; +// profileModel.id = id; +// responseObject.profile = profileModel; + + socialLoginDelegate.onOauthLoginSuccess(access_token, responseObject, PrefManager.Value.BACKEND_MOE); + +// environment.getRouter().showMainDashboard(this); + } + + } + + public void destroyWebView() { + +// mWebContainer.removeAllViews(); + + htmlWebView.clearHistory(); + htmlWebView.clearCache(true); + htmlWebView.loadUrl("about:blank"); + htmlWebView.onPause(); + htmlWebView.removeAllViews(); + htmlWebView.destroyDrawingCache(); + htmlWebView.pauseTimers(); + htmlWebView.destroy(); + htmlWebView = null; + } + + public static HashMap jsonToMap(String t) throws JSONException { + + HashMap map = new HashMap<>(); + JSONObject jObject = new JSONObject(t); + Iterator keys = jObject.keys(); + + while( keys.hasNext() ){ + String key = (String)keys.next(); + String value = jObject.getString(key); + map.put(key, value); + } + return map; + } + + + private class CustomWebViewClient extends WebViewClient{ + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + super.onPageStarted(view, url, favicon); + Log.d("WebView", "your current url when webpage loading... " + url); + if (url.contains("code=")) { + String authCode = url.split("code=", 2)[1]; + Log.d("WebView", "IT's ALIVE!!!" + authCode); + try { + sendPost(authCode); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Override + public void onPageFinished(WebView view, String url) { + Log.d("WebView", "your current url when webpage loading.. finish " + url); + super.onPageFinished(view, url); + } + + @Override + public void onLoadResource(WebView view, String url) { + // TODO Auto-generated method stub + super.onLoadResource(view, url); + } + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + view.loadUrl(url); + return true; + } + } + + + @Override + protected void onResume() { + super.onResume(); + if (environment.getLoginPrefs().getUsername() != null) { + finish(); + environment.getRouter().showMainDashboard(this); + } + } + + + /** + * Starts fetching profile of the user after login by Facebook or Google. + * + * @param accessToken + * @param backend + */ + public void onSocialLoginSuccess(String accessToken, String backend, Task task) { + tryToSetUIInteraction(false); + task.setProgressDialog(findViewById(R.id.progress_indicator)); + } + + public void onUserLoginSuccess(ProfileModel profile) { + setResult(RESULT_OK); + finish(); + environment.getRouter().showMainDashboard(this); + if (!environment.getConfig().isRegistrationEnabled()) { + environment.getRouter().showMainDashboard(this); + } + } + + public void onUserLoginFailure(Exception ex, String accessToken, String backend) { + tryToSetUIInteraction(true); + + if (ex != null && ex instanceof LoginException) { + LoginErrorMessage errorMessage = (((LoginException) ex).getLoginErrorMessage()); + showAlertDialog( + errorMessage.getMessageLine1(), + (errorMessage.getMessageLine2() != null) ? + errorMessage.getMessageLine2() : getString(R.string.login_failed)); + } else if (ex != null && ex instanceof HttpStatusException && + ((HttpStatusException) ex).getStatusCode() == HttpStatus.UPGRADE_REQUIRED) { + SSOAuthActivity.this.showAlertDialog(null, + getString(R.string.app_version_unsupported_login_msg), + getString(R.string.label_update), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + AppStoreUtils.openAppInAppStore(SSOAuthActivity.this); + } + }, getString(android.R.string.cancel), null); + } else { + showAlertDialog(getString(R.string.login_error), ErrorUtils.getErrorMessage(ex, SSOAuthActivity.this)); + logger.error(ex); + } + } + + @Override + protected void onDestroy() { +// htmlWebView.destroy(); +// htmlWebView = null; + super.onDestroy(); + } + +} \ No newline at end of file diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/http/constants/ApiConstants.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/http/constants/ApiConstants.java index 344a526..247bda7 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/http/constants/ApiConstants.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/http/constants/ApiConstants.java @@ -28,6 +28,8 @@ public class ApiConstants { public static final String URL_PASSWORD_RESET = "/password_reset/"; public static final String URL_EXCHANGE_ACCESS_TOKEN = "/oauth2/exchange_access_token/{" + GROUP_ID + "}/"; +// public static final String URL_EXCHANGE_ACCESS_TOKEN = "/oauth2/exchange_access_token/{" + GROUP_ID + "}"; +// public static final String URL_EXCHANGE_ACCESS_TOKEN = "/oauth2/access_token{" + GROUP_ID + "}"; public static final String URL_REVOKE_TOKEN = "/oauth2/revoke_token/"; @@ -62,6 +64,9 @@ public static String getOAuthGroupIdForAuthBackend(@NonNull LoginPrefs.AuthBacke case GOOGLE: { return PrefManager.Value.BACKEND_GOOGLE; } + case MOE: { + return PrefManager.Value.BACKEND_MOE; + } default: { throw new IllegalArgumentException(authBackend.name()); } diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/module/analytics/Analytics.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/module/analytics/Analytics.java index 0a06f32..cf2642f 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/module/analytics/Analytics.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/module/analytics/Analytics.java @@ -450,6 +450,7 @@ interface Values { String PASSWORD = "Password"; String FACEBOOK = "Facebook"; String GOOGLE = "Google"; + String MOE = "Moe"; String DOWNLOAD_MODULE = "downloadmodule"; String VIDEO_LOADED = "edx.video.loaded"; String VIDEO_PLAYED = "edx.video.played"; diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/module/prefs/LoginPrefs.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/module/prefs/LoginPrefs.java index 76b0d13..f0a07f8 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/module/prefs/LoginPrefs.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/module/prefs/LoginPrefs.java @@ -23,7 +23,8 @@ public class LoginPrefs { public enum AuthBackend { PASSWORD, FACEBOOK, - GOOGLE + GOOGLE, + MOE } @NonNull @@ -42,6 +43,10 @@ public void storeAuthTokenResponse(@NonNull AuthResponse response, @NonNull Auth pref.put(PrefManager.Key.ANALYTICS_KEY_BACKEND, analyticsTokenFromAuthBackend(backend)); } + public void storeOauthTokenResponse(@NonNull AuthResponse response) { + pref.put(PrefManager.Key.AUTH_JSON, gson.toJson(response)); + } + public void clearAuthTokenResponse() { pref.put(PrefManager.Key.AUTH_JSON, null); pref.put(PrefManager.Key.ANALYTICS_KEY_BACKEND, null); @@ -173,6 +178,8 @@ private static String analyticsTokenFromAuthBackend(@NonNull AuthBackend backend return Analytics.Values.FACEBOOK; case GOOGLE: return Analytics.Values.GOOGLE; + case MOE: + return Analytics.Values.MOE; default: throw new IllegalArgumentException(backend.name()); } diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/module/prefs/PrefManager.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/module/prefs/PrefManager.java index b493314..f9072f0 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/module/prefs/PrefManager.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/module/prefs/PrefManager.java @@ -307,7 +307,8 @@ public static final class Value { * These values are used in API endpoint */ public static final String BACKEND_FACEBOOK = "facebook"; - public static final String BACKEND_GOOGLE = "google-oauth2"; + public static final String BACKEND_GOOGLE = ""; + public static final String BACKEND_MOE = "moe"; } /** diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/social/SocialFactory.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/social/SocialFactory.java index 913dc26..b50e832 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/social/SocialFactory.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/social/SocialFactory.java @@ -16,7 +16,8 @@ public class SocialFactory { //TODO - we should create a central place for application wide constants. public static enum SOCIAL_SOURCE_TYPE { - TYPE_UNKNOWN(-1, "unknown"), TYPE_GOOGLE(100, "google-oauth2"), TYPE_FACEBOOK(101,"facebook"); + TYPE_UNKNOWN(-1, "unknown"), TYPE_GOOGLE(100, ""), TYPE_FACEBOOK(101,"facebook"); +// TYPE_UNKNOWN(-1, "unknown"), TYPE_GOOGLE(100, "google-oauth2"), TYPE_FACEBOOK(101,"facebook"); private int code; private String value; @@ -29,7 +30,7 @@ private SOCIAL_SOURCE_TYPE(int code, String value) { public static SOCIAL_SOURCE_TYPE fromString(String source){ if ( "facebook".equalsIgnoreCase( source ) ) return TYPE_FACEBOOK; - if ( "google-oauth2".equalsIgnoreCase( source ) || "google".equalsIgnoreCase( source ) ) + if ( "".equalsIgnoreCase( source ) || "google".equalsIgnoreCase( source ) ) return TYPE_GOOGLE; return TYPE_UNKNOWN; } diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/social/SocialLoginDelegate.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/social/SocialLoginDelegate.java index 6feb5dc..b5a304a 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/social/SocialLoginDelegate.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/social/SocialLoginDelegate.java @@ -127,7 +127,15 @@ else if (socialType == SocialFactory.SOCIAL_SOURCE_TYPE.TYPE_GOOGLE) */ public void onSocialLoginSuccess(String accessToken, String backend) { loginPrefs.saveSocialLoginToken(accessToken, backend); - Task task = new ProfileTask(activity, accessToken, backend); + AuthResponse responseObject = new AuthResponse(); + Task task = new ProfileTask(activity, accessToken, responseObject, backend); + callback.onSocialLoginSuccess(accessToken, backend, task); + task.execute(); + } + + public void onOauthLoginSuccess(String accessToken, AuthResponse responseObject, String backend) { + loginPrefs.saveSocialLoginToken(accessToken, backend); + Task task = new ProfileTask(activity, accessToken, responseObject, backend); callback.onSocialLoginSuccess(accessToken, backend, task); task.execute(); } @@ -157,18 +165,21 @@ public void getUserInfo(SocialFactory.SOCIAL_SOURCE_TYPE socialType, String acce } - private class ProfileTask extends Task { + public class ProfileTask extends Task { private String accessToken; private String backend; + private AuthResponse responseObject; + @Inject LoginAPI loginAPI; - public ProfileTask(Context context, String accessToken, String backend) { + public ProfileTask(Context context, String accessToken, AuthResponse responseObject, String backend) { super(context); this.accessToken = accessToken; this.backend = backend; + this.responseObject = responseObject; } @Override @@ -204,7 +215,15 @@ public ProfileModel call() throws Exception { CharSequence desc = ResourceUtil.getFormattedString(context.getResources(), R.string.error_account_not_linked_desc_google, descParams); throw new LoginException(new LoginErrorMessage(title.toString(), desc.toString())); } - } else { + } else if (backend.equalsIgnoreCase(PrefManager.Value.BACKEND_MOE)){ + try { + auth = loginAPI.logInUsingMoe(accessToken, responseObject); + } catch (LoginAPI.AccountNotLinkedException e) { + CharSequence title = ResourceUtil.getFormattedString(context.getResources(), R.string.error_account_not_linked_title_google, descParams); + CharSequence desc = ResourceUtil.getFormattedString(context.getResources(), R.string.error_account_not_linked_desc_google, descParams); + throw new LoginException(new LoginErrorMessage(title.toString(), desc.toString())); + } + } else { throw new IllegalArgumentException("Unknown backend: " + backend); } return auth.profile; diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/util/Config.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/util/Config.java index e78fb07..cf94b0f 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/util/Config.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/util/Config.java @@ -44,6 +44,10 @@ public class Config { private static final String SPEED_TEST_ENABLED = "SPEED_TEST_ENABLED"; private static final String APP_UPDATE_URIS = "APP_UPDATE_URIS"; private static final String ORGANIZATION_CODE = "ORGANIZATION_CODE"; + private static final String SSO_AUTH_URL = "SSO_AUTH_URL"; + private static final String ACCESS_TOKEN_REQUEST_URL = "ACCESS_TOKEN_REQUEST_URL"; + private static final String ACCESS_TOKEN_REQUEST_DATA = "ACCESS_TOKEN_REQUEST_DATA"; + /* Composite configuration keys */ private static final String COURSE_ENROLLMENT = "COURSE_ENROLLMENT"; @@ -467,6 +471,18 @@ public String getApiHostURL() { return getString(API_HOST_URL); } + public String getSSOHostURL() { + return getString(SSO_AUTH_URL); + } + + public String getAccessTokenRequestUrl() { + return getString(ACCESS_TOKEN_REQUEST_URL); + } + + public String getAccessTokenRequestData() { + return getString(ACCESS_TOKEN_REQUEST_DATA); + } + // User facing name of the platform like "edX" public String getPlatformName() { return getString(PLATFORM_NAME); diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/MainTabsDashboardFragment.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/MainTabsDashboardFragment.java index a91341e..d95187f 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/MainTabsDashboardFragment.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/MainTabsDashboardFragment.java @@ -102,10 +102,13 @@ public void onAttach(Context context) { } public void sendGetUpdatedAccountCall() { +// String userName = "1017416882"; getAccountCall = userService.getAccount(profile.username); +// getAccountCall = userService.getAccount(userName); getAccountCall.enqueue(new UserAPI.AccountDataUpdatedCallback( getActivity(), profile.username, +// userName, null, // Disable global loading indicator null)); // No place to show an error notification } diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/Router.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/Router.java index bbfcc05..75164fc 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/Router.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/Router.java @@ -19,6 +19,7 @@ import de.greenrobot.event.EventBus; import sa.gov.moe.etraining.authentication.LoginAPI; +import sa.gov.moe.etraining.authentication.SSOAuthActivity; import sa.gov.moe.etraining.course.CourseDetail; import sa.gov.moe.etraining.discussion.DiscussionComment; import sa.gov.moe.etraining.discussion.DiscussionThread; @@ -116,7 +117,7 @@ public void showLaunchScreen(Context context) { } public void showSplashScreen(Context context) { - final Intent launchIntent = new Intent(context, SplashActivity.class); + final Intent launchIntent = new Intent(context, SSOAuthActivity.class); launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); context.startActivity(launchIntent); } diff --git a/build.gradle b/build.gradle index 4afce4b..94061af 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { +// google() jcenter() // This is the default repo mavenCentral() // This is the Maven Central repo } From ada847dbc658ce5bb2f67d95cfaf284fcaf25470 Mon Sep 17 00:00:00 2001 From: Anton Korobko Date: Mon, 1 Apr 2019 13:22:04 +0300 Subject: [PATCH 2/2] ID update, cleanup --- OpenEdXMobile/default_config/config.yaml | 16 ++++++++-------- .../sa/gov/moe/etraining/OkHttpClientProvider.kt | 3 +++ .../http/provider/OkHttpClientProvider.java | 5 +++++ .../view/ShowAboutPageActivityFragment.java | 2 +- .../view/ShowContactsPageActivityFragment.java | 2 +- .../view/ShowFAQPageActivityFragment.java | 2 +- 6 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 OpenEdXMobile/src/main/java/sa/gov/moe/etraining/OkHttpClientProvider.kt diff --git a/OpenEdXMobile/default_config/config.yaml b/OpenEdXMobile/default_config/config.yaml index d2955ab..87246c0 100644 --- a/OpenEdXMobile/default_config/config.yaml +++ b/OpenEdXMobile/default_config/config.yaml @@ -1,18 +1,18 @@ -API_HOST_URL: 'https://edxmoe.ilearnme.com' -ENVIRONMENT_DISPLAY_NAME: 'edxmoe.ilearnme.com' +API_HOST_URL: 'https://etraining.moe.gov.sa' +ENVIRONMENT_DISPLAY_NAME: 'etraining.moe.gov.sa' PLATFORM_NAME: 'MOE' -PLATFORM_DESTINATION_NAME: 'edxmoe.ilearnme.com' +PLATFORM_DESTINATION_NAME: 'etraining.moe.gov.sa' FEEDBACK_EMAIL_ADDRESS: 'support@ilearn.ws' -OAUTH_ENFORCE_SECURE: true +#OAUTH_ENFORCE_SECURE: true PUSH_NOTIFICATIONS: true USER_PROFILES_ENABLED: true DEBUG: true -OAUTH_CLIENT_ID: '0d7d01a1f2a866866285' +OAUTH_CLIENT_ID: '2c03c507cadfe54ac028' # PROD #ENABLE_MOBILE_REST_API: true MY_VIDEOS_ENABLED: true DISCUSSIONS_ENABLED: true COURSE_VIDEOS_ENABLED: true COURSE_ENROLLMENT : { TYPE : 'native', SEARCH_BAR_ENABLED : true } -SSO_AUTH_URL: 'https://edxmoe.ilearnme.com/oauth2/authorize/?scope=openid+profile+email+permissions&state=xyz&redirect_uri=https://edxmoe.ilearnme.com/api/mobile/v0.5/?app=ios&response_type=code&client_id=0d7d01a1f2a866866285' -ACCESS_TOKEN_REQUEST_URL: 'https://edxmoe.ilearnme.com/oauth2/access_token' -ACCESS_TOKEN_REQUEST_DATA: 'client_id=0d7d01a1f2a866866285&client_secret=be3a30b12ca7f198431ae670c7160beef0c2466f&grant_type=authorization_code&code=' \ No newline at end of file +SSO_AUTH_URL: 'https://etraining.moe.gov.sa/oauth2/authorize/?scope=openid+profile+email+permissions&state=xyz&redirect_uri=https://etraining.moe.gov.sa/api/mobile/v0.5/?app=android&response_type=code&client_id=2c03c507cadfe54ac028' +ACCESS_TOKEN_REQUEST_URL: 'https://etraining.moe.gov.sa/oauth2/access_token' +ACCESS_TOKEN_REQUEST_DATA: 'client_id=2c03c507cadfe54ac028&client_secret=b20556f9854dda7cdb29c45aee9c1d01bcc0331e&grant_type=authorization_code&code=' \ No newline at end of file diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/OkHttpClientProvider.kt b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/OkHttpClientProvider.kt new file mode 100644 index 0000000..71cd6b8 --- /dev/null +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/OkHttpClientProvider.kt @@ -0,0 +1,3 @@ +package sa.gov.moe.etraining + +public interface OkHttpClientProvider \ No newline at end of file diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/http/provider/OkHttpClientProvider.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/http/provider/OkHttpClientProvider.java index 0eab171..472edf1 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/http/provider/OkHttpClientProvider.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/http/provider/OkHttpClientProvider.java @@ -7,10 +7,12 @@ import com.google.inject.Provider; import com.google.inject.Singleton; +import okhttp3.Protocol; import sa.gov.moe.etraining.BuildConfig; import sa.gov.moe.etraining.R; import java.io.File; +import java.util.ArrayList; import java.util.List; import okhttp3.Cache; @@ -70,6 +72,9 @@ private synchronized OkHttpClient get(boolean isOAuthBased, boolean usesOfflineC OkHttpClient client = clients[index]; if (client == null) { final OkHttpClient.Builder builder = new OkHttpClient.Builder(); + List protocols = new ArrayList(); + protocols.add(Protocol.HTTP_1_1); + builder.protocols(protocols); List interceptors = builder.interceptors(); if (usesOfflineCache) { final File cacheDirectory = new File(context.getFilesDir(), "http-cache"); diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/ShowAboutPageActivityFragment.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/ShowAboutPageActivityFragment.java index 4a739f0..29ea0f3 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/ShowAboutPageActivityFragment.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/ShowAboutPageActivityFragment.java @@ -20,7 +20,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, View v=inflater.inflate(R.layout.fragment_about, container, false); mWebView = (WebView) v.findViewById(R.id.webview); - mWebView.loadUrl("https://edxmoe.ilearnme.com/about"); + mWebView.loadUrl("https://etraining.moe.gov.sa//about"); // Enable Javascript WebSettings webSettings = mWebView.getSettings(); diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/ShowContactsPageActivityFragment.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/ShowContactsPageActivityFragment.java index fff5e46..c365b6f 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/ShowContactsPageActivityFragment.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/ShowContactsPageActivityFragment.java @@ -20,7 +20,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, View v=inflater.inflate(R.layout.fragment_about, container, false); mWebView = (WebView) v.findViewById(R.id.webview); - mWebView.loadUrl("https://edxmoe.ilearnme.com/contact"); + mWebView.loadUrl("https://etraining.moe.gov.sa//contact"); // Enable Javascript WebSettings webSettings = mWebView.getSettings(); diff --git a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/ShowFAQPageActivityFragment.java b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/ShowFAQPageActivityFragment.java index 1e5dd96..1576ea2 100644 --- a/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/ShowFAQPageActivityFragment.java +++ b/OpenEdXMobile/src/main/java/sa/gov/moe/etraining/view/ShowFAQPageActivityFragment.java @@ -20,7 +20,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, View v=inflater.inflate(R.layout.fragment_about, container, false); mWebView = (WebView) v.findViewById(R.id.webview); - mWebView.loadUrl("https://edxmoe.ilearnme.com/faq"); + mWebView.loadUrl("https://etraining.moe.gov.sa/faq"); // Enable Javascript WebSettings webSettings = mWebView.getSettings();