Multiple account's linked to one (Admin) Firebase - ios

I am trying to create "child" accounts for a registered user.
So, after signing up and authenticating the account I would like to give that user the possibility to register further accounts; for other people to use without the need of an additional email or authentication. These child accounts would be linked back to the main user and that main user can delete/update them.
I am not sure if this is possible with Firebase. I have done some research but have not found a simple or any solution.
Thank you in advance.

The answer is yes, you can do that but there are caveats.
The biggest one is an admin/user situation is that when .createUser is called from the admin account (on the device) it will automatically log IN the createdUser and log OUT the admin. There are a number of posts regarding this behavior.
There are a number of options but one that I would suggest is to leverage the Firebase Admin Auth API which allows you to manage users without having to continually utilize the Firebase Console or do one of the workarounds required on the client side. A node.js example of creating a user looks like this
admin
.auth()
.createUser({
email: 'user#example.com',
emailVerified: false,
phoneNumber: '+11234567890',
password: 'secretPassword',
displayName: 'John Doe',
photoURL: 'http://www.example.com/12345678/photo.png',
disabled: false,
})
.then((userRecord) => {
// See the UserRecord reference doc for the contents of userRecord.
console.log('Successfully created new user:', userRecord.uid);
})
.catch((error) => {
console.log('Error creating new user:', error);
});

Related

Google firebase manual database post approval

