GitKit Client - Uploaded users cannot connect - google-identity-toolkit

We have an existing user database with SHA1-encoded passwords. We upload them to the Google Federated Database (through the GitKitClient java lib), but then these uploaded users can't log in The verifyPassword always returns "Incorrect password" ! The call to the uploadUsers looks like gitkitClient.uploadUsers('SHA1', new byte[0], gitkitUsers)
(We must provide an empty byte array as second param (hash key), since we get NPEs if we provide a null value)
The method that creates the GitkitUsers that are in the list is as follows:
private GitkitUser createGitkitUserFromUser(User user) {
GitkitUser gitkitUser = new GitkitUser()
gitkitUser.email = user.email
gitkitUser.localId = getLocalId(user)
gitkitUser.name = user.displayName
gitkitUser.hash = user.password?.bytes
if (user.pictureFileName) {
gitkitUser.photoUrl = user.getPictureUrl()
}
return gitkitUser
}
We see no way to further investigate. Did someone successfully use it ?

Make sure that the hashKey you use in setPassword() is the same one used in uploadUsers().
I am using the php SDK so I can't share code for you, but when I did NOT use the same hashKey for both places, I had the same problem.

Related

Unique field in Firestore database + Flutter

I'm trying to implement a normal authentication system in my app, but I'd like to create a new field for each user that is the "uniqueName" so users can search and add each other in their friends list. I was thinking of adding a textField in the signup form for the uniqueName and updating my User class adding a new String in this way:
class User {
String email;
String name;
String uniqueName;
String userID;
String profilePictureURL;
String appIdentifier;
...
}
Now, since I have this method for the email&password signup:
static firebaseSignUpWithEmailAndPassword(String emailAddress,String password,File? image,String name,) async {
try {
auth.UserCredential result = await auth.FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: emailAddress, password: password);
String profilePicUrl = '';
if (image != null) {
await updateProgress('Uploading image, Please wait...');
profilePicUrl =
await uploadUserImageToFireStorage(image, result.user?.uid ?? '');
}
User user = User(
email: emailAddress,
name: name,
userID: result.user?.uid ?? '',
profilePictureURL: profilePicUrl);
String? errorMessage = await firebaseCreateNewUser(user);
if (errorMessage == null) {
return user;
} else {
return 'Couldn\'t sign up for firebase, Please try again.';
}
}
how do I have to modify it in order to add this new field in the registration? Since I have to check that the uniqueName insert by the user is effectively unique before creating a new user in the database, what can I do?
Furthermore, I think that it would be cool if this check is made concurrently to the filling of the form, how can I do it? (this is not necessary)
Thanks everyone for the answers
You have to save your users in a collection, then check if uniqueName already exists in the collection. If it exists, return error.
Then when a new user account is created, save the uniqueName.
// this function checks if uniqueName already exists
Future<bool> isDuplicateUniqueName(String uniqueName) async {
QuerySnapshot query = await FirebaseFirestore.instance
.collection('PATH_TO_USERS_COLLECTION')
.where('uniqueName', isEqualTo: uniqueName)
.get();
return query.docs.isNotEmpty;
}
// call the above function inside here.
static firebaseSignUpWithEmailAndPassword(String emailAddress, String password, File? image, String name,) async {
if (await isDuplicateUniqueName(name)) {
// UniqueName is duplicate
// return 'Unique name already exists';
}
// ... the rest of your code. Go ahead and create an account.
// remember to save the uniqueName to users collection.
I suggest doing the following steps:
Create your own users collection (for example users) in Firestore, which you might have done already. (I don't think that User is a good class name, since Firebase Authentication is using the same name. Try MyUser or something.)
Add authentication triggers that will ensure that whenever a Firebase user is added or deleted, it will also be added to or deleted from users collection, use Firebase uid as identifier.
Create a solution to check whether a uniqueName already exists in users collection. You can use a Firestore query, but in this case you have to allow unauthenticated access to read users, at least uniqueName field. (Since the user is not authenticated yet at this point.) A Firebase Cloud Function is another option.
When users enter their desired uniqueName, run the check before creating Firebase user. You can do it when user enters this or when you start the signup process.
If uniqueName is unique, you can try to create Firebase user. Be aware, this step can also fail (for example e-mail name taken etc.). Your users document will be created by the authentication trigger you set up in step 2.
Finally, you have to store this uniqueName in users collection. At this point you will have uid of the newly created Firebase user, so you can use Firestore set command with merge option set to true, so you don't overwrite other data.
It is important to note that you can't guarantee that the Firebase trigger already created the new document in users by the time you arrive to point 6, it is very likely that the trigger is still working or not even started yet. That's why you have to use set both in the authentication trigger and in your own code that sets uniqueName: which "arrives" first, will create the document, and the second will update it.
Also, for the same reason, you have to allow inserts and updates into users collection with Firestore rules. This might sound a little scary, but keep in mind that this is only your own user list to keep track of uniqueName, and authentication is based not on this, but on Firebase Authentication's user management which is well protected.
Last comment: this is not a 100% solution. It is quite unlikely, but theoretically can happen, that some else reserves a uniqueName between you check whether it's unique and the user is actually created. To mitigate this, it is a good idead to make the check just before Firebase user is created. Even in this case a slight chance remains for duplicates.

User-Id for Push-Notification on Actions for Google

I try to make a push notification for my google assistant app.
I used the sendNotification Code form the google developer site: https://developers.google.com/actions/assistant/updates/notifications
I am coding Java.
Everything is working, expect getting the correct user id.
When I hardcode my user it works, but how do I get the user id in the code?
I tried following code:
Argument arg_userId = request.getArgument(ConstantsKt.ARG_UPDATES_USER_ID);
String userId = request.getUser().getUserId();
--> I get "java.lang.reflect.InvocationTargetException"
String userId = arg_userId.getRawText();
--> same Exception
There are two problems with the approach you're taking to get the notification ID:
The ID attached to the user object is deprecated and probably unavailable.
This wasn't the ID you wanted anyway.
In the response where the user finalizes the notification, that response includes an ID which you should get and store. Since you're using Java, the code might look something like this:
ResponseBuilder responseBuilder = getResponseBuilder(request);
Argument permission = request.getArgument(ConstantsKt.ARG_PERMISSION);
if (permission != null) {
Argument userId = request.getArgument(ConstantsKt.ARG_UPDATES_USER_ID);
// code to save intent and userID in your db
responseBuilder.add("Ok, I'll start alerting you.").endConversation();
} else {
responseBuilder.add("Ok, I won't alert you.");
}
return responseBuilder.build();

problem in Flutter with Sqflite exception

I have a problem with my code, I wrote simple flutter app which is f note app, and I have included SQLite as a database , I run the app at first via the emulator and everything went cool , but when I tried to run it on my real device (which is an android device), the database did not respond (i.e I could not add new notes to the database ) and when I went back to run my app via the emulator .. the app did the same thing I found in my real device and in console I found this error
Error: Can't use 'SqfliteDatabaseException' because it is declared more than once.
I need help Please
I saw your code and the problem is that the exception you get is probably related to this one:
PlatformException(sqlite_error, UNIQUE constraint failed: Notetable.id
And it's because you need to manage the unicity of your primary key when you insert a new row. You can have a look at this SO question for a quick reference.
So just to quickly make your code working I've made this changes (please take this code only for reference, write a better one):
void createDataBase(Database db,int newVersion) async{
await db.execute('CREATE TABLE IF NOT EXISTS $noteTable ($col_id INTEGER PRIMARY KEY ,'+
'$col_title TEXT , $col_description TEXT , $col_date TEXT,$col_priority INTEGER)');
}
And
Future<int> insertData(myNote note)async{
var mdatabase = await database;
var _newNoteMap = note.convertToMap();
_newNoteMap['id'] = null;
var result = await mdatabase.insert(noteTable, _newNoteMap);
return result;
}
Pay attention that you always call a DB insert even when you update an existing note.
UPDATE: added additional modification (not listed before)
in databaseObject.dart
Map<String,dynamic> convertToMap(){
var mapObject = Map<String,dynamic>();
mapObject["id"] = _id;
mapObject["title"] = _title;
mapObject["description"] = _description;
mapObject["date"] = _date;
mapObject["priority"] = _priority;
return mapObject;
}
in Note.dart
if(res >= 1){
showAlertDialog('Status', "New note added successfully and the value of result is $res");
}

How to check if users owns the object in Firebase bolt compiler

Supposing I have a simple schema with two collections users & posts. Each post object has a key, value pair (ownerId:userId) to find out which users owns the posts object.
users/{1,2,3...}
posts/{a,b,c...}/ownerId:userId
I am trying to write the rules where user can only read/write his user data and his posts.
For this the bolt rules for the user is quite straightforward:
isUser(uid) = auth != null && auth.uid == uid;
path /users/$uid {
read() = isUser($uid);
write() = isUser($uid);
}
My Question is how can I secure the posts collection to be only accessed by the user. Can I check the ownderId property of the posts collection in rules? If so how, If not they how can I structure my schema to do it?
EDIT
I am trying to secure the posts path like this:
path /posts/$pid {
read() = isUser(this.ownerId);
write() = isUser(this.ownerId);
}
Is this the correct way to do this?
We can do this by adding a owner Id property to the collection and then checking if the user is authenticated.
path /posts/$pid {
read() = isUser(this.ownerId);
write() = isUser(this.ownerId);
}

Storing DotNetOpenAuth information and user info retrieval

This question is a bit of a structural/design question as I'm having trouble working out the best way to perform the task.
In my MVC app, I am using DotNetOpenAuth (3.4) as my login information provider and just using the standard FormsAuthentication for cookies etc.
The current user table in the DB has:
UserId (PK, uniqueidentifier)
OpenIdIdentifier (nvarchar(255))
OpenIdDisplay (nvarchar(255))
Displayname (nvarchar(50))
Email (nvarchar(50))
PhoneNumber (nvarchar(50))
As the UserId is the clear identifier for a user (they should be able to change their OpenId provider at a later date), it is the key that other tables link to (for a user).
This is the current code, that on a successfull authentication, creates a temporary user and redirects to Create Action.
switch (response.Status)
{
case AuthenticationStatus.Authenticated:
FormsAuthentication.SetAuthCookie(response.ClaimedIdentifier, false);
var users = new UserRepository();
if (!users.IsOpenIdAssociated(response.ClaimedIdentifier))
{
var newUser = new DueDate.Models.User();
newUser.OpenIdIdentifer = response.ClaimedIdentifier;
newUser.OpenIdDisplay = response.FriendlyIdentifierForDisplay;
TempData["newUser"] = newUser;
return this.RedirectToAction("Create");
}
And now for the crux of the question:
Is the response.ClaimedIdentifier the correct piece of information to be storing against a user?
Is FormAuthentication.SetAuthCookie the preferred way to forms authentication? Or is there a better way?
When I call SetAuthCookie, there is no data relating to the user except for the ClaimedIdentifier. If I'm consistently referring to their UserId, is a better idea to create the user, then store that UserId in the cookie instead of the ClaimedIdentifier?
If I'm using that UserId in a number of places, how do I either retrieve it from the cookie, or store it somewhere else more logical/useful?
A bit long winded but I've been having trouble trying to work out the best way to do this/
1.Is the response.ClaimedIdentifier the correct piece of information to be storing against a user?
Yes. And make sure the column you store it in the database with is case sensitive. Here is a table schema that demonstrates how to make sure it is case sensitive. This comes out of the DotNetOpenAuth project template's database schema. The "CS" bit of the specified collation stand for Case Sensitive.
CREATE TABLE [dbo].[AuthenticationToken] (
[AuthenticationTokenId] INT IDENTITY (1, 1) NOT NULL,
[UserId] INT NOT NULL,
[OpenIdClaimedIdentifier] NVARCHAR (250) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL,
[OpenIdFriendlyIdentifier] NVARCHAR (250) NULL,
[CreatedOn] DATETIME NOT NULL,
[LastUsed] DATETIME NOT NULL,
[UsageCount] INT NOT NULL
);
2.Is FormAuthentication.SetAuthCookie the preferred way to forms authentication? Or is there a better way?
For MVC apps it definitely is, since you still can return your preferred ActionResult from the method.
3.When I call SetAuthCookie, there is no data relating to the user except for the ClaimedIdentifier. If I'm consistently referring to their UserId, is a better idea to create the user, then store that UserId in the cookie instead of the ClaimedIdentifier?
That sounds like personal preference. But I would typically go with user_id, since it might result in a faster database lookup every time an HTTP request comes in that requires you to look up any user information.
4.If I'm using that UserId in a number of places, how do I either retrieve it from the cookie, or store it somewhere else more logical/useful?
FormsAuthentication does provide a way to store more information in its encrypted cookie than just username, but it is harder than you'd expect to use it. This snippet comes out of DotNetOpenAuth's web SSO RP sample:
const int TimeoutInMinutes = 100; // TODO: look up the right value from the web.config file
var ticket = new FormsAuthenticationTicket(
2, // magic number used by FormsAuth
response.ClaimedIdentifier, // username
DateTime.Now,
DateTime.Now.AddMinutes(TimeoutInMinutes),
false, // "remember me"
"your extra data goes here");
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticket));
Response.SetCookie(cookie);
Response.Redirect(Request.QueryString["ReturnUrl"] ?? FormsAuthentication.DefaultUrl);
Then you can get at that extra data in a future HTTP request with this:
var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null) {
var ticket = FormsAuthentication.Decrypt(cookie.Value);
if (!string.IsNullOrEmpty(ticket.UserData)) {
// do something cool with the extra data here
}
}

Resources