Android Google Auth Sign In get Id token handleSignInResult:false - google-plus

I am setting GoogleSignInOptions and Google Api Client like this
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.server_client_ID))
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.addApi(Plus.API)
.build();
and my google web app client id like this:
1020847812450-xxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com
but always at onActivityResult
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
is returning false
where am i doing wrong here :S
onStart Section
mGoogleApiClient.connect();
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d(TAG, "Got cached sign-in");
// GoogleSignInResult result = opr.get();
// handleSignInResult(result);
} else {
// If the user has not previously signed in on this device or the sign-in has expired,
// this asynchronous branch will attempt to sign in the user silently. Cross-device
// single sign-on will occur in this branch.
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
#Override
public void onResult(GoogleSignInResult googleSignInResult) {
handleSignInResult(googleSignInResult);
}
});
}
onStop section
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
onHandleSignInResult
private void handleSignInResult(GoogleSignInResult result) {
Log.e(TAG, "handleSignInResult:" + result.isSuccess());
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
final GoogleSignInAccount acct = result.getSignInAccount();
Log.e(TAG, acct.getDisplayName());
}
}

I am also facing the same issue.First remove the current OAuth client ID,after that create one more OAuth client ID.Its worked for me.

Are you getting error 12501? I also had this issue because I was using debug.keystore which comes with the SDK (for some reason unknown to me, it didn't work). I created a new one on my own, got SHA-1 hash from it, entered in Google API console and then it worked.
Be sure you set up signing configs for both debug and release builds with the new keystore.

Follow all the step!!..
Release APK and debug APK has different SHA1 and different API keys for google services. Both of them must be added in Firebase Console -> Project settings. Then download google-services.json from here, add it to project and recompile with release keystore using the option "Build signed APK". That should work
and also read carefully...
https://developer.android.com/studio/publish/app-signing

I believe that you need a call to client.connect(); as per documentation example:
GoogleApiClient client = new GoogleApiClient.Builder(this)
.addApi(Plus.API)
.addScope(Plus.SCOPE_PLUS_LOGIN)
.setAccountName("users.account.name#gmail.com")
.build();
client.connect();
Or is it missing from your question and you are calling connect somwhere else in your code?

Related

Android Google Sign-In

I need to enable server-side access to Google Drive. In this case a person is using his Android device. As far as I understood the steps are as follows:
1. Create GoogleSignInOptions
2. Using the GoogleSignInOptions create GoogleSignInAccount
3. Getting authCode from GoogleSignInAccount
4. Exchange the authCode for access/refresh/ID tokens
I am stuck on step 3. I followed the well-described tutorials without any success - https://developers.google.com/identity/sign-in/android/offline-access, https://developers.google.com/identity/sign-in/android/sign-in#configure_google_sign-in_and_the_googleapiclient_object
Here is the code that initialize sign-in process:
final GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(new Scope(Scopes.DRIVE_APPFOLDER))
.requestServerAuthCode(backend_server_web_client_id)
.build();
GoogleSignInClient google_api_client = GoogleSignIn.getClient(context, gso);
activity.startActivityForResult(google_api_client.getSignInIntent(), RC_SIGN_IN);
Here is the code that handles the sign-in result:
// data is the intent from onActivityResult callback
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
if (task.isComplete())
handle(task);
else {
task.addOnCompleteListener(new OnCompleteListener<GoogleSignInAccount>() {
#Override
public void onComplete(#NonNull Task<GoogleSignInAccount> task) {
handle(task);
}}
});
}
And finally here is the handle function where is the problem:
public void handle(Task<GoogleSignInAccount> task) {
try {
GoogleSignInAccount account = task.getResult(ApiException.class);
} catch (ApiException e) {
//I'm always getting this exception with status code 10, which means DEVELOPER ERROR. Keys in Google API console are checked multiple times.
}
}
In handle function I'm always getting an exception with status code 10, which means DEVELOPER_ERROR. Keys in Google API console are checked multiple times. Code was rewritten few times.... I really have no idea what could be wrong.
Thank you :)
You might have forgotten to configure Google API Console. Follow the instructions:
https://developers.google.com/identity/sign-in/android/start-integrating
You see to create OAuth client ID for Android with corresponding package name and signing certificate's SHA1. You do NOT have to enter this key anywhere in the code. It just have to exist in Google API Console.

