Android Firebase Google SIgnon bad request - android

Android Firebase Google signin through authorization error when google return token id. i have both cleint id as well as web sdk key saved on firebase. Even json file.
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Log.w(TAG, "signInWithCredential", task.getException());
Toast.makeText(OnBoarding.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
}
// ...
}
});
Got this error
com.google.firebase.FirebaseException: An internal error has occured. [ Bad Request ]
at com.google.android.gms.internal.zzacq.zzbN(Unknown Source)
at com.google.android.gms.internal.zzacn$zzg.zza(Unknown Source)
at com.google.android.gms.internal.zzacy.zzbO(Unknown Source)
at com.google.android.gms.internal.zzacy$zza.onFailure(Unknown Source)
at com.google.android.gms.internal.zzact$zza.onTransact(Unknown Source)
at android.os.Binder.execTransact(Binder.java:565)
Though google signIn went well there is something missing with firebase which m not able to figure out need help
Logs
"error": {
"errors": [{
"domain": "usageLimits",
"reason": "keyExpired",
"message": "Bad Request"
}],
"code": 400,
"message": "Bad Request"
}
}

In the firebase console (Overview) Under Your mobile apps click the overflow button (three vertical dots) and goto Manage.
Once there goto your app and download the google-services.json
Add that to the root directory of your app and also to the /app folder.
This worked for me to fix this exact error. I assume I changed something at some point and needed a new one.
Hopefully this helps. Goodluck

Some reason to get [ Bad Request ].
Error Conditions:
The Firebase REST API will return error codes under these circumstances.
1) 404 Not Found : A request made over HTTP instead of HTTPS
2) 400 Bad Request : Unable to parse PUT or POST data
3) 400 Bad Request : Missing PUT or POST data
4) 400 Bad Request : Attempting to PUT or POST data which is too large
5) 417 Expectation Failed : A REST API call that doesn't specify a Firebase name
6) 400 Bad Request : A REST API call that contains invalid child names as part of the path
7) 403 Forbidden : A request that violates your Security and Firebase Rules
Check which type of parameter or other things are missing in request as per above option.
I hope its helps you.

Related

How to use Firestore Database and Datastore in same Android App

I want to use a Firestore database and Datastore in the same Android app. I know that it's not possible to use both in the same GCP project(explained here: Firestore and Datastore in the same GAE project) so I created two different projects, one for the Firestore and one for the Datastore. So now the problem is that I can't create a client Id for my Android app in both projects because of "duplicated fingerprints".
If I had just one project I normally would just login via Firebase AuthUi and then use the token from the FirebaseUser to build my service handler.
//login via FirebaseUI
FirebaseAuth auth = FirebaseAuth.getInstance();
AuthUI.getInstance().createSignInIntentBuilder()
.setTheme(getSelectedTheme())
.setLogo(getSelectedLogo())
.setAvailableProviders(getSelectedProviders())
.setTosAndPrivacyPolicyUrls(getSelectedTosUrl(),getSelectedPrivacyPolicyUrl())
.setIsSmartLockEnabled(true,true)
.build(),
FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
Task<GetTokenResult> tokenResultTask = firebaseUser.getIdToken(false);
tokenResultTask.addOnCompleteListener(task -> {
String result = task.getResult().getToken();
//Creating the service object
GoogleCredential credential = new GoogleCredential();
credential.setAccessToken(result);
EndpointsApi.Builder builder = new EndpointsApi.Builder(
AppConstants.HTTP_TRANSPORT,
AppConstants.JSON_FACTORY, credential);
builder.setApplicationName("endpointsapi-server");
return builder.build();
});
This works very well if I only have one project. But what to do if there are mutliple? The google-services.json is associated with the one project that also has the android client id, but the second project can't create an android client id using the same sha1 and package name(duplicated fingerprints).
If I just use the access token from the first project to build the service object(which belongs to the second project) I just get an error:
401 Unauthorized
{
"code": 401,
"errors": [
{
"domain": "global",
"message": "Authorization required",
"reason": "required"
}
],
"message": "Authorization required"
}
which makes sense, because the second project doesn't know about the first one. Im lost on what to do to somehow use both at the same time.
In my web app I just whitelist the web client of the first project in the second one and then use the credentials of the first, obtained using firebase.AuthUi, to also login the second one. Which works.
this.uiConfig = {
callbacks: {
signInSuccess: (currentUser, credential, redirectUrl) => {
const googleAuthcredential =
firebase.auth.GoogleAuthProvider.credential(credential['idToken']);
firebase.apps[1].auth().signInAndRetrieveDataWithCredential(googleAuthcredential):
}
}
};
this.ui = new firebaseui.auth.AuthUI(firebase.auth());
this.ui.start('#firebaseui-auth-container', this.uiConfig);
How to achieve the same thing in Android?
Thank you very much in advance.

