0

I previously asked question to secure realtime database on firebase. I am only using Firebase Realtime database just to creating chat app. The user verification working separately on our own server and we are not using any firebase auth service for user verification. As Frank van Puffelen suggested few official docs. I am now generating JWT to authorize as per documentation but as we are not using any other services of firebase i am not sure how to authorized the real time database with generated JWT.

mAuth.signInWithCustomToken(mCustomToken)
    .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
        @Override
        public void onComplete(@NonNull Task<AuthResult> task) {
            if (task.isSuccessful()) {
                // Sign in success

            } else {
                // If sign in fails
                Toast.makeText(CustomAuthActivity.this, "Authentication failed.",
            }
        }
    });

How to validate users and secure our database from world so only app user can edit their node only.

I followed this guide for Authenticate with Firebase with custom token.

  • User login with their credential
  • Server generate custom token (JWT).
  • Pass it to signInWithCustomToken as per doc.
  • What after that? guide bit incomplete for my use case.

Edit: The process:

Server generates JWT With PHP Firebase JWT

   $Token = JWT::encode($request_data,$secret_Key,'HS512');

this token return back to app if user login successfully.

After successfully user login i call sign in with custom token i received from server with firebase

firebaseAuth = FirebaseAuth.getInstance();
       firebaseAuth.signInWithCustomToken(Session.getJWT())
    .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
        @Override
        public void onComplete(@NonNull Task<AuthResult> task)    {             
        if (task.isComplete()){
            Intent intent=new Intent(getActivity(),MainActivity.class);
            getActivity().startActivity(intent); 
            }           
        }   
    });

When user click chat button. Check if room already exist or not if not then create one for 2 users with their phone numbers like 9810012345-9810012346

    DatabaseReference db = rebaseDatabase.getInstance().getReference();
      
      
      db.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                if (dataSnapshot.hasChild(RoomTitle)) {
                    RoomName(RoomTitle, true);
                }else {
                    RoomName(RoomTitle, false);
                }
            }
    
            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });

public void RoomName(String Name, boolean RoomExist) {
    button_SendMessage.setEnabled(true);
    if (!RoomExist) {
        Log.d(TAG, "Room Not Exist Creating One);
        RoomName.put(Name, "");
        FireBaseDatabase.updateChildren(RoomName);
    }

        // Launch Chat Screen

}

Then on chat screen i add items like linked question database structure

databaseReference = FirebaseDatabase.getInstance().getReference().child(Room_Name);

So creating room,allow reading writing message only created room, block access if room doesn't belong to users. I need to set rules for Realtime Database and only app users can access their rooms not others even they are app users(Block others app users to sneak into others users rooms) Below is the sample of our Realtime Database structure for better understanding how our 2 user room look like. I am not sure there is much thing to do on app side, i feel it's more database than app code question.

enter image description here

androidXP
  • 1,692
  • 3
  • 27
  • 58

1 Answers1

0

Once your call to signInWithCustomToken succeeds, that token will be passed to the server whenever the Firebase Realtime Database SDK connects, and from there on it will be verified and passed on to the auth variable in your security rules.

So you can check if the request comes from a signed-in user with:

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

That's a bit broad though, so you'll want to narrow it down to specific users. For example, you can allow only a content-owner access with:

{
  "rules": {
    "some_path": {
      "$uid": {
        // Allow only authenticated content owners access to their data
        ".read": "auth !== null && auth.uid === $uid",
        ".write": "auth !== null && auth.uid === $uid"
      }
    }
  }
}

Any claims you have in your JWT will be available in the security rules too under the auth.token variable.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks for the quick answers. I will try to implement it and see if it works. Thanks again. :) – androidXP Nov 08 '22 at 00:04
  • I am trying the guide with custom token i need to hand over our JWT key to Firebase to decode? There is not much info about custom validation like ours in docs. Is there any way to debug calls to database which can include data like JWT and other info exchanging ? – androidXP Nov 13 '22 at 14:11
  • You pass the token to Firebase when you call `signInWithCustomToken`. Once that succeeds, the token is passed to the database security rules with every API call by the SDK. --- There's nothing specific to custom tokens after that, as all the information from your token is available in the `auth.token` variable - just as it is for tokens minted by Firebase's built-in providers. --- To make debugging the token info easier, you can use the emulators: which show more info: https://firebase.google.com/docs/emulator-suite. – Frank van Puffelen Nov 13 '22 at 16:04
  • My app generates token on server when user login on our app and we keep that token on app side for API verification and i am passing same token to firebase after user successfully login at `signInWithCustomToken` . On later stage whenever user wants to initiate chat (connects Real time database) by `DatabaseReference db = FirebaseDatabase.getInstance().getReference();` So this call with suffix add unique room for every 2 users. I am able to verify JWT (Anyone can generate random JWT token) with rules whether it's coming from verified users or not. – androidXP Nov 13 '22 at 21:42
  • If you want to verify whether the ID token was created by your own code, [include a custom claim](https://firebase.google.com/docs/auth/admin/custom-claims) in the token that you can then find in `auth.token`. --- If after all of this you're still having trouble making it work, please provide an update to your question with the (updated) code of how you mint a token (with the custom claim) and how you check for that claim in the security rules. – Frank van Puffelen Nov 13 '22 at 21:51
  • Sure. I will update my code which can show you better insight what actually i am trying to do . Thanks alot for your help :) – androidXP Nov 13 '22 at 21:56
  • Please check update question. If i miss anything there please let me know. I tried different rules including the one you mentioned `auth.token` but i always get `DatabaseError: Permission denied` – androidXP Nov 14 '22 at 02:33