Currently I done using email authentication register new user to the database but now I met the problem of validate username and email which is prevent user enter the same username and password to the database so can you guys help me see whether the retrieve data statement got error?
auth = FirebaseAuth.getInstance();
db = FirebaseDatabase.getInstance();
ref = db.getReference();
FirebaseUser user = auth.getCurrentUser();
uid = user.getUid();//getuser id
run = (EditText) findViewById(R.id.Run);
rpw = (EditText) findViewById(R.id.Rpw);
rage = (EditText) findViewById(R.id.Rage);
//rbm = (RadioButton) findViewById(R.id.rbmale);
//rbfm = (RadioButton) findViewById(R.id.rbfemale);
re = (EditText) findViewById(R.id.Re);
rpn = (EditText) findViewById(R.id.Rpn);
ra = (EditText) findViewById(R.id.Ra);
rpc = (EditText) findViewById(R.id.Rpc);
//rbstd = (RadioButton) findViewById(R.id.rbstd);
//rbtt= (RadioButton) findViewById(R.id.rbtt);
final Button br = (Button) findViewById(R.id.Rbt);
br.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
usnm = run.getText().toString().trim();
pswd = rpw.getText().toString().trim();
email = re.getText().toString().trim();
ref.child(uid).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Object a = dataSnapshot.getValue();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
if (TextUtils.isEmpty(usnm)){
Toast.makeText(Register.this, "Username cannot be empty", Toast.LENGTH_SHORT).show();
return;
}else if (usnm.length()<8){
Toast.makeText(Register.this, "Username cannot less then 8 characters", Toast.LENGTH_SHORT).show();
return;
}else if (usnm.length()>8){
Toast.makeText(Register.this, "Username cannot greater then 8 characters", Toast.LENGTH_SHORT).show();
return;
}else if (ref.child(uid).child("username").equals(usnm)){
Toast.makeText(Register.this, "Username had been taken already! Please try another one.", Toast.LENGTH_SHORT).show();
return;
}else if (TextUtils.isEmpty(pswd)){
Toast.makeText(Register.this, "Password cannot be empty", Toast.LENGTH_SHORT).show();
return;
}else if (pswd.length()<8){
Toast.makeText(Register.this, "Password cannot less then 8 characters", Toast.LENGTH_SHORT).show();
return;
}else if (pswd.length()>8){
Toast.makeText(Register.this, "Password cannot greater then 8 characters", Toast.LENGTH_SHORT).show();
return;
}else if (TextUtils.isEmpty(email)){
Toast.makeText(Register.this, "Email cannot be empty", Toast.LENGTH_SHORT).show();
return;
}else if (ref.child(uid).child("email").equals(email)){
Toast.makeText(Register.this, "Email had been taken already! Please try another one.", Toast.LENGTH_SHORT).show();
return;
}
register(usnm, pswd, email);
}//end of onclick
});
I hope can prevent user enter same input during registration.
To solve your problem, i recomand you implementing Firebase Authentication which is the best solution in your case. This approach solves all you problems regaring authentication and saves time because you don't need to maintain any code.
If you still want to use your approach, to check for uniqueness i recomand you change your database structure a little bit. In stead of using a unique key or the UID, i recomand you using the email address. It's also unique and very easy to use. Remember, using the UID is not always the best solution because if you let the user the possibility to delete his account, if he signs in again, another UID is generated and this will cause you troubles.
To check an email address / user-name also for uniqueness, i recomand you creating another nodes in your Firebase database (emailAddresses / userNames) in which you need to add all email addresses and all user-names. To verify the existents of a email address/user-name, just add a listener on that particular node and use the exists() method on the dataSnapshop object.
Hope it helps.
Here is the solution to take the uid after you have registered successfully a user on your Firebase. You need to add an onCompleteListener on your registration and after Firebase returns the uid you can query Firebase to get username and email.
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
//Problem with saving the data
if (databaseError != null) {
} else {
//User has registered, retrieve his uid
String uniqueKey = databaseReference.getKey();
}
}
Related
This question already has answers here:
How to redirect multiple types of users to their respective Activities?
(3 answers)
Checking if a particular value exists in the Firebase database
(6 answers)
Closed 2 years ago.
First, I will tell the flow of my App.
Login Screen(SignInActivity.java) -> Enter details(MainActivity.java) ->Home Screen(HomeScreenActivity.java)
In my app, I have used Firebase Authentication and Firebase Database. When the user is new, then it should go to Main Activity from SignInActivity where user enters his name, a short description and his hobby. The details are stored in Firebase Database and then HomeScreenActivity opens where user details are shown in Recycler View.
But currently what happens is when same user does login again, it again asks user for details. I want to check if users Google Account already exists in Firebase Auth, then instead of asking details, it should directly go to HomeScreenActivity.
I checked many answers on StackOverflow, but nothing seems to work. One thing that i tried was additionalUserInfo.isNewUser but in this app crashes when user does login again, showing null error where I display user details in HomeScreenActivity.
SignInActivity.java
private void firebaseAuthWithGoogle(String idToken) {
AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null);
mAuthIn.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "SignInWithCredential:success");
startActivity(new Intent(SignInActivity.this, MainActivity.class));
finish();
} else {
// If sign in fails, display a message to the user.
Toast.makeText(SignInActivity.this, "Authentication Failed", Toast.LENGTH_SHORT).show();
}
}
});
}
MainActivity.java
public void init() {
hobbiesContinueButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String name=user.getText().toString().trim();
String desc=description.getText().toString().trim();
String hobby=spinner.getSelectedItem().toString();
String image="default";
String thumbnail="default";
if(!TextUtils.isEmpty(name))
{
FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
assert currentUser != null;
String userId=currentUser.getUid();
User user=new User(name,hobby,desc,image,thumbnail);
dbRef.child(userId).setValue(user);
startActivity(new Intent(getApplicationContext(), HomeScreenActivity.class));
finish();
}
else
{
Toast.makeText(getApplicationContext(), "Enter a name",Toast.LENGTH_SHORT).show();
}
}
});
}
HomeScreenActivity.java
dbRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
imgvw = headerView.findViewById(R.id.imageView);
imgvw.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//to open gallery
Intent galleryIntent = new Intent();
galleryIntent.setType("image/*");
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(galleryIntent, "SELECT IMAGE"), GALLERY_PICK);
}
});
TextView nameDrawer = findViewById(R.id.navName);
TextView descDrawer = findViewById(R.id.navDescription);
User change = snapshot.getValue(User.class);
assert change != null;
//This is where null error occurs
nameDrawer.setText(change.getUserName());
descDrawer.setText(change.getUserDesc());
//change profile picture
image= Objects.requireNonNull(snapshot.child("userImage").getValue()).toString();
Log.d(TAG, "onComplete: "+image);
if(!image.equals("default")){
Picasso.get().load(image).placeholder(R.drawable.avatar).into(imgvw);
}
}
The solution is to save your user details in shared preferences for the first time when the user sign in , then after the user signs out and sign it again , you get data from shared preferences and set them directly to your edittexts
Try this Code :
///save sharedpreferences
SharedPreferences sharedPreferences =
getSharedPreferences("prefs",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("username","put here your username"); //
editor.putString("email","put your email here"); //you can add more details
editor.apply();
///get sharedpreferences
SharedPreferences sharedPreferences1 =
getSharedPreferences("prefs",Context.MODE_PRIVATE);
String username = sharedPreferences1.getString("username","");
String email = sharedPreferences1.getString("email","");
//then here set the valeus from sharedpreferences to your edittexts
When the Login process failed, I would like to find out what went wrong. So if the email was wrong or the password. So I can send more detailed instructions to go on with the process.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
emailView = findViewById(R.id.emailText);
passwordView = findViewById(R.id.pwText);
loginB = findViewById(R.id.loginB);
registerB = findViewById(R.id.registerB);
// Initialize Firebase Auth
mAuth = FirebaseAuth.getInstance();
loginB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String email = emailView.getText().toString();
String password = passwordView.getText().toString();
if(email.isEmpty()){
emailView.setError("Please enter a valid Email");
emailView.requestFocus();
}
if(password.isEmpty()){
passwordView.setError("Please enter a passoword");
}
if(!(email.isEmpty() && password.isEmpty())){
mAuth.signInWithEmailAndPassword(email,password).addOnCompleteListener(MainActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
Intent i = new Intent(MainActivity.this,HomeActivity.class);
startActivity(i);
}else{
//My Question
}
}
});
}
}
});
registerB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, RegisterActivity.class);
startActivity(intent);
}
});
}
Tried to find a function in task which could help but didn't find anything helpful.
For security reasons, you don't usually tell what was wrong with the credentials.
If you tell "username not valid" and "password not valid", an attacker can use that to determine which usernames exist. It's a bit of security by obscurity, but legitimate users would know their username (or their email address at least, to retrieve the credentials).
#Kayaman's answer is correct: for security reasons you can't determine which part of the credentials was incorrect. But for a better user experience you can do a bit more...
If you want to know if an email address is registered, you can call fetchSignInMethodsForEmail. You can use that to determine if the email is of a known Firebase user, and in that case for example offer to send a password reset email.
I have created a simple app on which a user can register an login. authentication is working perfectly. I have also added a real-time database. I am getting "permission denied" when i try to read the data from firebase, despite the "write data" is working perfect.
I want to fetch the data for logged in user.
here are firebase rules:
{
"rules": {
"users": {
"$userId": {
".write": "$userId === auth.uid",
".read": "$userId === auth.uid"
}
}
}
}
This is the write method(this works perfect):
public void writeUserInfo(){
String username = etUserName.getText().toString().trim();
String age = etAge.getText().toString().trim();
String sex = etSex.getText().toString().trim();
if(username.isEmpty()){
etUserName.setError("user name required");
etUserName.requestFocus();
return;
}
if(age.isEmpty()){
etAge.setError("age required");
etAge.requestFocus();
return;
}
if(sex.isEmpty()){
etSex.setError("sex required");
etSex.requestFocus();
return;
}
User user = new User(username,age,sex);
mDatabase.child("users/"+firebaseUser.getUid()).setValue(user);
}
And this is the read method:
public void readUserData(){
mDatabase.child("users").orderByChild(userId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
//array list to staore user data as elements
ArrayList<User> userData = new ArrayList<>();
for(DataSnapshot snapshot:dataSnapshot.getChildren()){
User element = snapshot.getValue(User.class);
userData.add(element);
}
for(User user: userData){
etUserName.setText(user.getmUsername());
etAge.setText(user.getmAge());
etSex.setText(user.getmSex());
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
here is the database hierarchy:
Firebase Console
I am also including login and signup methods:
Login method:
public void signIn(){
String userEmail = etEmail.getText().toString().trim();
String userPassword = etPassword.getText().toString().trim();
//validation
//validation
if(userEmail.isEmpty()){
etEmail.setError("Email is required");
//et is focused
etEmail.requestFocus();
return;
}
if(!Patterns.EMAIL_ADDRESS.matcher(userEmail).matches()){
etEmail.setError("Invalid email address");
//focus et
etEmail.requestFocus();
return;
}
if(userPassword.isEmpty()){
etPassword.setError("Password is required");
//et is focused
etPassword.requestFocus();
return;
}
if(userPassword.length()<6){
etPassword.setError("Password length should be atleast 6 characters");
//request focus
etPassword.requestFocus();
return;
}
//setting progress bar
progressBar.setVisibility(View.VISIBLE);
//firebase signin method
mAuth.signInWithEmailAndPassword(userEmail,userPassword).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
//hiding progress bar
progressBar.setVisibility(View.GONE);
if(task.isSuccessful()){
Intent intent = new Intent(getApplicationContext(),Profile.class);
//this flag will clear all the open activities
//so that user cant go back to login activyty upon pressing
//back button
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
Toast.makeText(getApplicationContext(),"Logged in successfully",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(),task.getException().getMessage(),Toast.LENGTH_SHORT).show();
}
}
});
}
and here is the signUp method:
public void userRegistration(){
String userEmail = etSignupEmail.getText().toString().trim();
String userPassword = etSignupPassword.getText().toString().trim();
//validation
if(userEmail.isEmpty()){
etSignupEmail.setError("Email is required");
//et is focused
etSignupEmail.requestFocus();
return;
}
if(!Patterns.EMAIL_ADDRESS.matcher(userEmail).matches()){
etSignupEmail.setError("Invalid email address");
//focus et
etSignupEmail.requestFocus();
return;
}
if(userPassword.isEmpty()){
etSignupPassword.setError("Password is required");
//et is focused
etSignupPassword.requestFocus();
return;
}
if(userPassword.length()<6){
etSignupPassword.setError("Password length should be atleast 6 characters");
//request focus
etSignupPassword.requestFocus();
return;
}
//showing progressbar upon regisration process lifetime
progressBar.setVisibility(View.VISIBLE);
//calling firebase register users methods via mAuth instance
mAuth.createUserWithEmailAndPassword(userEmail,userPassword).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
//changing visibility of progress bar to gone upon registration
progressBar.setVisibility(View.GONE);
//checking if the process was successful
//using this task obj
if(task.isSuccessful()){
Toast.makeText(getApplicationContext(),"user registered successfully", Toast.LENGTH_SHORT).show();
}else{
//this line checks whether the email is already registered or not
//using the task obj and FirebasesuthUSerCollisonException
if(task.getException() instanceof FirebaseAuthUserCollisionException){
Toast.makeText(getApplicationContext(),"email already exists",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(),task.getException().getMessage(),Toast.LENGTH_SHORT).show();
}
}
}
});
}
I cannot figure what has gone wrong. Help is appreciated. Thanks
You're trying to read from /users here:
mDatabase.child("users").orderByChild(userId).addValueEventListener(new ValueEventListener() {
But your rules only gives a user access to /users/$uid. Since the user doesn't have read permission on /users, the listener gets rejected.
If you want to read the user's own data, read that specific child node:
mDatabase.child("users").child(userId).addValueEventListener(new ValueEventListener() {
Now since the user has read permission to their own node, the listener will be allowed.
Make sure app name and client id are same as in firebase console.
If you are not sure re-download google-services.json from your project's console and add it your project.
and also change your rules during development and testing period to this
{
"rules": {
".read": true,
".write": true
}
}
This is the error message I get everytime I register a new user then log in. Above is the error message and below is my code. Please help me, thank you in advance! Just trying to complete my first app.
//initialize the button for log in
Button btnLogin= (Button) findViewById(R.id.btn_login);
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d(TAG, "onClick: attempting to log in.");
String email = mEmail.getText().toString();
String password = mPassword.getText().toString();
if (isStringNull(email) && isStringNull(password)){
Toast.makeText(mContext, "You must fill out all the fields", Toast.LENGTH_SHORT).show();
}else{
mProgressBar.setVisibility(View.VISIBLE);
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(LoginActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithEmail:onComplete:" + task.isSuccessful());
FirebaseUser user = mAuth.getCurrentUser();
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Log.w(TAG, "signInWithEmail:failed", task.getException());
Toast.makeText(LoginActivity.this, getString(R.string.auth_failed), Toast.LENGTH_SHORT).show();
mProgressBar.setVisibility(View.GONE);
}else{
try{
if (user.isEmailVerified()){
Log.d(TAG, "onComplete: success. Email is verified.");
Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
startActivity(intent);
}else{
Toast.makeText(mContext, "Email is not verified \n check your email inbox.", Toast.LENGTH_SHORT).show();
mProgressBar.setVisibility(View.GONE);
mAuth.signOut();
}
}catch (NullPointerException e){
Log.e(TAG, "onComplete: NullPointerException: " + e.getMessage() );
I had a similar problem. Here's how I solved it :
My entire code was correct, but Firebase requires your password to be of minimum 8 characters and should include at least one numeric value. Try setting a password which matches the above guidelines.
I have an application that I want to create a log in activity. Ive got
1) Login (Button)
2) UserID (EditText)
3) Password (EditText)
I would like to store the username and password on the device's internal storage. How do I create the file from which the SharedPreferences pulls from and encrypt it?
login_Button.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
SharedPreferences userDetails = getSharedPreferences("userdetails", MODE_PRIVATE);
SharedPreferences.Editor edit = userDetails.edit();
edit.clear();
if(etUserID.getText().toString().equals("")){
Toast.makeText(getApplicationContext(),"Please enter a User ID", Toast.LENGTH_LONG).show();
}else if (etPassword.getText().toString().equals("")){
Toast.makeText(getApplicationContext(),"Please enter a password", Toast.LENGTH_LONG).show();
}else{
edit.putString("userID", txtUID.getText().toString().trim());
edit.putString("password", txtPass.getText().toString().trim());
edit.commit();
}
}
});
The txtUID and txtPass is showing up as red and when I delete it the system says that the getText is wrong.
This is my first shot at an authenticator. I found something called PasswordAuthentication from the android dev page but I haven't been able to find any tutorials or code of it being used.
SharedPreferences userDetails = getSharedPreferences("userdetails", MODE_PRIVATE);
String UID = userDetails.getString("userID", "");
String pass = userDetails.getString("password", "");
if (userDetails.contains("userID")||userDetails.contains("password")){
startActivity(new Intent(LogOn.this,CrimeMap.class));
}
Sources Ive used for my research:
http://developer.android.com/reference/java/net/PasswordAuthentication.html
how to use getSharedPreferences in android
Update:
Ok, here is my updated code. If I don't enter a User ID or password it sets off my statements. However, the program doesn't go to the next activity when I put in the correct UserID and Password. I'm going to get it running first and then Ill move on to encrypting it.
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_log_on);
etUserID = (EditText) findViewById(R.id.etUserID);
etPassword = (EditText) findViewById(R.id.etPassword);
login_Button = (Button) findViewById(R.id.bLogin);
login_Button.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
int uid = 1155;
String pass = "pass";
SharedPreferences userDetails = getSharedPreferences(User_File, MODE_PRIVATE);
SharedPreferences.Editor edit = userDetails.edit();
edit.putInt("userID", uid);
edit.putString("password", pass);
edit.commit();
if((etUserID.getText().toString().equals("")) || (etPassword.getText().toString().equals(""))) {
Toast.makeText(getApplicationContext(),"Please enter a User ID", Toast.LENGTH_LONG).show();
}else if (etPassword.getText().toString().equals("")){
Toast.makeText(getApplicationContext(),"Please enter a password", Toast.LENGTH_LONG).show();
}else{
edit.putInt("userID", Integer.parseInt(etUserID.getText().toString()));
edit.putString("password", etPassword.getText().toString());
}
}
});
SharedPreferences userDetails = getSharedPreferences(User_File, MODE_PRIVATE);
if (userDetails.equals(etUserID) && (userDetails.equals(etPassword))){
startActivity(new Intent(LogOn.this,CrimeMap.class));
}
Update:
I finally got it! Thanks for your help! Here is my complete code for this portion of the project. I still haven't encrypted it but I think I'm going to take a break and come back to it later. Thanks for all your help!
#Override
public void onClick(View v) {
int uid = 1155;
String pass = "pass";
SharedPreferences userDetails = getSharedPreferences(User_File, MODE_PRIVATE);
SharedPreferences.Editor edit = userDetails.edit();
edit.putInt("userID", uid);
edit.putString("password", pass);
edit.commit();
if((etUserID.getText().toString().equals(""))){
Toast.makeText(getApplicationContext(),"Please enter a User ID", Toast.LENGTH_LONG).show();
}else if (etPassword.getText().toString().equals("")){
Toast.makeText(getApplicationContext(),"Please enter a password", Toast.LENGTH_LONG).show();
}else{
String user_id = etUserID.getText().toString();
int user_id2 = Integer.parseInt(user_id);
String user_password = etPassword.getText().toString();
int userID = userDetails.getInt("userID", 1);
String password = userDetails.getString("password", "no name");
if (userID == user_id2 && password.equals(user_password)){
startActivity(new Intent(LogOn.this,CrimeMap.class));
}
}
Don't try to access the file. Let android do that, and encrypt the data you store to the shared preferences. I mean:
edit.putString("userID", encrypt(txtUID.getText().toString().trim()));
edit.putString("password", encrypt(txtPass.getText().toString().trim()));
You can use whatever encryption you like, though of course you'll need to decode it this way.
Another option is to store the SHA1 encrypted password, and in the authentication you compare the SHA1 encypted password that was typed in with the stored string. You could use http://mvnrepository.com/artifact/commons-codec/commons-codec for example:
String sha1Password = DigestUtils.sha1Hex(password);
edit.putString("sha1Password", encrypt(sha1Password);
To fix the "red" problem you'll need to declare txtUID, txtPass. They should be added to your layout somehow. Probably via editing the layout xml. But even programmatically you can do, like: Input text dialog Android