001package com.gigya.android.sdk.providers.provider; 002 003import android.app.Activity; 004import android.content.Context; 005import android.util.Pair; 006 007import com.gigya.android.sdk.Config; 008import com.gigya.android.sdk.Gigya; 009import com.gigya.android.sdk.GigyaLogger; 010import com.gigya.android.sdk.account.IAccountService; 011import com.gigya.android.sdk.api.GigyaApiResponse; 012import com.gigya.android.sdk.api.IBusinessApiService; 013import com.gigya.android.sdk.network.adapter.RestAdapter; 014import com.gigya.android.sdk.persistence.IPersistenceService; 015import com.gigya.android.sdk.session.ISessionService; 016import com.gigya.android.sdk.session.SessionInfo; 017import com.gigya.android.sdk.ui.WebLoginActivity; 018import com.gigya.android.sdk.utils.AuthUtils; 019import com.gigya.android.sdk.utils.UrlUtils; 020 021import org.json.JSONObject; 022 023import java.util.Map; 024import java.util.TreeMap; 025 026public class WebLoginProvider extends Provider { 027 028 private static final String LOG_TAG = "WebLoginProvider"; 029 030 final private ISessionService _sessionService; 031 final private IAccountService _accountService; 032 final private Config _config; 033 034 public WebLoginProvider(Context context, 035 Config config, 036 ISessionService sessionService, 037 IAccountService accountService, 038 IPersistenceService persistenceService, 039 IBusinessApiService businessApiService, 040 ProviderCallback providerCallback) { 041 super(context, persistenceService, businessApiService, providerCallback); 042 _config = config; 043 _sessionService = sessionService; 044 _accountService = accountService; 045 } 046 047 @Override 048 public String getName() { 049 return "web"; 050 } 051 052 @Override 053 public void login(Map<String, Object> loginParams, final String loginMode) { 054 if (_connecting) { 055 return; 056 } 057 _connecting = true; 058 _loginMode = loginMode; 059 final String providerName = (String) loginParams.get("provider"); 060 final String loginUrl = getRequest(_context, loginParams, loginMode); 061 WebLoginActivity.present(_context, loginUrl, new WebLoginActivity.WebLoginActivityCallback() { 062 063 @Override 064 public void onResult(Activity activity, Map<String, Object> parsed) { 065 GigyaLogger.debug(LOG_TAG, "onResult: " + parsed.toString()); 066 067 final String status = (String) parsed.get("status"); 068 if (status != null && status.equals("ok")) { 069 070 final SessionInfo sessionInfo = parseSessionInfo(parsed); 071 // Notify successful sign in. 072 onLoginSuccess(providerName, sessionInfo); 073 074 } else { 075 076 JSONObject jsonObject = new JSONObject(); 077 078 try { 079 // An error result appears in a different format. 080 // Need to parse it correctly in order for the flow to continue as expected. 081 082 if (parsed.containsKey("error_description")) { 083 084 final String errorDescription = (String) parsed.get("error_description"); 085 if (errorDescription != null) { 086 String[] parts = errorDescription.replace("+", "").split("-"); 087 if (parts.length > 1) { 088 final int errorCode = Integer.parseInt(parts[0].trim()); 089 final String errorMessage = parts[1].trim(); 090 091 jsonObject.put("errorCode", errorCode); 092 jsonObject.put("errorMessage", errorMessage); 093 } 094 } 095 096 if (parsed.containsKey("x_regToken")) { 097 final String regToken = (String) parsed.get("x_regToken"); 098 jsonObject.put("regToken", regToken); // Nullification is not relevant here. 099 } 100 } 101 } catch (Exception ex) { 102 ex.printStackTrace(); 103 } 104 105 GigyaLogger.debug(LOG_TAG, "onResult: with error = " + jsonObject.toString()); 106 107 onLoginFailed(new GigyaApiResponse(jsonObject.toString())); 108 } 109 110 if (activity != null) { 111 activity.finish(); 112 } 113 } 114 115 @Override 116 public void onCancelled() { 117 if (_providerCallback != null) { 118 _providerCallback.onCanceled(); 119 } 120 } 121 }); 122 } 123 124 @Override 125 public void logout() { 126 // Stub. 127 } 128 129 @Override 130 public String getProviderSessions(String tokenOrCode, long expiration, String uid) { 131 return null; 132 } 133 134 @Override 135 public boolean supportsTokenTracking() { 136 return false; 137 } 138 139 @Override 140 public void trackTokenChange() { 141 // Stub. 142 } 143 144 private SessionInfo parseSessionInfo(Map<String, Object> result) { 145 final String accessToken = (String) result.get("access_token"); 146 final String expiresInString = (String) result.get("expires_in"); 147 final long expiresIn = Long.parseLong(expiresInString != null ? expiresInString : "0"); 148 final String secret = (String) result.get("x_access_token_secret"); 149 return new SessionInfo(secret, accessToken, expiresIn); 150 } 151 152 private String getRequest(Context context, Map<String, Object> loginParams, String loginMode) { 153 final TreeMap<String, Object> serverParams = new TreeMap<>(); 154 final String provider = ((String) loginParams.get("provider")); 155 if (provider != null) { 156 provider.toLowerCase(); 157 final String xperm = (String) loginParams.get(provider + "ExtraPermissions"); 158 if (xperm != null) { 159 loginParams.remove(provider + "ExtraPermissions"); 160 serverParams.put("x_extraPermissions", xperm); 161 } 162 } 163 // Deep link schematics -> Scheme = gigya, host = gsapi, pathPrefix = package name + "/login_result. 164 final String redirectUri = "gigya://gsapi/" + context.getPackageName() + "/login_result"; 165 serverParams.put("redirect_uri", redirectUri); 166 serverParams.put("response_type", "token"); 167 serverParams.put("client_id", _config.getApiKey()); 168 serverParams.put("gmid", _config.getGmid()); 169 serverParams.put("ucid", _config.getUcid()); 170 serverParams.put("x_secret_type", "oauth1"); 171 serverParams.put("x_sdk", Gigya.VERSION); 172 // x_params additions. 173 for (Map.Entry entry : loginParams.entrySet()) { 174 final String key = (String) entry.getKey(); 175 Object value = loginParams.get(key); 176 if (value != null) { 177 if (key.startsWith("x_")) 178 serverParams.put(key, value); 179 else 180 serverParams.put("x_" + key, value); 181 } 182 } 183 184 String api = "socialize.login"; 185 if (loginMode.equals("connect")) { 186 api = "socialize.addConnection"; 187 } 188 189 if (_sessionService.isValid()) { 190 // Add signature parameters if needed. 191 @SuppressWarnings("ConstantConditions") final String sessionToken = _sessionService.getSession().getSessionToken(); 192 serverParams.put("oauth_token", sessionToken); 193 final String sessionSecret = _sessionService.getSession().getSessionSecret(); 194 AuthUtils.addAuthenticationParameters(sessionSecret, 195 RestAdapter.GET, 196 UrlUtils.getBaseUrl(api, _config.getApiDomain()), 197 serverParams, 198 _config.getServerOffset()); 199 } 200 201 202 // Build final URL. 203 return String.format("%s://%s.%s/%s?%s", "https", "socialize", _config.getApiDomain(), 204 api, UrlUtils.buildEncodedQuery(serverParams)); 205 } 206 207 private Pair<String, String> getPostRequest(Map<String, Object> loginParams) { 208 /* Remove if added. */ 209 if (!loginParams.isEmpty()) 210 loginParams.remove(FacebookProvider.LOGIN_BEHAVIOUR); 211 212 final String url = "https://socialize." + _config.getApiDomain() + "/socialize.login"; 213 final TreeMap<String, Object> urlParams = new TreeMap<>(); 214 urlParams.put("redirect_uri", "gsapi://login_result"); 215 urlParams.put("response_type", "token"); 216 urlParams.put("client_id", _config.getApiKey()); 217 urlParams.put("gmid", _config.getGmid()); 218 urlParams.put("ucid", _config.getUcid()); 219 220 // x_params additions. 221 for (Map.Entry entry : loginParams.entrySet()) { 222 final String key = (String) entry.getKey(); 223 Object value = loginParams.get(key); 224 if (value != null) { 225 if (key.startsWith("x_")) 226 urlParams.put(key, value); 227 else 228 urlParams.put("x_" + key, value); 229 } 230 } 231 urlParams.put("x_secret_type", "oauth1"); 232 urlParams.put("x_endPoint", "socialize.login"); 233 urlParams.put("x_sdk", Gigya.VERSION); 234 final String provider = (String) loginParams.get("provider"); 235 if (provider != null) { 236 urlParams.put("x_provider", provider); 237 } 238 239 // Encode post body. 240 final String encodedParams = UrlUtils.buildEncodedQuery(urlParams); 241 return new Pair<>(url, encodedParams); 242 } 243}