|
|
@ -1,7 +1,5 @@ |
|
|
|
package com.gmeremit.online.gmeremittance_native.loginV2.presenter; |
|
|
|
|
|
|
|
import android.os.Build; |
|
|
|
import android.security.keystore.KeyPermanentlyInvalidatedException; |
|
|
|
import android.util.Log; |
|
|
|
|
|
|
|
import com.gmeremit.online.gmeremittance_native.GmeApplication; |
|
|
@ -14,11 +12,7 @@ import com.gmeremit.online.gmeremittance_native.utils.Constants; |
|
|
|
import com.gmeremit.online.gmeremittance_native.utils.Utils; |
|
|
|
import com.gmeremit.online.gmeremittance_native.utils.https.GenericApiObserverResponse; |
|
|
|
import com.gmeremit.online.gmeremittance_native.utils.security.SecurityUtils; |
|
|
|
import com.mtramin.rxfingerprint.data.FingerprintAuthenticationException; |
|
|
|
import com.mtramin.rxfingerprint.data.FingerprintDecryptionResult; |
|
|
|
import com.mtramin.rxfingerprint.data.FingerprintEncryptionResult; |
|
|
|
|
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
|
|
|
|
import io.reactivex.Observable; |
|
|
|
import io.reactivex.android.schedulers.AndroidSchedulers; |
|
|
@ -53,21 +47,33 @@ public class LoginV2Presenter extends BasePresenter implements LoginV2PresenterI |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void persistUserCredentialForBiometricAuth(String userId, String pwd) { |
|
|
|
Observable.zip(Observable.just(userId), encryptData(pwd), BiometricEncParams::new) |
|
|
|
.observeOn(AndroidSchedulers.mainThread()) |
|
|
|
.subscribe(new BiometricEncrypterObserver()); |
|
|
|
private void persistUserCredentialForFingerprintAuth(String userId, String pwd) { |
|
|
|
SecurityUtils.generateKey() |
|
|
|
.flatMap(key -> Observable.zip(Observable.just(userId), |
|
|
|
SecurityUtils.encryptSymmetric(pwd, key).subscribeOn(Schedulers.io()), |
|
|
|
encryptToKeyStore(key).subscribeOn(Schedulers.io()), |
|
|
|
FingerprintEncResult::new) |
|
|
|
).observeOn(AndroidSchedulers.mainThread()) |
|
|
|
.subscribe(new FingerprintEncResultObserver()); |
|
|
|
} |
|
|
|
|
|
|
|
private Observable<FingerprintEncryptionResult> encryptData(String data) { |
|
|
|
private Observable<String> encryptToKeyStore(String data) { |
|
|
|
return SecurityUtils.encryptToKeyStore(view.getContext(), data) |
|
|
|
.subscribeOn(Schedulers.io()); |
|
|
|
.flatMap(encKey -> Observable.just(encKey.getEncrypted())); |
|
|
|
} |
|
|
|
|
|
|
|
private Observable<FingerprintDecResult> authenticateFingerprint() { |
|
|
|
return Observable.zip(Observable.fromCallable(gateway::getPersistedUserId), |
|
|
|
Observable.fromCallable(gateway::getPersistedSecretKey) |
|
|
|
.flatMap(storedKey -> decryptFromKeyStore(storedKey).flatMap(decAesKey -> SecurityUtils.decryptSymmetric(gateway.getPersistedUserPwd(), decAesKey))) |
|
|
|
.subscribeOn(Schedulers.io()), |
|
|
|
FingerprintDecResult::new) |
|
|
|
.observeOn(AndroidSchedulers.mainThread()); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private Observable<FingerprintDecryptionResult> decryptData(String data) { |
|
|
|
private Observable<String> decryptFromKeyStore(String data) { |
|
|
|
return SecurityUtils.decryptFromKeyStore(view.getContext(), data) |
|
|
|
.subscribeOn(Schedulers.io()) |
|
|
|
.flatMap(authentication -> { |
|
|
|
switch (authentication.getResult()) { |
|
|
|
case FAILED: |
|
|
@ -80,7 +86,8 @@ public class LoginV2Presenter extends BasePresenter implements LoginV2PresenterI |
|
|
|
return io.reactivex.Observable.error(new Throwable(authentication.getMessage())); |
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
}) |
|
|
|
.map(FingerprintDecryptionResult::getDecrypted); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
@ -102,7 +109,7 @@ public class LoginV2Presenter extends BasePresenter implements LoginV2PresenterI |
|
|
|
|
|
|
|
@Override |
|
|
|
public boolean checkIfBiometricIsAvailable() { |
|
|
|
return SecurityUtils.doesAppHasBiometricFeature(view.getContext()) && gateway.isFingerPrintAuthEnabled() && gateway.getPersistedUserId() != null && gateway.getPersistedUserPwd() != null; |
|
|
|
return SecurityUtils.checkFingerPrintUsablity(view.getContext()) && gateway.isFingerPrintAuthEnabled() && gateway.getPersistedUserId() != null && gateway.getPersistedUserPwd() != null; |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
@ -115,29 +122,12 @@ public class LoginV2Presenter extends BasePresenter implements LoginV2PresenterI |
|
|
|
} else { |
|
|
|
if (fingerPrintScanningSubscription == null || fingerPrintScanningSubscription.isDisposed()) |
|
|
|
view.showFingerPrintScanner(true); |
|
|
|
fingerPrintScanningSubscription = Observable.zip(Observable.fromCallable(gateway::getPersistedUserId), decryptData(gateway.getPersistedUserPwd()), BiometricDecParams::new) |
|
|
|
.observeOn(AndroidSchedulers.mainThread()) |
|
|
|
.retryWhen(errors -> errors.flatMap( |
|
|
|
error -> { |
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && error instanceof KeyPermanentlyInvalidatedException) { |
|
|
|
view.showFingerPrintScanner(false); |
|
|
|
gateway.flushBiometricData(); |
|
|
|
} |
|
|
|
else if(error instanceof FingerprintAuthenticationException) |
|
|
|
{ |
|
|
|
view.showFingerPrintScanner(false); |
|
|
|
} |
|
|
|
else if (error instanceof SecurityUtils.FailedFingerPrintException || error instanceof SecurityUtils.SensorNotReadyException) { |
|
|
|
view.showToastMessage(error.getMessage()); |
|
|
|
return Observable.timer(100, TimeUnit.MILLISECONDS); |
|
|
|
} |
|
|
|
return Observable.error(error); |
|
|
|
} |
|
|
|
)) |
|
|
|
.subscribeWith(new BiometricDecrypterObserver()); |
|
|
|
fingerPrintScanningSubscription = authenticateFingerprint() |
|
|
|
.subscribeWith(new FingerprintDecResultObserver()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
public void loginUser(String userId, String userPwd) { |
|
|
|
String auth = "Basic " + Utils.toBase64("172017F9EC11222E8107142733:QRK2UM0Q:" + GmeApplication.getAppRelatedMetaData().getDeviceId()); |
|
|
@ -182,8 +172,8 @@ public class LoginV2Presenter extends BasePresenter implements LoginV2PresenterI |
|
|
|
|
|
|
|
@Override |
|
|
|
protected void onSuccess(Boolean aBoolean) { |
|
|
|
if (SecurityUtils.doesAppHasBiometricFeature(view.getContext())) |
|
|
|
persistUserCredentialForBiometricAuth(userId, encUserPassword); |
|
|
|
if (SecurityUtils.checkFingerPrintUsablity(view.getContext())) |
|
|
|
persistUserCredentialForFingerprintAuth(userId, encUserPassword); |
|
|
|
else { |
|
|
|
view.showInvalidPassword(null); |
|
|
|
view.showInvalidUserId(null); |
|
|
@ -209,74 +199,85 @@ public class LoginV2Presenter extends BasePresenter implements LoginV2PresenterI |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public class BiometricEncParams { |
|
|
|
private String userId; |
|
|
|
private FingerprintEncryptionResult pwd; |
|
|
|
|
|
|
|
BiometricEncParams(String userId, FingerprintEncryptionResult pwd) { |
|
|
|
public class FingerprintEncResult { |
|
|
|
String userId; |
|
|
|
String encPwd; |
|
|
|
String encKey; |
|
|
|
|
|
|
|
public FingerprintEncResult(String userId, String encPwd, String encKey) { |
|
|
|
this.userId = userId; |
|
|
|
this.pwd = pwd; |
|
|
|
this.encPwd = encPwd; |
|
|
|
this.encKey = encKey; |
|
|
|
} |
|
|
|
|
|
|
|
public String getUserId() { |
|
|
|
return userId; |
|
|
|
} |
|
|
|
|
|
|
|
public void setUserId(String userId) { |
|
|
|
this.userId = userId; |
|
|
|
public String getEncPwd() { |
|
|
|
return encPwd; |
|
|
|
} |
|
|
|
|
|
|
|
public FingerprintEncryptionResult getPwd() { |
|
|
|
return pwd; |
|
|
|
public String getEncKey() { |
|
|
|
return encKey; |
|
|
|
} |
|
|
|
|
|
|
|
public void setPwd(FingerprintEncryptionResult pwd) { |
|
|
|
this.pwd = pwd; |
|
|
|
@Override |
|
|
|
public String toString() { |
|
|
|
return "FingerprintEncResult{" + |
|
|
|
"userId='" + userId + '\'' + |
|
|
|
", encPwd='" + encPwd + '\'' + |
|
|
|
", encKey='" + encKey + '\'' + |
|
|
|
'}'; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public class BiometricDecParams { |
|
|
|
private String userId; |
|
|
|
private FingerprintDecryptionResult pwd; |
|
|
|
public class FingerprintDecResult { |
|
|
|
String userId; |
|
|
|
String userPwd; |
|
|
|
|
|
|
|
BiometricDecParams(String userId, FingerprintDecryptionResult pwd) { |
|
|
|
public FingerprintDecResult(String userId, String userPwd) { |
|
|
|
this.userId = userId; |
|
|
|
this.pwd = pwd; |
|
|
|
this.userPwd = userPwd; |
|
|
|
} |
|
|
|
|
|
|
|
public String getUserId() { |
|
|
|
return userId; |
|
|
|
} |
|
|
|
|
|
|
|
public void setUserId(String userId) { |
|
|
|
this.userId = userId; |
|
|
|
} |
|
|
|
|
|
|
|
public FingerprintDecryptionResult getPwd() { |
|
|
|
return pwd; |
|
|
|
public String getUserPwd() { |
|
|
|
return userPwd; |
|
|
|
} |
|
|
|
|
|
|
|
public void setPwd(FingerprintDecryptionResult pwd) { |
|
|
|
this.pwd = pwd; |
|
|
|
@Override |
|
|
|
public String toString() { |
|
|
|
return "FingerprintDecResult{" + |
|
|
|
"userId='" + userId + '\'' + |
|
|
|
", userPwd='" + userPwd + '\'' + |
|
|
|
'}'; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public class BiometricEncrypterObserver extends DisposableObserver<BiometricEncParams> { |
|
|
|
|
|
|
|
public class FingerprintEncResultObserver extends DisposableObserver<FingerprintEncResult> { |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onNext(BiometricEncParams biometricParams) { |
|
|
|
gateway.persistUserId(biometricParams.getUserId()); |
|
|
|
gateway.persistUserPwd(biometricParams.getPwd().getEncrypted()); |
|
|
|
public void onNext(FingerprintEncResult fingerprintEncResult) { |
|
|
|
Log.d(SecurityUtils.TAG, "Success : " + fingerprintEncResult.toString()); |
|
|
|
gateway.persistSecretKey(fingerprintEncResult.getEncKey()); |
|
|
|
gateway.persistUserPwd(fingerprintEncResult.getEncPwd()); |
|
|
|
gateway.persistUserId(fingerprintEncResult.getUserId()); |
|
|
|
view.showInvalidPassword(null); |
|
|
|
view.showInvalidUserId(null); |
|
|
|
view.redirectToDashboard(); |
|
|
|
encUserPassword = null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onError(Throwable e) { |
|
|
|
Log.d(SecurityUtils.TAG,e.getMessage()); |
|
|
|
Log.d(SecurityUtils.TAG, "Failed : " + e.getMessage()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
@ -285,19 +286,21 @@ public class LoginV2Presenter extends BasePresenter implements LoginV2PresenterI |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public class BiometricDecrypterObserver extends DisposableObserver<BiometricDecParams> { |
|
|
|
public class FingerprintDecResultObserver extends DisposableObserver<FingerprintDecResult> { |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onNext(BiometricDecParams biometricParams) { |
|
|
|
encUserPassword = biometricParams.getPwd().getDecrypted(); |
|
|
|
view.onLoginPerformTask(() -> loginUser(biometricParams.getUserId(), "")); |
|
|
|
public void onNext(FingerprintDecResult fingerprintDecResult) { |
|
|
|
Log.d(SecurityUtils.TAG, "Success : " + fingerprintDecResult.toString()); |
|
|
|
|
|
|
|
encUserPassword = fingerprintDecResult.getUserPwd(); |
|
|
|
view.onLoginPerformTask(() -> loginUser(fingerprintDecResult.getUserId(), "")); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onError(Throwable e) { |
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && e instanceof KeyPermanentlyInvalidatedException) |
|
|
|
return; |
|
|
|
view.showToastMessage(e.getMessage()); |
|
|
|
Log.d(SecurityUtils.TAG, "Failed : " + e.getMessage()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|