I am trying to set up RLS to a table in Supabase that will only allow the authenticated user to UPDATE their row on users table. I have opted to use Supabase on my server rather than the front-end. My current workflow is as follows:
Client requests a OTP via email
User is emailed an OTP
OTP is entered into the Client
OTP is verified on the server
If verified UPDATE the users row in the users table with new session details
Return the current user details to the Client
Here is the code that is failing:
const { error } = await supabase
.from('users')
.update({
access_token: session.access_token,
refresh_token: session.refresh_token,
expires_at: session?.expires_at || 0
})
.eq('user_id', user.id)
.single();
Here is the table structure:
When I run const user = supabase.auth.user(); I am showing the correct user that has a user.id that matches the rows user_id column of the row I want to UPDATE.
Without RLS set up this workflow is working perfectly. Anything I try fails. Below are the three RLS that I have tried that should work.
Checking if user exists WHERE auth.uid() = users.user_id in both USING and CHECK
Added auth.uid() = user_id in both USING and CHECK
The weirdest one of the all, set true in both USING and CHECK
Here are screen shots of the uuid on the auth.users table and user_id on the users table:
Attempted this from one of the answers and it is still failing:
Here is the error response I am receiving from Supabase:
This is not very well documented yet, but signed in users have authenticated role, and not anon role, so changing the target role to authenticated should fix it. When in doubt, just leave the target roles blank, which will apply the RLS on all roles.
Related
I was wondering if there is any way to do this in hasura without resorting to creating another service.
Let me explain, in an api a user sends his token, this is decoded in the backend and and so we know who the user is, this is useful for example to search and return records in the database that only belong to this user.
Is there any way to do that with Hasura? the only return the records that belong to a certain user using its token?.
Token data is available as session data so you can use hasura column presets to insert the user id and add permission to only fetch rows that have user id equal to user id from session https://hasura.io/docs/latest/graphql/core/databases/postgres/schema/default-values/column-presets.html#column-presets
I would like to ask about logging in to Laravel but in a different way:
User information including the password but not the email will be stored in users table, while email_address will be stored in a email_addresses table with a boolean field called is_default.
So the user can have several emails, but he can log in with only one email that has the is_default is true. and he could change his default email through his profile.
So, how can I make the login process through the Auth::login() facade.
I was able to register the user by storing the information in a users table and store his email_address and is_default = true in the email_addresses table.
It can be a little tricky. Auth::login() just needs to fetch email and password, so if you can trick the model into thinking it has an email field accessible via $user->email, things will work out:
public function getEmailAttribute()
{
return DB::table('email_addresses')->whhere('default', 1)->where('user_id', $this->id)->first()->toArray()['email'];
}
I am doing authentication using azure mobile apps in my xamarin forms app and once I retrieve unique User Authentication Id, I am storing this with bunch of other user information into a sync table called Users as shown below.
So basically I am also using Azure Mobile Sync in my app. Id column below is predefined Azure Mobile Id. Everything works fine as long as I have same user with Id stored in Local sync db.
Once, if I lose this local Db information (It can be caused by reinstalling app or deleting app data). User will prompt to re-login and although I get the same Azure Authentication Id, snyc will cause a new insert into Azure Users table. Because it doesnt know that it is an existing row.
Possible Solutions is to make userAuthId as PK (eventually it is unique). But if I do that I will lose azure mobile sync feature, wont I? Can somebody shade me lights how to make Custom Id column for azure mobile sync? or instead of auto generate, i can pass the value from client.
I encountered the similar issue before, I just set the value of Id column in my users table to UserAuthId. For adding the additional UserAuthId and use it as the foreign key in other tables, I assumed that after user logged, you need to check the online Users table and try to retrieve the existing user record based on the current UserAuthId, then you could insert/update your local data store or directly update your online Users table. Moreover, I would recommend you follow adrian hall's book here about developing Azure Mobile Apps with Xamarin.
I found a solution myself following suggestion from Bruce Chen. Basically just remove the Default Value or Binding as shown in the image and on your backend Api change the Post function as below and also your controller should retrieve UserId from the authentication by calling ClaimsPrincipal as below. Using this method, you get the authenticated UserId within your Api. You can see the full implementation on this github link. So you can pass this as Id of the table. I also added extra check before I insert that if Id is already exist or not since I am not auto generating the Id.
I hope this helps to anybody else having same problem.
public string UserId => ((ClaimsPrincipal)User).FindFirst(ClaimTypes.NameIdentifier).Value;
public async Task<IHttpActionResult> PostUser(User item)
{
try
{
User current;
item.Id = UserId;
myAppsAPIContext db = new myAppsAPIContext();
User User = db.Users.Where(u => u.Id == UserId).SingleOrDefault();
if (User == null)
{
current = await InsertAsync(item);
}
else
current = User;
return CreatedAtRoute("Tables", new { id = current.Id }, current);
}
catch (Exception ex)
{
TelemetryClient.TrackException(ex);
return null;
}
}
I have a two tables in database
1. users(default user table)
2. suspend_users(only two column:- id, email)
now i want to first check in the "suspend_user" table user email exist or not if user email exist in the "suspend table" authentication failed message shows.
now i do not understand that how to check second table(suspend_users) first and how to check multiple table authenticate
I dont understand exactly what you mean, you can check first if the mail exists on the suspend_table and after check login:
example:
if (SuspendedUser::findBy(['email' => $user_email])) {
// go back to what else... throw expetion etc....
}
if (Auth::attempt(email, pass)) {} // check login
you can easily authenticate multiple table in laravel 5.1 and above.
http://blog.sarav.co/multiple-authentication-in-laravel/
Anyone know how I can get the user id for a certain user in Auth?
Let's say I am logged in with current user jalla#gmail.com, then I can get userid by
let userId = FIRAuth.auth()?.currentUser?.uid
But if I want to get the userId of the other user jarra#gmail.com while I am logged in as jalla#gmail.com.
How can I do that?
This is how I create a new user:
FIRAuth.auth()?.createUser(withEmail: txtUsername.text!, password: txtPassword.text!, completion: {
user, error in
if error != nil {
print("error: " + error.debugDescription)
}
else{
print("User created")
self.login()
}
})
Which result in the authenticated user in the image attached.
I also have a Users table, but this has nothing to do with authenticating users for login.
The thing is that I need to programatically add new authenticated users. Which is ok, but how can I query data from the Authenticated table? I need to do it because I add the authenticated uid to each user roots in the database (see User table image)
For each user, create a record in your Firebase Database and store uid for each user so that you can retrieve that uid once you need it.
If you will query uid information by using the email information of the said user (i.e. jarra#gmail.com in your case), it might be best to store user information including uid under a key of respective user's email.
If you are logging in code rather than the console, one option is to leverage a /users node.
With Firebase, it's common practice to have a /users node that stores information about your users.
users
uid_001
email: "dr#who.com"
name: "Dr. Who"
fav_food: "Jelly Babies"
uid_002
email: "homer#simpsons.com"
name: "Homer Simpson"
fav_food: "Doughnuts"
The uid's used as the key to each user node are the ones created by Firebase when the user is created.
From there, it's a snap to query for the email address which will retrieve the node in question, the parent key being the uid of the user.