check current password before updating user password #4042
|
I want this behaviour like in this image bellow:
The available choice is: const { user, error } = await supabase.auth.update({ password: newPassword});With this code anyone has opened the user profile page can update the password! |
Replies: 14 comments 27 replies
|
I think the intended way to change a password is with a reset password email |
|
I did this 👇 as a RPC function create or replace function change_user_password(current_plain_password varchar, new_plain_password varchar)
returns json
language plpgsql
security definer
as $$
DECLARE
_uid uuid; -- for checking by 'is not found'
user_id uuid; -- to store the user id from the request
BEGIN
-- First of all check the new password rules
-- not empty
IF (new_plain_password = '') IS NOT FALSE THEN
RAISE EXCEPTION 'new password is empty';
-- minimum 6 chars
ELSIF char_length(new_plain_password) < 6 THEN
RAISE EXCEPTION 'it must be at least 6 characters in length';
END IF;
-- Get user by his current auth.uid and current password
user_id := auth.uid();
SELECT id INTO _uid
FROM auth.users
WHERE id = user_id
AND encrypted_password =
crypt(current_plain_password::text, auth.users.encrypted_password);
-- Check the currect password
IF NOT FOUND THEN
RAISE EXCEPTION 'incorrect password';
END IF;
-- Then set the new password
UPDATE auth.users SET
encrypted_password =
crypt(new_plain_password, gen_salt('bf'))
WHERE id = user_id;
RETURN '{"data":true}';
END;
$$I got this error: But when trying these lines in the supabase sql editor: SELECT id
FROM auth.users
WHERE id = 'THE-USER-ID'
AND encrypted_password =
crypt('THE-USER-PASSWORD'::text, auth.users.encrypted_password);
-- And
UPDATE auth.users SET
encrypted_password =
crypt('NEW-USER-PASSWORD', gen_salt('bf'))
WHERE id = 'THE-USER-ID';The code is run successfully! WHY?Edit:The function is working fine, I just moved the If you got the |
|
Does your search path include extensions? I ran into this with the http extension. Although your error sort of implies it found the crypt function.... |
|
It might be the user who created the function does not have access to the auth schema. Crypt would probably fail with that salt error if auth.user.encrypted_password can't be accessed. The SQL console is run as superuser. This would let queries work standalone. Security Definer on the function means it runs with permissions of the creator. Did you create the function in the SQL console or elsewhere? I'm not sure if Supabase has any other sort of protection on auth.user as in general they don't want you accessing it (hence the auth.uid() type functions), but you were able to use it as superuser in sql console so don't think so. |
|
@zakaria-chahboun Since I was considering using something like you have, I tested it out. .rpc('change_user_password', { 'current_plain_password': "Sblgfsjgrijg", 'new_plain_password': 'lflflfllflflllf' }) I created it in the sql editor window on Supabase UI. For what it is worth my search_path for the sql user is: ""$user", public, auth, extensions" although I'm skeptical that matters. Edit: Did you by chance first create the function in the database page of the UI initially? I don't think create/replace changes the original owner and I believe that is a different user there. |
|
In case someone is looking for a quick solution here it is. This returns |
|
I'd leave this information for anyone who might had faced the In my case, it was because the user I'm connected with does not have his password set yet, because he's signed up using a provider (google in my case) |
|
Well, here is another approach if you dont want to deal with the "rpc" or sql stuff. (User must be logged-in) |
|
I was successfully using abdulrahimiliasu's solution above, until I migrated from Unsure how that broke it, but found declaring the auth.uid first has fixed it. CREATE SUPABASE FUNCTION: NEXT.JS: |
|
@kiwicopple wouldn't this be a nice feature for the supabase Auth library? To add a functionality for an optional parameter "oldPassword" to the "auth.updateUser()" function? Actually, there is already a feature request for this: https://github.com/orgs/supabase/discussions/18820 |
|
to disable previous method auth.update(email) and making only way to update with rpc function above : |
|
If you wanna have more control over this workflow, you could use the following rpc that only confirms the current password. You can run the rest of the flow using the SDK CREATE
OR REPLACE FUNCTION confirm_current_user_password (current_plain_password TEXT) RETURNS json LANGUAGE plpgsql SECURITY DEFINER AS $$
DECLARE
user_id uuid;
BEGIN
user_id := auth.uid();
IF NOT EXISTS (
SELECT 1
FROM auth.users
WHERE id = user_id
AND encrypted_password = crypt(current_plain_password::text, auth.users.encrypted_password)
) THEN
RAISE EXCEPTION 'incorrect password';
END IF;
RETURN '{"data":true}';
END;
$$; |
|
I wish Supabase had a verified password method for those more secure platforms. An RPC can be missed during the launch of a new platform, complicating what should be pretty straightforward. |
|
Unfortunately this method is not secure since the client can still call |

I did this 👇 as a RPC function