I'm picking up a project from last year that was based on the now discontinued 'mobile backend starter' from Google. I believe the app was left in a working state but it now seems to fail the authentication when the "Secured by Client IDs" setting is selected on the web page google provided. I get the following error:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
{
"code": 401,
"errors": [
{
"domain": "global",
"location": "Authorization",
"locationType": "header",
"message": "Unauthenticated calls are not allowed",
"reason": "required"
}
],
"message": "Unauthenticated calls are not allowed"
}
The error results from running this method
private void listPosts(final String alertTxt) {
// create a response handler that will receive the result or an error
CloudCallbackHandler<List<CloudEntity>> handler =
new CloudCallbackHandler<List<CloudEntity>>() {
#Override
public void onComplete(List<CloudEntity> results) {
//mAnnounceTxt.setText(R.string.announce_success);
mAnnounceTxt.setText(alertTxt);
mPosts = results;
animateArrival();
updateGuestbookView();
}
#Override
public void onError(IOException exception) {
mAnnounceTxt.setText(R.string.announce_fail);
animateArrival();
handleEndpointException(exception);
}
};
...
I am not really sure where/how to start debugging this?
401 Errors are usually caused by any of the following:
Expired token
Token revocation
Token not authorized for needed scopes
Request not authorized correctly with OAuth
Try refreshToken() to resolve expired token issues
Related
Ii have configured android for FCM.
public class DERFirebaseInstanceIDService extends FirebaseInstanceIdService {
#Override
public void onTokenRefresh() {
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
}
}
The token that I get from firebase server is following
"c5pu6rD06ts:APA91bHEgXUbJR8UegRPnLMgowEC6QxUPP73TiSBIHG1Pe0I8u22298rjpbXBsK94ExTmTbL0VT009AhsIqgMSkoLFZJDuaPSpaLlqBAyIrrtzsdLuWhvCp6CtkZwMT88P-WxBFCT2DH"
This token contains double quotations. So what I am doing wrong that server send me this token. Can any one help me..?
Due to this , when server send request to this token I am getting following error
"message": "The registration token is not a valid FCM registration
token",
"domain": "global",
"reason": "badRequest"
I am using Retrofit 2.1.0 with Jackson to make an API call.
The remote api gives two different response one which has json object with string and one custom object. and another response cary only status and error message.like below
required response
{
"status": "success",
"data": {
"id": 79068,
"username": "neha.fren01#gmail.com",
"email": "neha.fren01#gmail.com",
"enabled": false,
"confirmation_token": "27090745",
"name": "ronem",
"premium": false,
"token": "nmdgZe5Put6kS1KC_KH5d8Tk-fZLxZ15bV5tahJwQlY",
"phone_verified": false,
"email_verified": false
}
}
error response
{
"status": "error",
"message": "Unable to create userERROR: Email you entered is invalid. Provide another email.\n"
}
I can handle the required response shown above.but cannot handle the error response.
Here is the code how I made call
call.enqueue(new Callback<RegisteredResponse>() {
#Override
public void onResponse(Call<RegisteredResponse> call, Response<RegisteredResponse> response) {
if (response.isSuccessful()) {
try {
EventBus.post(new Events.RegistrationResponseEvent(StaticStorage.REGISTRATION_IDENTIFIER, response.body()));
} catch (Exception e) {
e.printStackTrace();
// EventBus.post(new Events.ErrorEvent(StaticStorage.REGISTRATION_IDENTIFIER, response.errorBody().toString()));
}
}else{
// I want to handle error response here.but error response is present inside response.isSuccessful() block
}
}
#Override
public void onFailure(Call<RegisteredResponse> call, Throwable t) {
t.printStackTrace();
EventBus.post(new Events.ErrorEvent(StaticStorage.REGISTRATION_IDENTIFIER, StaticStorage.ERROR_IN_LOADING));
}
});
Even the response object is error response it always goes to
response.isSuccessful()
block
I am unable to solve this issue. I lost 2 hours searching solution.
I followed this link aswell
response.isSuccessful()
Retrofit is depend on what status code you are getting from the server. even in failure if server still sending you 200 responseCode then there is no way you will get it in onError
means your api call was successful and response came. Doesn't matter what response came from server. For that you have to manually parse response and check whether your Json object has error or success status.
As per my opinion you have to make the response universal for all the web service. like
Sucess
{
"status": true,
"data": {
"id": 79068,
"username": "neha.fren01#gmail.com",
"email": "neha.fren01#gmail.com",
"enabled": false,
"confirmation_token": "27090745",
"name": "ronem",
"premium": false,
"token": "nmdgZe5Put6kS1KC_KH5d8Tk-fZLxZ15bV5tahJwQlY",
"phone_verified": false,
"email_verified": false
}
"message": ""
}
Error
{
"status": false,
"data":{},
"message": "Unable to create userERROR: Email you entered is invalid. Provide another email.\n"
}
Please change to status boolean flag, you have to check status of the response. If it is true then response is sucessfull if false then there is some error in response.
response.isSuccessful()
instead of above you need to check the status code of the server response, if it is 200 then web service sucessfully called.
I am trying to consume Google's Beacon Proximity api. i have followed following steps to integrate them:
1) Signed up on Google Api Console.
2) Created new Project.
3) enabled Beacon proximity api and Nearby Api.
4) Generated Api key from Credentials.
Afterwards i invoke the following api:
{
"advertisedId": {
"type": "EDDYSTONE",
"id": "ABEiM0RVZneImaq7zN3u/w=="
},
"status": "ACTIVE",
"placeId": "ChIJL_P_CXMEDTkRw0ZdG-0GVvw",
"latLng": {
"latitude": "71.6693771",
"longitude": "-22.1966037"
},
"indoorLevel": {
"name": "1"
},
"expectedStability": "STABLE",
"description": "An example beacon.",
"properties": {
"position": "entryway"
}
}
with the follwing url:
https://proximitybeacon.googleapis.com/v1beta1/beacons:register?key=xxxx(my_api_key)
but the response says:
{
"error": {
"code": 403,
"message": "Unauthorized.",
"status": "PERMISSION_DENIED"
}
}
what is it that i am missing..
I also tried to use Beacon tools app but after entering EID and all other credentials..the App crashes(on android), while it is not able to connect to my eddystone on Ios.
Found the Solution, API_KEY can be used only to Access already registered beacons and their Characteristics, while to Register and update we require ClientId and client Secret key and you can register it in OAuth2.0 Playground.
it worked for me ;)
You can Get a service token after creating an account service key on the google API Console. Then generate it with this code:
String token = null;
try{
GoogleCredential credential = GoogleCredential.fromStream(accesKey).createScoped
(Collections.singleton("https://www.googleapis.com/auth/userlocation.beacon.registry"));
credential.refreshToken();
token = credential.getAccessToken();
} catch (FileNotFoundException ex) {
Logger.getLogger(BeaconRegisterClass.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(BeaconRegisterClass.class.getName()).log(Level.SEVERE, null, ex);
}
Then put it on the header of your call:
key: Authorization value: Bearer (your token here)
set the body of this call as beacon.json
I had a working app with Facebook & Email Login feature, since I upgrade the Firebase console (only, the sdk has not been update).
The app release before the Firebase 3.0 was working before, but it is not anymore able to sign/log with Facebook after the console has been upgraded.
What I have done:
1 - Upgraded the Firebase console
Because of Firebase & Facebook console update, I also had to put the Oauth Callback to the Facebook App
2 - Pasted the Firebase Facebook OAuth Callback to the Facebook console (before it was void) `https://xxx.firebaseapp.com/__/auth/handler``
The Exception:
The firebase Auth listener trigger a Firebase Error :
Invalid authentication credentials provided. and Facebook :
{"providerErrorInfo":{"code":400,"message":"Unsuccessful debug_token
response from Facebook: {\"error\":{\"message\":\"(#100) You must
provide an app access token or a user access token that is an owner or
developer of the
app\",\"type\":\"OAuthException\",\"code\":100,\"fbtrace_id\":\"DG4lLRJHFBS\"}}"}}
The FirebaseError Code:
In the decompiled code of the FirebaseAndroidSdk, the error object is:
0 = {java.util.LinkedHashMap$LinkedEntry#22680} "code" ->
"INVALID_CREDENTIALS"
1 = {java.util.LinkedHashMap$LinkedEntry#22681}
"message" -> "Invalid authentication credentials provided."
2 = {java.util.LinkedHashMap$LinkedEntry#22682} "details" ->
"{"providerErrorInfo":{"code":400,"message":"Unsuccessful debug_token
response from Facebook: {\"error\":{\"message\":\"(#100) You must
provide an app access token or a user access token that is an owner or
developer of the app\",\"type\":\"OAuthException\",\"code\":100,\"fbtrace_id\":\"BtB3JF2qmku\"}}"}}"
with the decompiled code:
private void makeAuthenticationRequest(String urlPath, Map<String, String> params, AuthResultHandler handler) {
final AuthenticationManager.AuthAttempt attempt = this.newAuthAttempt(handler);
this.makeRequest(urlPath, HttpRequestType.GET, params, Collections.emptyMap(), new RequestHandler() {
public void onResult(Map<String, Object> result) {
Object errorResponse = result.get("error");
String token = (String)Utilities.getOrNull(result, "token", String.class);
if(errorResponse == null && token != null) {
if(!AuthenticationManager.this.attemptHasBeenPreempted(attempt)) {
AuthenticationManager.this.authWithCredential(token, result, attempt);
}
} else {
FirebaseError error = AuthenticationManager.this.decodeErrorResponse(errorResponse);
AuthenticationManager.this.fireAuthErrorIfNotPreempted(error, attempt);
}
}
public void onError(IOException e) {
FirebaseError error = new FirebaseError(-24, "There was an exception while connecting to the authentication server: " + e.getLocalizedMessage());
AuthenticationManager.this.fireAuthErrorIfNotPreempted(error, attempt);
}
});
}
At AuthListener level, the firebaseError code : -20
https://www.firebase.com/docs/java-api/javadoc/com/firebase/client/FirebaseError.html
The specified authentication credentials are invalid.
The Facebook Error Code:
code 400
Nothing relevant found here : https://developers.facebook.com/docs/graph-api/using-graph-api/#errors
The code for Authing:
public void authWithFirebase(final String provider, Map<String, String> options) {
if (options.containsKey(AUTH_OPTIONS_ERROR)) {
EventBus.getDefault().post(new MessageToDisplayEvent(options.get(AUTH_OPTIONS_ERROR), true));
} else {
if (provider.equalsIgnoreCase(AUTH_PROVIDER_TWITTER)) {
// if the provider is twitter, we must pass in additional options, so use the options endpoint
ref.authWithOAuthToken(provider, options, new AuthResultHandler(provider));
} else {
// if the provider is not twitter, we just need to pass in the oauth_token
ref.authWithOAuthToken(provider, options.get(AUTH_OPTIONS_TOKEN), new AuthResultHandler(provider));
}
}
}
TOKEN Validity:
From the code above, the Token is confirmed valid since :
https://graph.facebook.com/app?access_token=%7Byour_access_token%7D return a valid JSON
And the Facebook Tool AccessToken https://developers.facebook.com/tools/debug/accesstoken return a still valid TOKEN
What changed from user point of view:
Now, When I click on the FacebookLoginButton, I have a new dialog that ask "connection as %FacebookUserName", with 2 buttons ("Unconnect" & "Cancel")
I posted a bug report at Firebase, but I even do not know if this is Facebook or Firebase, any help, advise for exploring new issue surface or solution is welcome.
In Facebook Developper Console, switch-off the option about the "app key that is integrated in the client".
For me this changed the behavior. I will give more information as far I get from Firebase/Facebook
Here is a French Screenshot to help you setting up Facebook:
In order to implement social features in an android app, I try to use the "writeMoment" method of the "PlusClient" class, but nothing happens. I am able to get a successful connection with "PlusClient" and to write deep link posts with my app.
Here is my code when I open the Google+ connection :
monPlusClient = new PlusClient.Builder(this,
new GooglePlayServicesClient.ConnectionCallbacks() {
#Override
public void onConnected() {
plusencours = false;
String accountName = monPlusClient.getAccountName();
// We've resolved any connection errors.
Toast.makeText(
ActiviteAfficher.this,
accountName
+ " "
+ ActiviteAfficher.this
.getResources()
.getString(
R.string.texteconnexion),
Toast.LENGTH_LONG).show();
// Log.d(TAG_DEBUG, accountName + " connected");
}
#Override
public void onDisconnected() {
plusencours = false;
// Log.d(TAG_DEBUG, "disconnected");
}
}, new GooglePlayServicesClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult resultat) {
if (resultat.hasResolution()) {
try {
resultat.startResolutionForResult(
ActiviteAfficher.this,
REQUEST_CODE_RESOLVE_ERR);
} catch (SendIntentException e) {
plusencours = true;
monPlusClient.connect();
}
}
// Save the result and resolve the connection failure
// upon a user click.
mConnectionResult = resultat;
}
})
.setVisibleActivities("http://schemas.google.com/AddActivity",
"http://schemas.google.com/DiscoverActivity")
.setScopes(Scopes.PLUS_LOGIN, Scopes.PLUS_PROFILE).build();
And here is my code when I use "writeMoment" :
ItemScope target = new ItemScope.Builder()
.setId(monSujet.getMid())
.setName(
monSujet.getName() + " - "
+ monSujet.getNotablename())
.setDescription(dialoguedescription).setImage(urlimage)
.setType("http://schema.org/Person").build();
Moment moment = new Moment.Builder()
.setType("http://schemas.google.com/AddActivity")
.setTarget(target).build();
if (monPlusClient.isConnected()) {
monPlusClient.writeMoment(moment);
}
Understanding the logcat is difficult for me :
05-09 12:00:32.380: I/ElegantRequestDirector(27290): I/O exception (org.apache.http.NoHttpResponseException) caught when processing request: The target server failed to respond
05-09 12:00:32.380: I/ElegantRequestDirector(27290): Retrying request
05-09 12:00:33.000: E/Volley(27290): [3428] BasicNetwork.performRequest: Unexpected response code 400 for https://www.googleapis.com/plus/v1/people/me/moments/vault
05-09 12:00:33.050: D/SyncManager(295): failed sync operation XXXXXXX#gmail.com (com.google), com.google.android.gms.plus.action, USER, earliestRunTime 140603923, SyncResult: stats [ numIoExceptions: 1]
05-09 12:00:33.050: D/SyncSetupManager(16157): setState: sync = true, wantedSyncState = true
05-09 12:00:33.090: D/SyncSetupManager(16157): Enabling sync
If you're having problems debugging issues while writing app activities, you should try enabling debug for GooglePlusPlatform:
adb shell setprop log.tag.GooglePlusPlatform VERBOSE
Which is also described here - https://developers.google.com/+/mobile/android/getting-started#frequently_asked_questions
Running your code with debugging enabled writes the following to logcat:
D/GooglePlusPlatform(8133): Unexpected response code (400) when requesting: writeMoment
D/GooglePlusPlatform(8133): Error response: {
D/GooglePlusPlatform(8133): "error": {
D/GooglePlusPlatform(8133): "errors": [
D/GooglePlusPlatform(8133): {
D/GooglePlusPlatform(8133): "domain": "global",
D/GooglePlusPlatform(8133): "reason": "badRequest",
D/GooglePlusPlatform(8133): "message": "Missing metadata field: http://schema.org/url."
D/GooglePlusPlatform(8133): }
D/GooglePlusPlatform(8133): ],
D/GooglePlusPlatform(8133): "code": 400,
D/GooglePlusPlatform(8133): "message": "Missing metadata field: http://schema.org/url."
D/GooglePlusPlatform(8133): }
D/GooglePlusPlatform(8133): }
You cannot supply a Person object without supplying a public target URL which has appropriate markup (instead of an explicit name and description). Running your code with http://schema.org/Thing instead of http://schema.org/Person worked for me.