FirebaseAuthWithPlayGames Fatal Exception: java.lang.RuntimeException Caused by java.lang.IllegalArgumentException Given String is empty or null

Hello I have a fully working code for signing in a Player by Google Play Games Sign in. See this code snippet
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestServerAuthCode("720182182679-fv285c7k5kecqhqdmc9ggc9f73jc9hef.apps.googleusercontent.com")
.build();
mGoogleSignInClient = GoogleSignIn.getClient(start.this, gso);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Games.API)
.addScope(Games.SCOPE_GAMES)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
private void startSignInIntent() {
GoogleSignInClient googleSignInClient = GoogleSignIn.getClient(this, GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN);
Intent intent = googleSignInClient.getSignInIntent();
startActivityForResult(intent, RC_SIGN_IN);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess()) {
// The signed in account is stored in the result.
GoogleSignInAccount signedInAccount = result.getSignInAccount();
assert signedInAccount != null;
Toast.makeText(start.this, "Google Play Games Connectet", Toast.LENGTH_SHORT).show();
} else {
String message = result.getStatus().getStatusMessage();
new AlertDialog.Builder(this).setMessage(message)
.setNeutralButton(android.R.string.ok, null).show();
}
}
}
The code above works perfektly. But if I want to trigger the following method the game crashes, and gets me the error in the title.
private void firebaseAuthWithPlayGames(GoogleSignInAccount acct) {
Log.d(TAG, "firebaseAuthWithPlayGames:" + acct.getId());
AuthCredential credential = PlayGamesAuthProvider.getCredential(acct.getServerAuthCode());
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, task -> {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithCredential:success");
FirebaseUser user = mAuth.getCurrentUser();
updateUI(user);
} else {
// If sign in fails, display a message to the user.
Log.w(TAG, "signInWithCredential:failure", task.getException());
Toast.makeText(start.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
updateUI(null);
}
// ...
});
}
I trigger this method by calling it in the on ActivityResult of startSignInIntent like this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess()) {
// The signed in account is stored in the result.
GoogleSignInAccount signedInAccount = result.getSignInAccount();
assert signedInAccount != null;
---------> firebaseAuthWithPlayGames(signedInAccount); <-----------
Toast.makeText(start.this, "Google Play Games Connectet", Toast.LENGTH_SHORT).show();
} else {
String message = result.getStatus().getStatusMessage();
new AlertDialog.Builder(this).setMessage(message)
.setNeutralButton(android.R.string.ok, null).show();
}
}
}
I hope someone has faced this issue and can help.
I believe this is because it is not getting the token correctly between Game Services and Firebase
You have to configure the web app that is linked to the same game in the play console. Then copy the client id from the web app and paste it into the setup dialog for the plugin.
Steps are here...
https://firebase.google.com/docs/auth/android/play-games
Double check these steps:
Enable Google Play Games as a sign-in provider:
Find your project's web server client ID and client secret. The web server client ID identifies your Firebase project to the Google Play auth servers.
To find these values:
Open your Firebase project in the Google APIs console credentials page.
In the OAuth 2.0 client IDs section, open the Web client (auto created by Google Service) details page. This page lists your web server client ID and secret.
Then, in the Firebase console, open the Authentication section.
On the Sign in method tab, enable the Play Games sign-in provider. You will need to specify your project's web server client ID and client secret, which you got from the APIs console.
I think I might have just bumped into the exact same issue you have experienced earlier. I see, already 1 year have passed since your question, but I hope maybe it still can help you or others.
I was doing the integration of Firebase with my existing game that had Google Play Games Services. I wanted Firebase to use Play Games authentication, but after I have done everything according to the manual, the sign-in into Firebase was unsuccessful with the error message: Given String is empty or null.
I have figured out that actually there was no problem with the code, nor with the integration setup. The solution was that simply I had to log out from my Google account and re-login again.
I think, at the time when I last logged in to my Google account and Games Services in my app, the info about the Firebase integration setup was not existing there yet, so my cached account on my phone did not know about it at all. The re-login refreshed the settings in the cache and the following authCode request could finally successfully return the needed string:
String authCode = signedInAccount.getServerAuthCode();

