I believe my security rules and code is correct, but I am getting a permission error in Android studio when I try to retrieve from the user document...
This is the Get User Profile method in my Android java code:
public void getUserProfile(){
db.collection("users")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull com.google.android.gms.tasks.Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
String displayName = document.getString("DisplayName");
String userEmail = user.getEmail();
}
} else {
Log.w("DEBUG_FirestoreActivity", "Error getting documents.", task.getException());
}
}
});
}
... and this is how my security rules are set up:
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;}
Here is the output of the error I'm receiving in android studio:
com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions.
What's strange is that everything should work, and I have tested it with the Rules Playground.
Your security rules allow each user to read their own document. But your code is trying to read the documents of all users, and is thus rejected.
Note that security rules are not filters on their own. If you want to only read the current user's document, you need to do so from the code: the security rules won't do this for you.
For example:
db.collection("users")
.doc(FirebaseAuth.getInstance().getCurrentUser().getUid())
.get()
Related
Please read carefully what I want. Here is my Firestore database structure:
Source Image
I want to start a query to find user-entered refer code is available / not in the Firestore database. All available refer codes of my users are stored in [collection]users--->[uid/Document Id]--->[Field]myRefer.
In my app user can create an account with a referral code I want to check if entered refer code is available in the database, I want to show the document id where is available the referral code. I want to show the document id in a text view.
Please help me with the Java language in Android Studio.
I want to check if entered refer code is available in the database
To be able to check if for example, #e0f2f67 exists in the "users" collection or not, please use the following lines of code:
String myRefer = "#e0f2f67";
FirebaseFirestore db = FirebaseFirestore.getInstance();
Query queryByMyRefer = db.collection("users").whereEqual("myRefer", myRefer);
queryByMyRefer.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
if (document.exists()) {
String name = document.getString("name");
Log.d(TAG, name + " already exists");
} else {
Log.d(TAG, name + " does not exists");
}
}
} else {
Log.d(TAG, task.getException().getMessage()); //Never ignore potential errors!
}
}
});
In which myRefer is defined as in the screenshot, so we can make the comparison.
Hello I want to know how can I access user email while authenticating a user through Github in my android App. I am using firebase and android studio. Please note that I cannot use user.getEmail in onSuccesslistner because I am also using Google authentication, which throws exception that email already exist and pending task method works for first time only. Basically I want to use setScopes to retrieve the user Email. I have to get Email and check if user exist in my database in simply logged in user.
Here is my Code:
public void git_login(View view)
{
SignInWithGithubProvider(
OAuthProvider.newBuilder("github.com")
.setScopes(
new ArrayList<String>()
{
{
add("user:email");
}
}).build()
);
}
private void SignInWithGithubProvider(OAuthProvider login)
{
Task<AuthResult> pendingResultTask= mAuth.getPendingAuthResult();
if (pendingResultTask!=null)
{
// There's something already here! Finish the sign-in for your user.
pendingResultTask
.addOnSuccessListener(
new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
Toast.makeText(getApplicationContext(), "User Exist" + authResult, Toast.LENGTH_SHORT).show();
// User is signed in.
// IdP data available in
// authResult.getAdditionalUserInfo().getProfile().
// The OAuth access token can also be retrieved:
// authResult.getCredential().getAccessToken().
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Handle failure.
}
});
}
else {
// There's no pending result so you need to start the sign-in flow.
// See below.
mAuth.startActivityForSignInWithProvider(this , login).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e)
{
if (e.toString().equals("com.google.firebase.auth.FirebaseAuthUserCollisionException: An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address."))
{
showDialogAlert();
}
}
}).addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
FirebaseUser user = mAuth.getCurrentUser();
Toast.makeText(getApplicationContext(), "Login" + user.getUid() +"\n"+user.getEmail(), Toast.LENGTH_SHORT).show();
userNameForDb = user.getDisplayName();
userImageForDb = String.valueOf(user.getPhotoUrl());
userEmailForDb = user.getEmail();
Toast.makeText(CreateNewAccountActivity.this, "Account added to Firebase: " +userNameForDb+"\n"+userEmailForDb+"\n"+userTokenForDb, Toast.LENGTH_SHORT).show();
saveDataToDb(userNameForDb , userEmailForDb , userTokenForDb);
}
});
}
}
```
I want to know how can I access user email while authenticating a user through Github
The simplest solution I can think of is once you are successfully authenticated, you can get the email address from the "userInfo" object like in the following lines of code:
FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
if (firebaseUser != null) {
for (UserInfo userInfo : firebaseUser.getProviderData()) {
if (userInfo.getProviderId().equals("github.com")) {
Log.d(TAG, "User is signed in with Github");
Log.d(TAG, "email: " + userInfo.getEmail());
}
}
}
The output in the logcat will be the email address that was used by the user for the authentication process.
Edit:
It's true, if the user is already registered with a Gmail account, you'll get an Exception that says that such an account is already there. So you need to use for authentication Google credentials.
I actually want to get the user id in this case and want to check it in my database which is my local server that this email exists or not.
There is no need for that because you can handle the Exception, and indicate to the user that a Google account is already there, and then simply use Google credentials for authentication. If there is no Exception, is obvious that the user doesn't exist yet.
I am working on an android app for my degree and I am using Firebase Realtime Database, the app is going to be something similar to spotify, but on a smaller scale. I was forced to take a longer break and my client requests from the Database have been automatically disabled (the 30 day limit by default).
I've changed the rules to be "true" for both read and write(for the purpose of making it work, not secure, I will change them appropriately). I also attached some screenshots and code snippets to help. I checked other stack questions and they didnt help, the only solution I see right now is making another project so basically reinitializing the whole thing withing a new Firebase project.
private void registerUser(){
final String email = emailField.getText().toString().trim();
final String username = usernameField.getText().toString().trim();
String password = passwordField.getText().toString().trim();
String confirmPass = confirmPasswordField.getText().toString().trim();
if(username.isEmpty()){
usernameField.setError("Username is required");
usernameField.requestFocus();
return;
}
if(email.isEmpty()){
emailField.setError("Email is required");
emailField.requestFocus();
return;
}
if(password.isEmpty()){
passwordField.setError("Password is required");
passwordField.requestFocus();
return;
}
if(!Patterns.EMAIL_ADDRESS.matcher(email).matches()){
emailField.setError("Please provide valid email");
emailField.requestFocus();
return;
}
if(password.length() < 6){
passwordField.setError("Password length should be at least 6 characters");
passwordField.requestFocus();
return;
}
if(!password.equals(confirmPass)){
confirmPasswordField.setError("Passwords do not match");
confirmPasswordField.requestFocus();
return;
}
progressBar.setVisibility(View.VISIBLE);
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
User user = new User(username, email);
FirebaseDatabase.getInstance().getReference("Users")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.setValue(user).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
Toast.makeText(RegisterActivity.this, "User has registered successfully", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(RegisterActivity.this, "Registration has failed", Toast.LENGTH_LONG).show();
}
progressBar.setVisibility(View.GONE);
}
});
}
}
});
}
This is where I register my user to the Realtime Database. They do show up in the authentication tab and I can log in with them, but they do not in the database.
{
"rules": {
"users": {
".read": "true",
".write": "true",
}
}
}
These are the rules that I am using right now with the purpose of getting to the bottom of this issue that I am having right now, I am planning to change them so that the users can only write data that belongs to them.
Basically my question boild down to, if my client requests have expired, what can I do to re enable them so that I can have entries in my Realtime DB again? This is the DB right now
Im trying to do the email authentication of firebase.
I'm following the document and i get this error:
UNAUTHORIZED_DOMAIN:Domain not whitelisted by project
I saw this soultion:
Firebase Auth/unauthorized domain. Domain is not authorized
and it didn't work, so I went and tried to create a dynamic link because I saw here that I need to create dynamic link:
Firebase says "Domain not whitelisted" for a link that is whitelisted
and that also didn't work. i got when tried to create dynamic link:
An error occurred when creating a new Dynamic Link
so i went and tried this:
Firebase console create dynamic link error
and still the same problem
so now I don't know what else to do.
the code:
private void sendEmail(String email) {
Log.d(TAG, "sendEmail: here in sendEmail");
String url = "https://.........";
ActionCodeSettings actionCodeSettings = ActionCodeSettings.newBuilder().setUrl(url)
.setHandleCodeInApp(true)
.setAndroidPackageName("com.myapp_pack.my_app_name", true, "12").build();
auth.sendSignInLinkToEmail(email, actionCodeSettings).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "onComplete: email sent homie!");
} else{
Log.d(TAG, "onComplete: task failed " + task.getException().getMessage());
}
}
});
}
This was useful for me, using Firebase v.9 (current last version in January 2022)
Try not creating dynamic links but check if you are listing not just "localhost" (or where you would serve the project) but also the url you pass to the url property of the object you pass as the third parameter of "sendSignInLinkToEmail". Example:
const config = {
url: "https://example.com/",
*...other properties*
};
sendSignInLinkToEmail(auth, email, config).catch((error) => {
console.log(error);
});
In this case you would go to the firebase console and add in the whitelist "example.com".
Disclaimer: Checking this solved my problem as I was unintentionally only whitelisting the url where I was serving my project in dev mode.
I wanted to try and keep my native android firebase development to minimum so as to when I'm ready to port to IOS/web I won't be doing a lot there.
Right now firebase's Javascript doesn't allow google login from Android, this can be taken care of from the plugin. But what I'm stuck on is how to initialize firebase based on the Java Android Google login.
So this is what I'm trying to achieve:
Cordova calls Java-Android-Native login into google ---> based on this, how would I initialize firebase?
This plugin can let me login into google natively: https://www.npmjs.com/package/cordova-plugin-googleplus
But I guess I need auth token? token ID?
firebase.auth().signInWithCredential(credential).catch(function(error) {
} else {
console.error(error);
}
});
Can this give me the above required toke? https://developers.google.com/identity/sign-in/android/sign-in
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
Update 1: Just want to share more information. When getting the user logged in through google on android I have the below object
GoogleSignInAccount
https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInAccount
It has public String getIdToken () & public String getServerAuthCode () why can't these be used to authenticate firebase using JS?
Update 2: Answer provided by Faraz seems to be working. Here is reference for the function signInWithCredential https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithCredential
Thank you for your help.
Use auth.signInWithCredential with the GoogleAuthProvider credential.
Here is an example:
auth.signInWithCredential(firebase.auth.GoogleAuthProvider.credential(googleAccessToken)).then(function(user) {
// Google User is logged in
}).catch(function(error) {
// Error
});
Source for more infomation
You can read this GitHub example about Firebase usage.
And Here you can find -
mFirebaseRef.authWithOAuthToken("google", token, new AuthResultHandler("google"));
Which (if all is success) calls this
public void onAuthenticated(AuthData authData)
Where token is your getIdToken
I mean it is possble to login into Firebase using Google, Facebook,Twitter in all cases you have to send token you receive to Firebase server that checks your token whether you already logged in or not. You can setup your own server in the same way.
After google login you have to Use auth.signInWithCredential with the GoogleAuthProvider credential:
Here is an code:
private void firebaseAuthWithGoogle(GoogleSignInAccount account) {
Log.d(TAG, "firebaseAuthWithGoogle:" + account.getId());
final String name = account.getDisplayName();
final String email = account.getEmail();
AuthCredential credential = GoogleAuthProvider.getCredential(account.getIdToken(), null);
getAuth().signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d(TAG, "onComplete: sign in with credentials " + task.isSuccessful());
if (task.ienter code heresSuccessful()) {
Log.e(TAG, "success: sign in with credentials ");
}
if (!task.isSuccessful()) {
Log.e(TAG, "onComplete: sign in with credentials " + task.getException());
}
}
});
}