Skip to content

Commit

Permalink
Merge pull request #231 from Simperium/add-compromised-password-handling
Browse files Browse the repository at this point in the history
Add compromised password response handling
  • Loading branch information
AmandaRiu authored Aug 12, 2021
2 parents 4de51b2 + db7366a commit e475d72
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 19 deletions.
5 changes: 2 additions & 3 deletions Simperium/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@ repositories {
}

android {
buildToolsVersion "28.0.3"
compileSdkVersion 28
compileSdkVersion 30

defaultConfig {
minSdkVersion 23
targetSdkVersion 28
targetSdkVersion 30
versionName project.version

// Calculating PIN for certificate: OU=Domain Control Validated, CN=*.simperium.com
Expand Down
24 changes: 13 additions & 11 deletions Simperium/src/main/java/com/simperium/android/AsyncAuthClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@
import android.util.Log;

import com.koushikdutta.async.http.AsyncHttpClient;
import com.koushikdutta.async.http.AsyncHttpClient.JSONObjectCallback;
import com.koushikdutta.async.http.AsyncHttpPost;
import com.koushikdutta.async.http.AsyncHttpResponse;
import com.koushikdutta.async.http.body.JSONObjectBody;
import com.koushikdutta.async.parser.JSONObjectParser;
import com.simperium.BuildConfig;
import com.simperium.client.AuthException;
import com.simperium.client.AuthProvider;
Expand Down Expand Up @@ -109,14 +107,14 @@ public AsyncHttpPost buildRequest(String path, JSONObject body) {

private void sendRequest(String path, JSONObject body, final AuthResponseHandler handler) {

mClient.execute(buildRequest(path, body), new JSONObjectParser(), new JSONObjectCallback() {
@Override
public void onCompleted(Exception e, AsyncHttpResponse source, JSONObject result) {
mClient.executeString(buildRequest(path, body), new AsyncHttpClient.StringCallback() {

@Override
public void onCompleted(Exception e, AsyncHttpResponse asyncHttpResponse, String s) {
int responseCode = AuthException.ERROR_STATUS_CODE;

if (source != null) {
responseCode = source.code();
if (asyncHttpResponse != null) {
responseCode = asyncHttpResponse.code();
}

if (e != null) {
Expand All @@ -126,12 +124,16 @@ public void onCompleted(Exception e, AsyncHttpResponse source, JSONObject result
}

if (responseCode == 200) {
handler.onResponse(result);
return;
try {
JSONObject object = new JSONObject(s);
handler.onResponse(object);
return;
} catch (JSONException jsonException) {
handler.onError(AuthException.defaultException());
}
}

handler.onError(AuthException.exceptionForStatusCode(responseCode));

handler.onError(AuthException.exceptionForStatusCode(responseCode, new Throwable(s)));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ public void run() {
case EXISTING_ACCOUNT:
showDialogErrorExistingAccount();
break;
case COMPROMISED_PASSWORD:
showCompromisedPasswordDialog();
break;
case INVALID_ACCOUNT:
default:
showDialogError(getString(
Expand Down Expand Up @@ -484,6 +487,35 @@ public void onClick(DialogInterface dialog, int which) {
.show();
}

private void showCompromisedPasswordDialog() {
hideDialogProgress();
final Context context = new ContextThemeWrapper(CredentialsActivity.this, getTheme());
new AlertDialog.Builder(context)
.setTitle(R.string.simperium_compromised_password)
.setMessage(R.string.simperium_compromised_password_message)
.setNegativeButton(R.string.simperium_not_now, null)
.setPositiveButton(R.string.simperium_change_password,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
try {
String url = getString(com.simperium.R.string.simperium_dialog_button_reset_url, URLEncoder.encode(getEditTextString(mInputEmail), UTF_8));

if (isBrowserInstalled()) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
clearPassword();
} else {
showDialogErrorBrowser(url);
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Unable to parse URL", e);
}
}
}
)
.show();
}

private void startLogin() {
final String email = getEditTextString(mInputEmail);
final String password = getEditTextString(mInputPassword);
Expand Down
15 changes: 12 additions & 3 deletions Simperium/src/main/java/com/simperium/client/AuthException.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@

import com.simperium.SimperiumException;

import java.util.Objects;

public class AuthException extends SimperiumException {

static public final String GENERIC_FAILURE_MESSAGE = "Invalid username or password";
static public final String EXISTING_USER_FAILURE_MESSAGE = "Account already exists";
static public final String COMPROMISED_PASSWORD_MESSAGE = "Password has been compromised";
static public final String COMPROMISED_PASSWORD_BODY = "compromised password";

static public final int ERROR_STATUS_CODE = -1;
static public final int INVALID_ACCOUNT_CODE = 0x0;
static public final int EXISTING_ACCOUNT_CODE = 0x1;

public final FailureType failureType;

public enum FailureType {
INVALID_ACCOUNT, EXISTING_ACCOUNT
INVALID_ACCOUNT, EXISTING_ACCOUNT, COMPROMISED_PASSWORD
}

public AuthException(FailureType code, String message){
Expand All @@ -39,6 +41,13 @@ public static AuthException exceptionForStatusCode(int statusCode, Throwable cau
switch (statusCode) {
case 409:
return new AuthException(FailureType.EXISTING_ACCOUNT, EXISTING_USER_FAILURE_MESSAGE, cause);
case 401:
// Code 401 can be obtain because credentials are wrong or the user's password has been compromised
// To differentiate both responses, we check the response's body
String message = cause != null && cause.getMessage() != null ? cause.getMessage().toLowerCase() : "";
if (Objects.equals(message, COMPROMISED_PASSWORD_BODY)) {
return new AuthException(FailureType.COMPROMISED_PASSWORD, COMPROMISED_PASSWORD_MESSAGE, cause);
}
default:
return new AuthException(FailureType.INVALID_ACCOUNT, GENERIC_FAILURE_MESSAGE, cause);
}
Expand Down
5 changes: 4 additions & 1 deletion Simperium/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@
<string name="simperium_hint_email">Email</string>
<string name="simperium_hint_password">Password</string>
<string name="simperium_subtitle">App data, everywhere it\'s needed.</string>
<string name="simperium_compromised_password">Compromised Password</string>
<string name="simperium_compromised_password_message">This password has appeared in a data breach, which puts your account at high risk of compromise. It is recommended that you change your password immediately.</string>
<string name="simperium_not_now">Not Now</string>
<string name="simperium_change_password">Change Password</string>
<string name="simperium_title">@string/app_name</string>
<string name="simperium_url">https://simperium.com/</string>

</resources>
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ def gitDescribe() {
}

def static gitVersion() {
'0.10.0'
'0.10.1'
}

0 comments on commit e475d72

Please sign in to comment.