Google Play Warning Vulnerability SSL Error Handler [duplicate]

I have a link which will open in WebView. The problem is it cannot be open until I override onReceivedSslError like this:
#Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
I am getting security alert from Google Play saying:
Security alert
Your application has an unsafe implementation of the WebViewClient.onReceivedSslError handler. Specifically, the implementation ignores all SSL certificate validation errors, making your app vulnerable to man-in-the-middle attacks. An attacker could change the affected WebView's content, read transmitted data (such as login credentials), and execute code inside the app using JavaScript.
To properly handle SSL certificate validation, change your code to invoke SslErrorHandler.proceed() whenever the certificate presented by the server meets your expectations, and invoke SslErrorHandler.cancel() otherwise. An email alert containing the affected app(s) and class(es) has been sent to your developer account address.
Please address this vulnerability as soon as possible and increment the version number of the upgraded APK. For more information about the SSL error handler, please see our documentation in the Developer Help Center. For other technical questions, you can post to https://www.stackoverflow.com/questions and use the tags “android-security” and “SslErrorHandler.” If you are using a 3rd party library that’s responsible for this, please notify the 3rd party and work with them to address the issue.
To confirm that you've upgraded correctly, upload the updated version to the Developer Console and check back after five hours. If the app hasn't been correctly upgraded, we will display a warning.
Please note, while these specific issues may not affect every app that uses WebView SSL, it's best to stay up to date on all security patches. Apps with vulnerabilities that expose users to risk of compromise may be considered dangerous products in violation of the Content Policy and section 4.4 of the Developer Distribution Agreement.
Please ensure all apps published are compliant with the Developer Distribution Agreement and Content Policy. If you have questions or concerns, please contact our support team through the Google Play Developer Help Center.
If I remove onReceivedSslError (handler.proceed()), then page won't open.
Is there any way I can open the page in WebView and avoid security alert?
To properly handle SSL certificate validation, change your code to
invoke SslErrorHandler.proceed() whenever the certificate presented by
the server meets your expectations, and invoke
SslErrorHandler.cancel() otherwise.
As email said, onReceivedSslError should handle user is going to a page with invalid cert, such like a notify dialog. You should not proceed it directly.
For example, I add an alert dialog to make user have confirmed and seems Google no longer shows warning.
#Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.notification_error_ssl_cert_invalid);
builder.setPositiveButton("continue", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
handler.proceed();
}
});
builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
handler.cancel();
}
});
final AlertDialog dialog = builder.create();
dialog.show();
}
More explain about the email.
Specifically, the implementation ignores all SSL certificate validation
errors, making your app vulnerable to man-in-the-middle attacks.
The email says the default implement ignored an important SSL security problem. So we need to handle it in our own app which used WebView. Notify user with a alert dialog is a simple way.
The proposed solutions so far just bypass the security check, so they are not safe.
What I suggest is to embed the certificate(s) in the App, and when a SslError occurs, check that the server certificate matches one of the embedded certificates.
So here are the steps:
Retrieve the certificate from the website.
Open the site on Safari
Click on the padlock icon near the website name
Click on Show Certificate
Drag and drop the certificate in a folder
see https://www.markbrilman.nl/2012/03/howto-save-a-certificate-via-safari-on-mac/
Copy the certificate (.cer file) into the res/raw folder of your app
In your code, load the certificate(s) by calling loadSSLCertificates()
private static final int[] CERTIFICATES = {
R.raw.my_certificate, // you can put several certificates
};
private ArrayList<SslCertificate> certificates = new ArrayList<>();
private void loadSSLCertificates() {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
for (int rawId : CERTIFICATES) {
InputStream inputStream = getResources().openRawResource(rawId);
InputStream certificateInput = new BufferedInputStream(inputStream);
try {
Certificate certificate = certificateFactory.generateCertificate(certificateInput);
if (certificate instanceof X509Certificate) {
X509Certificate x509Certificate = (X509Certificate) certificate;
SslCertificate sslCertificate = new SslCertificate(x509Certificate);
certificates.add(sslCertificate);
} else {
Log.w(TAG, "Wrong Certificate format: " + rawId);
}
} catch (CertificateException exception) {
Log.w(TAG, "Cannot read certificate: " + rawId);
} finally {
try {
certificateInput.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (CertificateException e) {
e.printStackTrace();
}
}
When a SslError occurs, check that the server certificate matches one embedded certificate. Note that it is not possible to directly compare certificates, so I use SslCertificate.saveState to put the certificate data into a Bundle, and then I compare all the bundle entries.
webView.setWebViewClient(new WebViewClient() {
#Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
// Checks Embedded certificates
SslCertificate serverCertificate = error.getCertificate();
Bundle serverBundle = SslCertificate.saveState(serverCertificate);
for (SslCertificate appCertificate : certificates) {
if (TextUtils.equals(serverCertificate.toString(), appCertificate.toString())) { // First fast check
Bundle appBundle = SslCertificate.saveState(appCertificate);
Set<String> keySet = appBundle.keySet();
boolean matches = true;
for (String key : keySet) {
Object serverObj = serverBundle.get(key);
Object appObj = appBundle.get(key);
if (serverObj instanceof byte[] && appObj instanceof byte[]) { // key "x509-certificate"
if (!Arrays.equals((byte[]) serverObj, (byte[]) appObj)) {
matches = false;
break;
}
} else if ((serverObj != null) && !serverObj.equals(appObj)) {
matches = false;
break;
}
}
if (matches) {
handler.proceed();
return;
}
}
}
handler.cancel();
String message = "SSL Error " + error.getPrimaryError();
Log.w(TAG, message);
}
});
I needed to check our truststore before show any message to the user so I did this:
public class MyWebViewClient extends WebViewClient {
private static final String TAG = MyWebViewClient.class.getCanonicalName();
Resources resources;
Context context;
public MyWebViewClient(Resources resources, Context context){
this.resources = resources;
this.context = context;
}
#Override
public void onReceivedSslError(WebView v, final SslErrorHandler handler, SslError er){
// first check certificate with our truststore
// if not trusted, show dialog to user
// if trusted, proceed
try {
TrustManagerFactory tmf = TrustManagerUtil.getTrustManagerFactory(resources);
for(TrustManager t: tmf.getTrustManagers()){
if (t instanceof X509TrustManager) {
X509TrustManager trustManager = (X509TrustManager) t;
Bundle bundle = SslCertificate.saveState(er.getCertificate());
X509Certificate x509Certificate;
byte[] bytes = bundle.getByteArray("x509-certificate");
if (bytes == null) {
x509Certificate = null;
} else {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(bytes));
x509Certificate = (X509Certificate) cert;
}
X509Certificate[] x509Certificates = new X509Certificate[1];
x509Certificates[0] = x509Certificate;
trustManager.checkServerTrusted(x509Certificates, "ECDH_RSA");
}
}
Log.d(TAG, "Certificate from " + er.getUrl() + " is trusted.");
handler.proceed();
}catch(Exception e){
Log.d(TAG, "Failed to access " + er.getUrl() + ". Error: " + er.getPrimaryError());
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
String message = "SSL Certificate error.";
switch (er.getPrimaryError()) {
case SslError.SSL_UNTRUSTED:
message = "O certificado não é confiável.";
break;
case SslError.SSL_EXPIRED:
message = "O certificado expirou.";
break;
case SslError.SSL_IDMISMATCH:
message = "Hostname inválido para o certificado.";
break;
case SslError.SSL_NOTYETVALID:
message = "O certificado é inválido.";
break;
}
message += " Deseja continuar mesmo assim?";
builder.setTitle("Erro");
builder.setMessage(message);
builder.setPositiveButton("Sim", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
handler.proceed();
}
});
builder.setNegativeButton("Não", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
handler.cancel();
}
});
final AlertDialog dialog = builder.create();
dialog.show();
}
}
}
Fix which works for me is just disable onReceivedSslError function defined in AuthorizationWebViewClient. In this case handler.cancel will be called in case of SSL error. However it works good with One Drive SSL certificates. Tested on Android 2.3.7, Android 5.1.
According to Google Security Alert: Unsafe implementation of the interface X509TrustManager, Google Play won't support X509TrustManager from 11th July 2016:
Hello Google Play Developer,
Your app(s) listed at the end of this email use an unsafe
implementation of the interface X509TrustManager. Specifically, the
implementation ignores all SSL certificate validation errors when
establishing an HTTPS connection to a remote host, thereby making your
app vulnerable to man-in-the-middle attacks. An attacker could read
transmitted data (such as login credentials) and even change the data
transmitted on the HTTPS connection. If you have more than 20 affected
apps in your account, please check the Developer Console for a full
list.
To properly handle SSL certificate validation, change your code in the
checkServerTrusted method of your custom X509TrustManager interface to
raise either CertificateException or IllegalArgumentException whenever
the certificate presented by the server does not meet your
expectations. For technical questions, you can post to Stack Overflow
and use the tags “android-security” and “TrustManager.”
Please address this issue as soon as possible and increment the
version number of the upgraded APK. Beginning May 17, 2016, Google
Play will block publishing of any new apps or updates containing the
unsafe implementation of the interface X509TrustManager.
To confirm you’ve made the correct changes, submit the updated version
of your app to the Developer Console and check back after five hours.
If the app hasn’t been correctly upgraded, we will display a warning.
While these specific issues may not affect every app with the
TrustManager implementation, it’s best not to ignore SSL certificate
validation errors. Apps with vulnerabilities that expose users to risk
of compromise may be considered dangerous products in violation of the
Content Policy and section 4.4 of the Developer Distribution
Agreement.
...
I had the same issue and tried all the above-mentioned suggestions as below.
Implement onReceivedSslError() by giving the chance to the user to
decide handler.proceed(); or handler.cancel(); when a SSL error
occurred
Implement onReceivedSslError() to call handler.cancel(); whenever a
SSL issue occurred without considering user's decision.
Implement onReceivedSslError() to verify SSL certificate locally
addition to checking error.getPrimaryError() and providing the user
to decide handler.proceed(); or handler.cancel(); only if the SSL
certificate is valid. If not just call handler.cancel();
Removing the implementation of onReceivedSslError() and just let to
happen Android default behavior.
Even after trying all the above attempts, Google Play was keeping sending the same notification mail mentioning the same error and the old APK version (Even though in the all above attempts we changed both version code and version name in the Gradle)
We were in huge trouble and contacted Google Support via mail and asked
"We are uploading the higher versions of the APK but the review result
says the same error mentioning the old buggy APK version. What's the
reason for that ?"
After a few days, google support replied to our request as follows.
Please note that you must completely replace version 12 in your
Production track. It means that you'll have to full rollout a higher
version in order to deactivate version 12.
The highlighted point was never found or mentioned in the play console or any forum.
According to that guideline in the classic Google play view, we checked the production track and there were both buggy versions and the latest bug fixed version but the bug fix version's rollout percentage is 20%. So, turned it to full rollout then the buggy version disappeared from the production track. After more than 24 hour review time version has come back.
NOTE: When we had this issue Google has just moved to a new UI version of their play console and it had missed some views in the previous UI version or classic view. Since we were using the latest view we couldn't notice what was happening. Simply what happened was Google reviewed the same previous buggy version of the APK since the new one was not full roll-out.
You can use SslError for show, some information about the error of this certificated, and you can write in your dialog the string of the type error.
#Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
final SslErrorHandler handlerFinal;
handlerFinal = handler;
int mensaje ;
switch(error.getPrimaryError()) {
case SslError.SSL_DATE_INVALID:
mensaje = R.string.notification_error_ssl_date_invalid;
break;
case SslError.SSL_EXPIRED:
mensaje = R.string.notification_error_ssl_expired;
break;
case SslError.SSL_IDMISMATCH:
mensaje = R.string.notification_error_ssl_idmismatch;
break;
case SslError.SSL_INVALID:
mensaje = R.string.notification_error_ssl_invalid;
break;
case SslError.SSL_NOTYETVALID:
mensaje = R.string.notification_error_ssl_not_yet_valid;
break;
case SslError.SSL_UNTRUSTED:
mensaje = R.string.notification_error_ssl_untrusted;
break;
default:
mensaje = R.string.notification_error_ssl_cert_invalid;
}
AppLogger.e("OnReceivedSslError handel.proceed()");
View.OnClickListener acept = new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
handlerFinal.proceed();
}
};
View.OnClickListener cancel = new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
handlerFinal.cancel();
}
};
View.OnClickListener listeners[] = {cancel, acept};
dialog = UiUtils.showDialog2Buttons(activity, R.string.info, mensaje, R.string.popup_custom_cancelar, R.string.popup_custom_cancelar, listeners); }
In my situation:This error occured when we try to updated apk uploaded
into the Google Play store,and getting SSL Error:
Then i have used following code
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
try {
progressDialog.dismiss();
} catch (WindowManager.BadTokenException e) {
e.printStackTrace();
}
super.onPageFinished(view, url);
}
#Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
final AlertDialog.Builder builder = new AlertDialog.Builder(PayNPayWebActivity.this);
builder.setMessage(R.string.notification_error_ssl_cert_invalid);
builder.setPositiveButton("continue", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
handler.proceed();
}
});
builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
handler.cancel();
}
});
final AlertDialog dialog = builder.create();
dialog.show();
}
}

