I'm having a problem pulling images from Firebase Storage. I get the error message:
com.google.firebase.storage.StorageException: User does not have permission to access this object.
I have changed the permissions in firebase to all of the following and none of them work.
1.
service firebase.storage {
match /b/wics-application.appspot.com/o {
match /public/{allPaths=**} {
allow read, write: if request.auth == null;
}
match /user/{allPaths=**} {
allow read, write: if request.auth == null;
}
match /auth/{allPaths=**} {
allow read, write: if request.auth == null;
}
}
}
2.
service firebase.storage {
match /b/wics-application.appspot.com/o {
match /{allPaths=**} {
allow read, write;
}
}
}
Is there any other reason that I could be getting this message?
Have you created an instance of FirebaseUser?
FirebaseAuth mAuth;
FirebaseUser mUser;
Above onCreate and in onCreate
mAuth = FirebaseAuth.getInstance();
mUser = mAuth.getCurrentUser();
Then call your storage
Related
Register Button in Register Acvtivity
public void registerBtnClicked(View view){
String email = binding.userEmailEditText.getText().toString();
String password = binding.userPasswordEditText.getText().toString();
String userNameData = binding.usernameEditText.getText().toString();
user = new Users(userNameData,email,password);
db = FirebaseDatabase.getInstance();
databaseReference = db.getReference(Users.class.getSimpleName());
databaseReference.push().setValue(user);
if(email.equals("") || password.equals("")){
Toast.makeText(this, "Enter email and password", Toast.LENGTH_LONG).show();
}else{
auth.createUserWithEmailAndPassword(email,password).addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
Intent intent = new Intent(RegisterPage.this, MainActivity.class);
startActivity(intent);
finish();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(RegisterPage.this, e.getLocalizedMessage(),Toast.LENGTH_LONG).show();
}
});
}
}
I created a real time database.But I couldn't figure out how to show username in navigation header section. Can you help me?
If I understand correctly, the firebaseUser is null when you're trying to read the display name from it. This is actually a common scenario, as the user's sign-in session is managed by Firebase in the background, and the current user may change at any time.
The simple fix is to check whether there is a current user before accessing their display name, which you can do with:
firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
if (firebaseUser != null) {
navUserEmail.setText(firebaseUser.getEmail());
navUserName.setText(firebaseUser.getDisplayName());
}
Note though that the display name is an optional property of the user profile, so it can indeed be null. If you want to display nothing in that case, you can do:
String displayName = firebaseUser.getDisplayName();
navUserName.setText(displayName != null ? displayName : "");
Even if you've set the display name of a user, it may take up to an hour until that is updated for all connected clients, as they all cache the user profile. And since such updates happen in the background... 👇
To correctly handle all auth state changes, you'll want to use an auth state listener, as shown in this article: https://stackoverflow.com/collectives/google-cloud/articles/68104924/listen-for-authentication-state-in-android
So I have come across a problem and I seem to not be able to figure it out. I am using Firebase Auth the problem with that firebase will assign a generated user id, so I have made a Realtime Database to have user info and store a unique username. Now I am having a hard time reading the username from the database. Any suggestions on how can I read the username and not the user ID generated by Firebase Auth?
//here I have it read the last 4 digits of user ID
public void readUserName(){
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
String name = user.getUid();
String lastFourDigits = "";
if (name.length() > 4)
{
lastFourDigits = name.substring(name.length() - 4);
}
else
{
lastFourDigits = name;
}
setUser.setText(lastFourDigits);
}
}
When the data is successfully written in the database, you can simply read it by creating a reference that points to the UID node (05KR...CPZ2) of the user and by attaching a listener as shown in the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("USERSINFO").child(uid);
uidRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
String username = task.getResult().child("username").getValue(String.class);
Log.d(TAG, username);
} else {
Log.d(TAG, task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
The result in the logcat will be:
suhash
One thing to notice is that the "uid" object represents the user ID that comes from the authentication process (05KR...CPZ2).
You can create another child in your database having username and userid relations and then you can get userid from username, something like this
"userReferences": {
"myUserName1": "myUserId1",
"myUserName2": "myUserId2"
}
i am developing an application that requires firebase custom tokens.
I can assign custom claims by callable cloud functions in node.js server. Now i need them in my app for controlling access. How can i achieve it?
FirebaseAuth.getInstance().getCurrentUser().getTokens()
like that
I have tried to get tokens from firestore but it costs read operations.
Use getIdToken() on Auth user to get claims.
Check out the below example:
user.getIdToken(false).addOnSuccessListener(new OnSuccessListener<GetTokenResult>() {
#Override
public void onSuccess(GetTokenResult result) {
boolean isAdmin = result.getClaims().get("admin");
if (isAdmin) {
// Show admin UI.
showAdminUI();
} else {
// Show regular user UI.
showRegularUI();
}
}
});
Also please keep in mind that ID Token need to be refreshed before these are updated which you can do by following,
currentUser.getIdToken(true)
And custom claims are only to verify roles and for storing very small data. It should not be used to keep user's information.
Source and Further Read: https://firebase.google.com/docs/auth/admin/custom-claims#propagate_custom_claims_to_the_client
currentUser has getIdToken method with a callback argument addOnSuccessListener. The addOnSuccessListener give access to GetTokenResult(map) use that to check your claims.
private fun login() {
val user = FirebaseAuth.getInstance().currentUser
if (user == null) showAuthActivity()
user?.getIdToken(true) // forceRefresh: boolean Force refresh regardless of token expiration.
?.addOnSuccessListener {it: GetTokenResult ->
val role = (it.claims["admin"] as? Boolean)
?: (it.claims["clientUser"] as? Boolean) ?: false
if (role) {
startActivity(Intent(this, MainActivity::class.java))
finish()
} else {
showAuthActivity()
showToast("You don't have permissions to use this app")
}
}
?.addOnFailureListener {
showAuthActivity()
showToast("Something went wrong e = ${it.message}")
}?.addOnCanceledListener {
showAuthActivity()
}
}
What I am trying to achieve is when a new user registers I would like to run a query to make sure that the username which they have selected doesn't already belong to some other user. To do this I have written the register(); method, but it's not giving me back anything, not the Toast message indicating that the username has already been taken, nor does it take me to the next page indicating that the email has been sent and the user has to now log in.
Can someone explain to me what I am doing wrong?
RegisterActivity
private void register(final String username, final String fullname, String email, String password) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users");
reference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
boolean ifUsernameExists = false;
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
User user = snapshot.getValue(User.class);
if (user != null) {
if (username.equals(user.getUsername())) {
Toast.makeText(RegisterActivity.this, "That username has already been taken. Try another", Toast.LENGTH_SHORT).show();
ifUsernameExists = true;
}
}
}
if (!ifUsernameExists) {
mAuth.createUserWithEmailAndPassword(email, password).addOnCompleteListener(RegisterActivity.this, task -> {
if (task.isSuccessful()) {
sendVerificationEmail();
FirebaseUser firebaseUser = mAuth.getCurrentUser();
String userid = firebaseUser.getUid();
mReference = FirebaseDatabase.getInstance().getReference().child("Users").child(userid);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("id", userid);
hashMap.put("email", email);
hashMap.put("username", username.toLowerCase());
hashMap.put("fullname", fullname);
hashMap.put("bio", "");
hashMap.put("imageurl", "https://firebasestorage.googleapis.com/v0/b/events-50eda.appspot.com/o/Placeholder.png?alt=media&token=0e651fa8-32e9-4f42-be9a-a5365f44b0f4");
mReference.setValue(hashMap).addOnCompleteListener(task1 -> {
if (task1.isSuccessful()) {
FirebaseAuth.getInstance().signOut();
Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
} else {
Toast.makeText(RegisterActivity.this, "You can't register with that email", Toast.LENGTH_LONG).show();
mProgressDialog.dismiss();
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
The value that you are looking for in the user variable is getting lost. I would print it out ar run a debug to check where I am losing it.
The first part of the problem was solved according to OP's comment:
I figured out that actually my entire problem was Firebase rules.
Using the information in the answer from the following post:
Checking if a particular value exists in the Firebase database
What if I just wanted to use a for loop and look through all the usernames?
You cannot do that unless you are authenticated.
Like I said the method I wrote works, I just need to make it so an unauthenticated user can read to see if the username could possibly exist and then write to the database, meaning save their data to Firebase.
The only way in which unauthenticated users can read the data is to write the rules like this:
{
"rules": {
".read": true,
".write": true
}
}
But is not recommended because these security rules are defined as public, and anyone can steal, modify, or delete data in your database.
The simplest solution I can think of is to authenticate the user with email and password and provide the option the set the user name right after that. Once the user is already authenticated, you can use the query that you said it's working along with the existing security rules.
I am creating authentication with facebook for my application and everything is working fine except that when I am signed out of facebook it still passes me to the main menu of the application. Which I assume means that .getCurrentUser() does not return null even if I am signed out.
I've tried commenting out updateUI(); in my code below and that seems to fix the problem, however I would like for this code to work properly
FirebaseUser currentUser = mAuth.getCurrentUser();
if(currentUser != null) {
updateUI();
}
You need to attach an authstate listener.
"There are some cases where getCurrentUser will return a non-null FirebaseUser but the underlying token is not valid. This can happen, for example, if the user was deleted on another device and the local token has not refreshed. In this case, you may get a valid user getCurrentUser but subsequent calls to authenticated resources will fail.
getCurrentUser might also return null because the auth object has not finished initializing.
If you attach an AuthStateListener you will get a callback every time the underlying token state changes. This can be useful to react to edge cases like those mentioned above."
https://firebase.google.com/docs/reference/android/com/google/firebase/auth/FirebaseAuth.AuthStateListener
https://firebase.google.com/docs/auth/android/manage-users
Try using AuthStateListener, sample:
//Declaration and defination
private FirebaseAuth firebaseAuth;
FirebaseAuth.AuthStateListener authStateListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() != null){
//Do anything here which needs to be done after user is set is complete
updateUI();
}
else {
}
}
};
//Init and attach
firebaseAuth = FirebaseAuth.getInstance();
firebaseAuth.addAuthStateListener(authStateListener);