ApiException on silent signing using GoogleSignInClient on Android

I get following error frequently when I try to sign in silently on android. How can I debug this. What is the reason for this. (I have an active google account on my android phone.)
signInSilently(): failure
com.google.android.gms.common.api.ApiException: 4:
at com.google.android.gms.common.internal.zzb.zzz(Unknown Source)
at com.google.android.gms.common.internal.zzbk.zzaa(Unknown Source)
at com.google.android.gms.common.internal.zzbl.zzs(Unknown Source)
at com.google.android.gms.common.api.internal.zzs.zzc(Unknown Source)
at com.google.android.gms.common.api.internal.zzs.setResult(Unknown Source)
at com.google.android.gms.auth.api.signin.internal.zzg.zza(Unknown Source)
at com.google.android.gms.auth.api.signin.internal.zzt.onTransact(Unknown Source)
at android.os.Binder.execTransact(Binder.java:446)
the code is follows
mGoogleSignInClient.silentSignIn().addOnCompleteListener(activity,
new OnCompleteListener<GoogleSignInAccount>() {
#Override
public void onComplete(#NonNull Task<GoogleSignInAccount> task) {
if (task.isSuccessful()) {
Log.d(TAG, "signInSilently(): success");
onConnected(task.getResult());
} else {
Log.d(TAG, "signInSilently(): failure", task.getException());
Toast.makeText(activity, "A sign-in problem encountered.",
Toast.LENGTH_SHORT).show();
onDisconnected();
}
}
});
There is a list of error codes
According to it, your error code means following:
public static final int SIGN_IN_REQUIRED
The client attempted to connect to the service but the user is not signed in. The client may choose to continue without using the API. Alternately, if hasResolution() returns true the client may call startResolutionForResult(Activity, int) to prompt the user to sign in. After the sign in activity returns with RESULT_OK further attempts should succeed.
Constant Value: 4
It means, that user needs to login manually before you can use silentSignIn. You can find an example on Google github
That error happened to me because I haven't added the email I was testing with to the Testers tab in Google Play Games Console.
I believe it also occurs if your build hasn't been signed with the same SHA1 key that your google play games app id was generated with

GoogleJsonResponseException 403 Forbidden PERMISSION_DENIED

