I'm trying to create a new user in Firebase but onError is constantly being called by my ValueResultHandler:
public void onSignUpComplete(String email, String password) {
Firebase ref = new Firebase(Constants.FIREBASE_URL); // this is "https://subdomain.firebaseio.com/"
ref.createUser(email, password, new SignUpResultHandler());
}
class SignUpResultHandler implements Firebase.ValueResultHandler<Map<String, Object>> {
#Override
public void onSuccess(Map<String, Object> StringObjectMap) {
Toast.makeText(getApplicationContext(), "Created User!", Toast.LENGTH_SHORT().show();
}
#Override
public void onError(FirebaseError firebaseError) {
Toast.makeText(getApplicationContext(), "Failed to create user! " +
firebaseError.getDetails(), Toast.LENGTH_SHORT).show();
}
}
I always get the toast "Failed to create user!" and an empty return from getDetails().
Some extra information: Email and password authentication is enabled in Firebase and my manifest has a uses-permission for "android.permission.INTERNET". I have firebase-auth:9.4.0, firebase-core:9.4.0, firebase-database:9.4.0 and firebase-client-android:2.5.2 as dependencies (and play services). I have my google-services.json file in the app folder and the plugin applied in gradle. I'm running the app in a connected device but this also fails on an emulator.
Looks like you're following old Firebase documentation.
new Firebase() method is deprecated as of May 18, 2016 and the url will be handled by the json file, so we do not need to define it. Here is the link for steps with new documentation: Create a password-based account.
Related
When a new user registers in my app using firebase-authentication custom sign in using email and password, I need to update that data into my firestore.
But Firebase only has FirebaseAuth.createUserWithEmailAndPassword(email, password) to create a new account and hence I cannot update my user's username at the same time.
To update the E-Mail in Firestore, I use Firebase cloud functions. Here's the code:
export const onNewUserJoined = functions.auth.user().onCreate((user) => {
//const newUserDisplayName = user.displayName //CAN'T USE THIS. REASON is BELOW
const newUserUID = user.uid
const newUserEmail = user.email
const timeCreated = Date.now()
console.log(`${newUserUID} has joined.`)
return admin.firestore().collection('Agent').doc(`${newUserUID}`).set({"E-Mail": newUserEmail, "Time": timeCreated})
})
OK, great now I have updated the E-Mail and time created in Firestore successfully.
But next challenge is I need to update the user's username in the same Firestore document. I do it instantly after the createUserWithEmailAndPassword() like this:
DocumentReference dDocRef = FirebaseFirestore.getInstance().document(documentPath);
Map<String, Object> updateUsernameAndPhone = new HashMap<>();
updateUsernameAndPhone.put("username", username);
updateUsernameAndPhone.put("phoneData", phoneModel);
dDocRef.update(updateUsernameAndPhone).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(getApplicationContext(), "Data successfully stored in Firestore", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
});
Now, it depends on who acts first, the cloud function or the user's device.
If the cloud functions act first, then there is no issue. The username and phoneModel both get updated into the document successfully. No issues.
But incase, the phone acts first then I get the following error:
As this error has occurred, username isn't in the document and only email and timeCreated are in the document updated by the cloud function which got late to create document so that user's device can update the username with ease.
I CAN'T use .SET instead of .update() in my app because if I use .set() and the cloud functions create the email and timeCreated fields first. Then the device will DELETE them and put username and phoneModel.
So how can I do this?
I can forcefully delay updating the username by putting it in the next activity so that cloud functions get enough time to do their job, but my signUpActivity asks for username along with email and password edit texts. I don't want to create a separate activity for that.
I used to use .update() when my data was stored in realtime database and it used to create the child even if the path didn't exist. But it looks firestore won't update if the field doesn't exist.
Any solution for this?
I tried as per #DougStevenson said and here's my code:
final String newUserUID = Objects.requireNonNull(signUpAuth.getCurrentUser()).getUid();
final String documentPath = "Agent/" + newUserUID;
FirebaseFirestore fFirestoreRef = FirebaseFirestore.getInstance();
final DocumentReference dDocRef = fFirestoreRef.document(documentPath);
fFirestoreRef.runTransaction(new Transaction.Function<Void>() {
#Nullable
#Override
public Void apply(#NonNull Transaction transaction) throws
FirebaseFirestoreException {
DocumentSnapshot documentSnapshot = transaction.get(dDocRef);
transaction.update(dDocRef, "username", username);
transaction.update(dDocRef, "phoneData", phoneModel);
return null;
}
}).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(getApplicationContext(), "Data updated in Firestore . . .", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
});
But no luck. It still gives me error: Cannot update a document which does not exist.
Use a transaction to resolve conflicts from multiple clients that are all trying to modify the same document. The transaction handler will be retried on the client if it detects the document was modified before the change could take place.
Using firebase authentication with Yahoo and followed the instructions mentioned here. So I created an App in Yahoo Developer with persmissions to read Contacts and Profile (Not sure which api to get the email and name so I requested for both) and copied the Client Id and Secret in Firebase Authentication Sign In Method for Yahoo. Copied the Callback back to Yahoo Developer.
I followed the codes from the Firebase Authentication for Yahoo but when I try to run it, I get the following error:
Here's my code:
public void onClick(View view) {
signInWithOtherProvider(
OAuthProvider.newBuilder("yahoo.com")
.addCustomParameter("prompt", "login")
.setScopes(new ArrayList<String>() {
{
// Request access to Yahoo Mail API.
add("mail-r");
// This must be preconfigured in the app's API permissions.
add("sdct-w");
// Profile
add("sdps-r");
}
})
.build()
);
}
private void signInWithOtherProvider(OAuthProvider provider) {
Task<AuthResult> pendingTaskResult = auth.getPendingAuthResult();
if (pendingTaskResult != null) {
pendingTaskResult
.addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
signInSuccess(authResult);
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
signInFailed(e);
}
});
} else {
auth
.startActivityForSignInWithProvider(getActivity(), provider)
.addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
signInSuccess(authResult);
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
signInFailed(e);
}
});
}
}
Has anyone successfully use Yahoo with Firebase on Android?
Appreaciate any help.
UPDATE 2019/09/30
I was able to replicate the error using Postman.
It seems that when I entered the incorrect callback URL in Yahoo Developer page, I got the same error. But when I entered it correctly (https://www.getpostman.com/oauth2/callback), it went through. So my best guess is that it must be an issue with the callback url in Firebase.
Now looking at the Firebase console specifically in the Sign In Method for Yahoo, the callback url is (project-id.firebaseapp.com). Yahoo does not accept this as it seems to need a valid url so I added https://. So the redirect url I used is https://project-id.firebasapp.com. However, this still does not work. Then I tried the format similar to the other providers callback which is https://project-id.firebaseapp.com/__/auth/handler but still does not work.
Is there anything I can do in the Firebase Console to validate the callback url?
public void signInWithLinkedIn(View view){
LISessionManager.getInstance(getApplicationContext()).init(this, buildScope(), new AuthListener() {
#Override
public void onAuthSuccess() {
Toast.makeText(getApplicationContext(), "success" + LISessionManager.getInstance(getApplicationContext()).getSession().getAccessToken().getValue(), Toast.LENGTH_LONG).show();
Log.d("SESSION", Boolean.toString(LISessionManager.getInstance(getApplicationContext()).getSession().isValid()));
//fetchBasicProfileData();
}
#Override
public void onAuthError(LIAuthError error) {
Toast.makeText(getApplicationContext(), "failed " + error.toString(),
Toast.LENGTH_LONG).show();
}
}, true);
// After complete authentication start new HomePage Activity
}
The block of code in onAuthSuccess got executed but getSession returns null AND most importantly the access token is null, making me unable to call other linkedin APIs. This happens only recently. Am I doing it correctly?
Updated:- One more thing it generally happens with few specific LinkedIn Ids and working fine with rest of the id.
LinkedIn is updating its android sdk and they deprecate several methods.They started doing this from this week, I also got the same problem.You should use javascript api's to authenticate user rather than using linkedin android sdk.We fixed ur problem the same way.
I'm trying to create a SyncAdapter for Microsoft calendars and the first step is Authentication. i'm using com.microsoft.aad:adal:2.0.4-alphaand using this code for first authentication:
getAuthenticationContext().acquireToken(
mContextActivity,
Constants.SCOPES.split(" "),
null,
Constants.CLIENT_ID,
Constants.REDIRECT_URI,
PromptBehavior.Auto,
new AuthenticationCallback<AuthenticationResult>() {
#Override
public void onSuccess(final AuthenticationResult authenticationResult) {
if (authenticationResult != null && authenticationResult.getStatus() ==
AuthenticationResult.AuthenticationStatus.Succeeded) {
dependencyResolver = new ADALDependencyResolver(
getAuthenticationContext(),
resourceId,
Constants.CLIENT_ID);
token = authenticationResult.getToken();
UserInfo userInfo = authenticationResult.getUserInfo();
if (userInfo != null) {
userIdentifier = new UserIdentifier(userInfo.getUniqueId(),
UserIdentifier.UserIdentifierType.UniqueId);
}
}
}
#Override
public void onError(Exception t) {
Log.e("initialize", "onError : " + t.getMessage());
result.setException(t);
}
}
);
this works perfectly and after entering username and password i can get token.
BUT this is for sync adapter and at some point i need to get token silently. so i used this code:
public void getTokenSilent() {
getAuthenticationContext()
.acquireTokenSilent(Constants.SCOPES.split(" "),
Constants.CLIENT_ID,
userIdentifier,
new AuthenticationCallback<AuthenticationResult>() {
#Override
public void onSuccess(
AuthenticationResult authenticationResult) {
UserInfo userInfo = authenticationResult.getUserInfo();
}
#Override
public void onError(Exception e) {
Log.e("getTokenSilent", "onError : " + e.getMessage());
}
});
}
After executing this code i got the error:
AUTH_REFRESH_FAILED_PROMPT_NOT_ALLOWED Prompt is not allowed and failed to get token: ver:2.0.4-alpha
onError : Refresh token is failed and prompt is not allowed
how can i resolve this error and get or refresh token silently?
tnx in advance.
If you want to get the token silently, there are two ways for using Azure AD V2.0 endpoint.
First, acquire the access token and refresh token interactively, then get the access token in the cache or renew the access token using refresh token via acquireTokenSilent method.
Second is that the Azure AD V2.0 endpoint also support the Client Credentials flow(refer here) which normally used for the service daemon application. However the MSAL for android doesn't support this flow at present. You need to implement it yourself. You can follow this article about detail of this flow. And this flow only works for the Azure AD account.
I am trying to login to firebase using google login. The google login is successful. After this I invoke authWithOAuthToken and I am getting below error.
Due to another authentication attempt, this authentication attempt was aborted before it could complete. Error Code = -5
Few other questions:
Do we need to call authWithOAuthToken at all (after google login)? I noticed I could add data to firebase database even without call.
If above is not required, how can I get uid (which is firebase user id same across providers). At present we can get this from AuthData.
Code Snippet Below.
baseFirebaseRef.authWithOAuthToken("google", oAuthTokenStr, new Firebase.AuthResultHandler() {
// #Override
public void onAuthenticated(AuthData authData) {
// the Google user is now authenticated with your Firebase app
Log.d(currentScreenName, "------On Firebase Authentication. Success");
}
// #Override
public void onAuthenticationError(FirebaseError firebaseError) {
// there was an error
Log.e(currentScreenName, "------Error On Firebase Authentication......." + firebaseError.getDetails() +
"Error Message = "+ firebaseError.getMessage() + " Error Code = "+ firebaseError.getCode()) ;
}
});
I called unauth() and then called authWithOAuthToken().