Integrating STS with AWSS3TransferManagerUploadRequest and AWSS3TransferManagerDownloadRequest

We are trying to implement AWS Security Token Service in our android and iOS app. At backend we are using below code to generate token:
public class CloudManagementImpl implements CloudManagement{
private static final Logger Log = LoggerFactory.getLogger(CloudManagementImpl.class);
#Override
public CloudConfiguration getCloudProperties() {
CloudConfiguration CloudConfiguration = new CloudConfiguration();
AssumeRoleRequest assumeRoleRequest = new AssumeRoleRequest();
assumeRoleRequest.setRoleArn(JiveGlobals.getProperty(XYZConstant.AWS_ARN_EC2_ROLE_MAP));
assumeRoleRequest.setRoleSessionName(XYZConstant.AWS_ROLE_SESSIONNAME);
assumeRoleRequest.setDurationSeconds(JiveGlobals.getIntProperty(XYZConstant.AWS_CREDENTIALS_LIFETIME, 1800));
AWSSecurityTokenServiceClient stsClient = new AWSSecurityTokenServiceClient();
AssumeRoleResult assumeRoleResult = stsClient.assumeRole(assumeRoleRequest);
if (assumeRoleResult != null) {
Credentials sessionCredentials = assumeRoleResult.getCredentials();
CloudConfiguration.setAwsAccessId(sessionCredentials.getAccessKeyId());
CloudConfiguration.setAwsAccessKey(sessionCredentials.getSecretAccessKey());
CloudConfiguration.setToken(sessionCredentials.getSessionToken());
CloudConfiguration.setAwsMainBucket(JiveGlobals.getProperty(XYZConstant.AWS_MAIN_BUCKET));
} else {
Log.error("Cloud Management :: Propery values not configured ");
}
return CloudConfiguration;
}
}
Generated token is then obtained in iOS and android app through a separate web-service call.
In android we are using below code to consume retrieved token:
public S3Client(String accessKey, String secretKey, String token, String bucketName) {
super();
this.accessKey = accessKey;
this.secretKey = secretKey;
this.bucketName = bucketName;
BasicSessionCredentials basicSessionCredentials = new BasicSessionCredentials(accessKey, secretKey, token);
amazonS3Client = new AmazonS3Client(basicSessionCredentials);
}
Problem is -
We do not have android like API in AWS mobile SDK version 2 for iOS,
using which we can consume the retrieved token, perhaps the best way
to achieve this thing in iOS is through AWSCognitoCredentialsProvider,
but we are not sure.
Please suggest - what is the best way to integrate AWS Security Token Service in iOS.
You need to implement your own credentials provider by conforming to AWSCredentialsProvider. Sounds like you already have a code snippet that retrieves the temporary credentials from your server. That logic should go into your custom credentials provider. You can take a look at the implementation of AWSWebIdentityCredentialsProvider and AWSCognitoCredentialsProvider for how to implement your own credentials provider.