I'm using google REST Api to retrieve list of spreadsheets.
Everything works when it is accessed by my account.
But when I try to use foreign account, I'm getting this error:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden {
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "The caller does not have permission",
"reason" : "forbidden"
} ],
"message" : "The caller does not have permission",
"status" : "PERMISSION_DENIED"
}
It says I have no access to my google script, but the script is set as visible and shared for anyone.
Code:
private Object getDataFromApi(ExecutionRequest request)
throws IOException
{
if (BuildConfig.DEBUG) {
request.setDevMode(true); // it will take saved version of script and not the published one
}
// Make the request.
Operation op =
mService.scripts().run(SCRIPT_ID, request).execute();
Change the SCOPE from SheetsScopes.SPREADSHEETS_READONLY to SheetsScopes.SPREADSHEETS.
private static final List SCOPES = Arrays.asList(SheetsScopes.SPREADSHEETS);
I found the problem was in code:
if (BuildConfig.DEBUG) {
request.setDevMode(true); // it will take saved version of script and not the published one
}
It looks like it alway force to access saved version and not the published. Then the foreign account had no access to saved version and returns error 403.
When I disable this dev mode or install release version, then everything is ok.

How to import a message with the Gmail API in Java

I've studied this page:
https://developers.google.com/gmail/api/v1/reference/users/messages/import
I have some messages I will be keeping track of in my Android program. I will be keeping a record of the messages I will be deleting and I would like to import those messages slated for deletion into a new folder (In Gmail API folders are called Labels).
I tried the test form:
POST https://www.googleapis.com/gmail/v1/users/omitted%40gmail.com/messages/import?deleted=false&internalDateSource=dateHeader&neverMarkSpam=true&processForCalendar=false&key={YOUR_API_KEY}
{
"payload": {
"body": {
"data": "hellio"
}
}
}
Response:
400 OK
- SHOW HEADERS -
{
"error": {
"errors": [
{
"domain": "global",
"reason": "invalidArgument",
"message": "'raw' RFC822 payload message string or uploading message via /upload/* URL required"
}
],
"code": 400,
"message": "'raw' RFC822 payload message string or uploading message via /upload/* URL required"
}
}
There is a problem sending the request but I am not sure at all what it means. What I need is some Java that sends a request that will import a message where I can specify the body, received date and subject line. Is it possible?
Thank you.
P.S. I just wanted to delete the attachments not the whole message but after reading the Gmail API documents it looks like this is not possible and is only possible through IMAP. The reason I am asking this question is so that I don't have to move my whole program to IMAP.
You are pretty close with your code. What you need to do is write a mail compliant with the RFC 2822 standard, and Base64-encode said mail and make it URL-safe (replace all + with - and all / with _) before inserting it.
You are better at Java than me, but if I would make a correct message in the browser's Developer Console, it could look something like this:
var encodedMail = btoa(
"Date: Thu, 1 Jan 1970 12:00:00 -0000\n" +
"From: emtholin#gmail.com\n" +
"To: emtholin#gmail.com\n" +
"Subject: Example Subject\n\n" +
"This is the body of the mail"
).replace(/\+/g, '-').replace(/\//g, '_');
Then I just insert this mail with the same request you issued:
POST https://www.googleapis.com/gmail/v1/users/me/messages?internalDateSource=dateHeader&key={YOUR_API_KEY}
{
"raw": "RGF0ZTogVGh1LCAxIEphbiAxOTcwIDEyOjAwOjAwIC0wMDAwCkZyb206IGVtdGhvbGluQGdtYWlsLmNvbQpUbzogZW10aG9saW5AZ21haWwuY29tClN1YmplY3Q6IEV4YW1wbGUgU3ViamVjdAoKVGhpcyBpcyB0aGUgYm9keSBvZiB0aGUgbWFpbA=="
}
As you can see, this worked great!

Check android purchase status but return the purchase token was not found

I refered google play android api to check the purchase and consumption status of an in-app item.
For some orders, I can get right result,but some return the error as below:
error: {
errors: [
{
domain: "global",
reason: "purchaseTokenNotFound",
message: "The purchase token was not found.",
locationType: "parameter",
location: "token"
}
],
code: 404,
message: "The purchase token was not found."
}
Purchase token is provided by google, does it can be faked?
I found if I cancel the google order, then check the purchase status,it will return the purchase token was not found. if not, i will get the right purchase status.
Hope somebody can help.
If you are selling the same INAPP product to the same user muliple times within a short period, then it's very likely that all access tokens except the last purchase will return a 404 code.
For example:
john#example.com went to your app and purchased com.example.test.product a few times, you will probaly notice within your records (or Google Wallet Merchant account) that it's the same user buying the product.
When you go to check the last purchase from this user, then the following is likely to appear
{
kind: "androidpublisher#inappPurchase",
purchaseTime: "1409823171827",
purchaseState: "0",
consumptionState: "1",
developerPayload: "My Product | Ref | 1409823162466"
}
and yet if you were to check his previous tokens, then it's very likely that his purchases will return 404!
I had read somewhere (can't remember where) that the purchase token created for each purchase is basically based on the inapp product and google user. Therefore, it's very likely that each purchase will "destroy" any previous purchase token created for the same user.
Hope this explanation helps. I am constantly having this problem everyday when my server is attempting to connect to the Google API and check the transactions. Perhaps one day somebody will read this and provide a solution :)
The documents are misleading. You don't need to use this API to verify purchases.
Mobile app have INAPP_PURCHASE_DATA and INAPP_DATA_SIGNATURE from getBuyIntent method.
You can verify the purchase with the signature and your public key.
https://developer.android.com/google/play/billing/billing_reference.html#getBuyIntent
You can find the public key on Google Play Developer Console -> YOUR_APP -> service and API
package main
import (
"crypto"
"crypto/rsa"
"crypto/sha1"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
)
//replace const below with your own.
const (
pubKeyPEM=`-----BEGIN PUBLIC KEY-----
Some thing like this
-----END PUBLIC KEY-----`
data = `purchase data from getBuyIntent API`
sign = `purchase data signature from getBuyIntent API`
)
func Panic(err error) {
if err != nil {
panic(err)
}
}
func main() {
PEMBlock, _ := pem.Decode([]byte(pubKeyPEM))
if PEMBlock == nil {
Panic(fmt.Errorf("Could not parse Public Key PEM"))
}
if PEMBlock.Type != "PUBLIC KEY" {
Panic(fmt.Errorf("Found wrong key type"))
}
pubkey, err := x509.ParsePKIXPublicKey(PEMBlock.Bytes)
if err != nil {
Panic(err)
}
// compute the sha1
h := sha1.New()
h.Write([]byte(data))
// decode b64 signature
signature, err := base64.StdEncoding.DecodeString(sign)
Panic(err)
// Verify
err = rsa.VerifyPKCS1v15(pubkey.(*rsa.PublicKey), crypto.SHA1, h.Sum(nil), signature)
Panic(err)
// It verified!
fmt.Println("OK")
}

Categories

Resources