is there a way to manual approve the posts that is being posted to the firebase database through the rules?
the current rule is like this:
{
"rules": {
".read": true,
".write": true
}
}
what I meant is to allow the users to post from into database, but I as an admin control the posts either approve or reject the post from firebase console, is that possible through the rules?
like this Manual approval / rejection of user registration by admin using Firebase
There is nothing built into Firebase for such an approval queue, but you could definitely build it into your app on top of Firebase.
What you essentially do is create a so-called moderation queue, that the users post to. So you end up with two top-level nodes:
posts
post1: ...
post2: ...
post3: ...
pending
post4: ...
post5: ...
The users of your regular app only see the data from /posts.
Then you create a separate app for your moderators, and that app shows the posts in the moderation queue (/pending above) and gives them the option to approve or reject them. If they approve the post, it is added to the actual list of postings that users of the regular app see.
If the app for your moderators is running in a trusted environment, you could consider using the Admin SDK, which ignores the security rules and always has full access to your database. In that case your rules could be as simple as:
{
"rules": {
"posts": {
".read": true
},
"pending": {
"$postid": {
".write": "!data.exists"
}
}
}
}
This allows anyone to read the posts, but only administrators can write them. On the other hand, anyone can write to the moderator queue (as long as they're not overwriting existing data), but only administrators can read from there.

Implementing Pusher Chat in Rails and React

I'm using this repo to create a chat system between 2 users in a Rails and React project. I've been able to log the user input into the console, and I have created messages_controller and message_threads_controller according to the repo.
However, I'm unable to persist the message to Rails db and then authenticate a user with Pusher before sending it to Pusher. Mainly because the from_uid, to_uid and thread_uid are not present by the time the message is been sent to Rails. Sending the message to rails like this:
sendMessage = (event) => {
event.preventDefault();
const {message} = this.state;
axios.post('/api/v1/messages', {message: message})
.then((response) => {
console.log(response);
})
console.log('send Message')
this.setState({'message': message});
console.log(this.state.message);
}
In my routes.rb file I have this
resources :messages
get 'threads/:id', to: 'message_threads#index'
post '/pusher/auth', to: 'pusher#auth'
I'm missing some required parameters, this is the error I get.
Pusher::Error - Bad request: Missing required parameter:
The flow according to this tutorial is that the message needs to be persisted first by the rails database before sending it to Pusher.
My question now is how do I produce the extra parameters (from_uid, thread_uid, to_uid) being used on the React side of the app here, to enable messages to be created?
Also, how do I authenticate the user using Pusher?
According to this Stack Overflow link they are getting from Rails the CSRF value like this - csrf = $('meta[name=csrf-token]').attr('content'). But I could not implement the same in React.
Answer from the author of the git repo.
The example I created here was pretty bare bones but below are a few bullet points that I hope will explain how you could expand on it.
Add a User model and Thread model to the Rails app
When a User is created, generate a public UID for the user (you can use Ruby's built-in SecureRandom.uuid to generate the id) and save that to the DB. This would become the ID for that user that you would expose in your javascript to allow for communications between users. All users would have a UID.
When a Thread is Created, generated a thread UID this would become the unique id for the conversation taking place
Add a Users_Threads has_and_belongs_to_many relationship so that you can eventually track the users that are subscribed to which threads
When React app loads, use an Ajax request to get a list of the current User's friends (returns list of user details + their uid) and a request to get all threads for current User
So let's say for example a User named Fred clicked on a User named Bob and wanted to send Bob a message but they do not currently have a thread. Fred types the message, clicks Submit and you send an Ajax request containing the message text, from_uid (Fred) and to_uid (Bob) with thread_uid as null (since there is no existing convo and no existing thread).
Your Rails app then receives that requests at a controller and sees that Fred is trying to send Bob a message and the thread ID is null, so the controller create a new thread (with its own UID) and then add two entries to users_threads one for the new thread_uid and bob's uid and another for the new thread_uid and Fred's uid. After that, you'd create a Message with that thread_uid and the participant details.
You'd also probably want users to see that they are part of a new thread without having to reload the page so you'd I think you'd want a Pusher channel subscription just for notifying users of a new thread. So I'd say in the UserThreads model after create a new thread you could send something like Pusher.trigger('threads_channel', user_secret_uid, { thread: new_thread_uid }). You'd also need to make sure in the react app that each user subscribes to the threads_channel for their user_secret_uid. For security, i'd make sure this is a different uid than the messaging otherwise people could subscribe to a list of a different users threads.

Test database for username without authentication [Firebase/Swift 3]

My problem currently is that when a user wants to create an account on my app (using Firebase) the following error occurs:
2017-07-12 21:57:05.958 GeneralMessage[8525] [Firebase/Database][I-RDB038012] Listener at /users failed: permission_denied
I realise that the error occurs because the user attempts to read from the database without being signed in to an account (authenticated). The problem also being that the user will NEVER be authenticated at the time they are testing if a name is taken (before they make the account).
I know that you can edit the Realtime Database rules to allow unauthenticated users to access the database but I also read that this was a security hazard and should only be used during testing.
My idea was to temporarily authenticate the user when they click the 'Create Account' button but I am also unsure about how I would do this.
Thank you for any help :)
If you want unauthenticated users to be able to read part of your database, you'll need to modify your security rules to allow that. There is no way to do this temporarily for a specific app instance, since that would require each app instance to be identified - like a user.
I know two approaches:
Sign the user in with anonymous authentication first
Store the user names in an unprotected part of the tree
Sign the user in with anonymous authentication first
Alternatively you can initially sign the user in with anonymous authentication:
Auth.auth().signInAnonymously() { (user, error) in
// ...
}
This only partially secures data access: since the user doesn't prove their identity, it's relatively easy for anyone to still get access to the data. That's why I recommend limiting the data they can access by...
Store the user names in an unprotected part of the tree
This approach is quite common: you want the usernames to be publicly readable, so you store that in a separate part of your database.
usernames
"T. Dess": 8295647
"Frank van Puffelen": 209103
And then with your security rules:
{
"rules": {
"users": {
".read": "auth !== null",
"$uid": {
".write": "auth.uid === $uid"
}
},
"usernames": {
".read": true
}
}
}
So with these rules:
Anyone can read the usernames
Any authenticated user can read the user profiles
Each signed in user can only modify their own user profile

How to create a "backdoor" for administrator, to be able to log in as anohter user and see information?

I am creating an online survey tool.
As an administrator, i would like to see what the users have answered and also be able to answer on their behalf. The system get's a users answers and other information based on his/her username, when they are logged in, using the built in membership provider.
There are currently three roles: Administrator, Moderator and Respondent
If i would like to show my administrator a list of users,
how would it be possible to create a "backdoor" for the administrator, so that he can "log" in as the user, see the users answers etc ? (Just like the user would be able to if he was logged in to his own account).
When answering and retrieving quyestions, the system is bound to `User.Identity.Name
My suggestion on how to solve this:
Currently, when i want to retrive a users answers i use the following code:
Firma_ID = db.Firma.Single(x => x.CVR_nummer == User.Identity.Name).firma_id;
var answers = db.Tabelform_Answers.Where(x => x.question_id == model.Question_ID && x.respondent == Firma_ID);
This is because i have a table named Firma, that has a column referencing to a users Name, called CVR_Nummer. I then retrieve all the records in the Tabelform_Answers table, that match question_id and Firma_ID (A users answers for a specific question).
Instead of using `Firma_ID = db.Firma.Single(x => x.CVR_nummer == User.Identity.Name).firma_id;
to retrive the Firma_ID of a given user, i could store it in the Session upon Login. When i want to view a specific users Answers as Administrator, i would then just change Firma_ID in the Session. Changing Firma_ID in the Session would only be allowed through a controller which has the following code:
[Authorize(Roles = "Administrator")]
Also, i would set the Session timeout to be the same as the Authentication timeout.
Can somebody tell me which pros and cons of this solution? Are there any other ways of storing a "global" variable for a Session? (Firma_ID)?
Thanks
If you only need to log in as your users, I went for a ticket-method.
I have a special login-page that can take a ticket-id. This ticket is created in the admin-gui when the admin wants to log in as another user. The login-page checks the ticket in the database, logs in the wanted user, and then deletes/marks the ticket as used. As an added security, a ticket is only valid for 10 seconds after creation.
Another option is to make answers from users available from the admin-gui...
also you can do in your log-in script override
so you have at present something like
if user name and password match string then user is logged in and based on this you get user permissions
instead have admin page,
where you can select user and then you can apply permissions of the user instead of admin.

symfony - credentials problem

I am trying to fully understand how the credentials/permissions system works in symfony(1.4)
I have 2 groups and 2 users.
User 1 has the following permissions:
Add.Car, Delete.Car
User 2 has the following permissions:
Add.Bike, Delete.Bike
Now what I want to do, is only allow users with the Add.x permissions to be able to add to a category table.
The problem is, that If I have:
credentials: [Add.Car, Add.Bike] - it seems to look for users with BOTH of these, not either of them.
Is this how the credentials work and If so, is there a way to check if the user has either Add.Bike OR Add.Car before allowing them to create new records?
Thanks
Wrap the credentials in [ ]
credentials: [[Add.Car, Add.Bike]]
see http://www.symfony-project.org/jobeet/1_4/Doctrine/en/13 'Complex Credentials' section

Resources