LibGit2Sharp: Fetching fails with "Too many redirects or authentication replays"

Here's the code I'm using to fetch:
public static void GitFetch()
{
var creds = new UsernamePasswordCredentials()
{Username = "user",
Password = "pass"};
var fetchOpts = new FetchOptions {Credentials = creds};
using (repo = new Repository(#"C:\project");)
{
repo.Network.Fetch(repo.Network.Remotes["origin"], fetchOpts);
}
}
but it fails during fetch with the following exception:
LibGit2Sharp.LibGit2SharpException: Too many redirects or authentication replays
Result StackTrace:
at LibGit2Sharp.Core.Ensure.HandleError(Int32 result)
at LibGit2Sharp.Core.Proxy.git_remote_fetch(RemoteSafeHandle remote, Signature signature, String logMessage)
at LibGit2Sharp.Network.DoFetch(RemoteSafeHandle remoteHandle, FetchOptions options, Signature signature, String logMessage)
at LibGit2Sharp.Network.Fetch(Remote remote, FetchOptions options, Signature signature, String logMessage)
I have verified that the config file has the required remote name and that git fetch works from the command line. I found that the exception originates from libgit2\src\transport\winhttp.c but I couldn't come up with a workaround/solution.
I tried #Carlos' suggestion in the following way:
public static void GitFetch()
{
var creds = new UsernamePasswordCredentials()
{Username = "user",
Password = "pass"};
CredentialsHandler credHandler = (_url, _user, _cred) => creds;
var fetchOpts = new FetchOptions { CredentialsProvider = credHandler };
using (repo = new Repository(#"C:\project");)
{
repo.Network.Fetch(repo.Network.Remotes["origin"], fetchOpts);
}
}
I could fetch from public repos on github as well as from password protected private repos on bitbucket; however, I couldn't do the same for the repositories hosted over LAN at work. Turns out they were configured in a way which does not accept UsernamePasswordCredentials provided by libgit2sharp. The following modification allowed me to fetch from repositories over LAN:
CredentialsHandler credHandler = (_url, _user, _cred) => new DefaultCredentials();
(I'm trying to find out what is the exact difference between the two; if I get further insight into it, I'll update the answer.)
The shim that should make the Credentials option work is currently buggy (and is deprecated anyway), pass a CredentialsProvider instead as a callback.
This seems to be a very common error message.
We were getting it on pushes to GitHub, because credentials were disabled for security:
https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/
We've solved it by enabling SAML SSO and doing the push outside the C# code, but perhaps using SSH keys somehow with the library or personal access tokens fixes the problem too.