3
votes

How to authenticate against the Firebase rest api from Android when I have this database rule:

"TOY_STORE": {
  ".read": "auth != null",
  ".write": "auth != null"
},

If I set the ".read": "true" I can access a nod using this code

 com.loopj.android.http.AsyncHttpClient client = new AsyncHttpClient();
    client.get("https://xxx-project.firebaseio.com/TOY_STORE/.json?print=pretty&shallow=true?auth=HnhLyXRxUsadhj237eYiQ53",  new JsonHttpResponseHandler() {

// respons..
}

But when having ".read": "auth != null" it gíve permission denied.

Im signed in to Firebase usning Google credentials and the auth=HnhLyXRxUsadhj237eYiQ53 is my Firebase ID. I can read and write to database making regularly ValueEventListener and updateChildren calls.

I have also tried the Web API Key for auth but not working.

I want to run this code because of the Firebase REST API shallow-data

2

2 Answers

3
votes

If you want to read from firebase by rule ".read": "auth != null" and you do not want to use firebase api I recommend Retrofit2 library. You have to auth by Bearer service account token.

Warning! The token is valid only for one hour. Then you need to refresh the new token.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

....

//mykey.json you get from FBconsole/Project Settings/service accounts/generte new private key

    myFile = new File(mykey.json);


    GoogleCredential googleCred = null;
    try {
        googleCred = GoogleCredential.fromStream(new FileInputStream(myFile));
    } catch (IOException e) {
        e.printStackTrace();
    }
    GoogleCredential scoped = googleCred.createScoped(
            Arrays.asList(
                    "https://www.googleapis.com/auth/firebase.database",
                    "https://www.googleapis.com/auth/userinfo.email"
            )
    );
    try {
        scoped.refreshToken();
    } catch (IOException e) {
        e.printStackTrace();
    }
    token = scoped.getAccessToken();
    Log.d("token ", token);




}//end of oncreate

Button click for read from FB

public void onClick(View view) {


    authtoken = "Bearer " + token;

    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);

    OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    httpClient.addInterceptor(new Interceptor() {
        @Override
        public okhttp3.Response intercept(Chain chain) throws IOException {
            Request original = chain.request();

            // Request customization: add request headers
            Request.Builder requestBuilder = original.newBuilder()
                    .header("Authorization", authtoken); // <-- this is the important line
            Request request = requestBuilder.build();
            return chain.proceed(request);
        }
    });

    httpClient.addInterceptor(logging);
    OkHttpClient client = httpClient.build();



    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://yourproject.firebaseio.com")//url of firebase database app
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())//use for convert JSON file into object
            .build();

    // prepare call in Retrofit 2.0
    FirebaseAPI firebaseAPI = retrofit.create(FirebaseAPI.class);

    Call<Event> call2=firebaseAPI.getPrivateData();

    call2.enqueue(new Callback<Event>() {
        @Override
        public void onResponse(Call<Event> call, Response<Event> response) {

            Log.d("Response ", "onResponse");
            //t1.setText("success name "+response.body().getName());


        }

        @Override
        public void onFailure(Call<Event> call, Throwable t) {
            Log.d("Response ", "onFailure");
            //t1.setText("Notification failure");
        }
    });
}

FirebaseAPI.java

public interface FirebaseAPI {

@GET("/uploadprivate/event.json")
Call<Event> getPrivateData();

}

POJO event.java

public class Event {
String name;
String address;

public Event(String name, String address) {
    this.address = address;
    this.name = name;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getAddress() {
    return address;
}

public void setAddress(String address) {
    this.address = address;
}


}

Data in FB console

enter image description here

2
votes

The documentation for authenticating with the REST API can be found here. You need to pass an auth parameter in the query string with the value of the user's authentication token.

It's a really bad idea to put your database secret key into your app, which can be easily reverse engineered by anyone. But if you want to use the REST API from a server you control, you can find your database secret key in Project Settings -> Service Accounts -> Database Secrets.