3

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

Community
  • 1
  • 1
Tord Larsen
  • 2,670
  • 8
  • 33
  • 76

2 Answers2

3

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

eurosecom
  • 2,932
  • 4
  • 24
  • 38
  • I accept this because it answer the Q. Must give a warning to others regarding what @DougStevenson say about this – Tord Larsen Mar 31 '17 at 05:55
  • Of course. To send private info through http connection it is everytime danger. Definitely you can not put the server key into App. To solve secure storage and read Server key is next question. – eurosecom Mar 31 '17 at 06:37
  • But doesn't this need the key.json file inside an app anyway? – Kushan Apr 11 '17 at 13:24
  • You do not need key.json inside an app. You can put key.json anywhere. – eurosecom Apr 11 '17 at 13:47
2

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.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441