nhost icon indicating copy to clipboard operation
nhost copied to clipboard

empty session when new user signUp

Open yureckey opened this issue 3 years ago • 10 comments

I remember it worked fine when I tried it couple months ago, but now when I'm running const { session, error} = await nhostTestStore.nhost.auth.signUp({...}) the resulting session is null - but the user is created fine

yureckey avatar Aug 04 '22 21:08 yureckey

After some discussion with Szilard from the team, I would like to add: I actually don't need returned session, I need newly created user id. Returned session was empty because session is the result of signIn, which in my case wasn't happening due to "require email confirmation" enabled. I think created user (or at least id) should return alongside session. I need it to create other data entities connected with newly created user, I'm creating it on the backend.

yureckey avatar Aug 11 '22 08:08 yureckey

Could you describe your specific use case in more detail?

I have a feeling it's possible to solve your use case without getting the user id after signing up.

elitan avatar Aug 11 '22 09:08 elitan

Well, I have user_profile table with user_id column and parent_id column, so I'm connecting users to parent (company) with it. User doesn't have permission to add/edit this data, it's created alongside user SignUp on backend

yureckey avatar Aug 11 '22 09:08 yureckey

I do same as you're describing: I have a profiles table with a user_id FK.

I create the new record using an INSERT event trigger implemented in a DB function in Postgres to guarantee that a new profiles record exists for the new user. I created the function from the Hasura Dashboard:

  • Data tab
  • SQL from left hand menu
  • Write code to create the function and the trigger (my version is below)
  • Turn on 'This is a Migration' so it gets created when you deploy. I didn't want it tracked (e.g. executable from GQL)
  • This creates a DB function sync_user_profiles which works with table public.profiles
  • Modify as needed for your table.
CREATE OR REPLACE FUNCTION sync_user_profiles() RETURNS TRIGGER AS
$BODY$
BEGIN
    INSERT INTO
        public.profiles(user_id)
        VALUES(new.id);

        RETURN new;
END;
$BODY$
language plpgsql;

CREATE TRIGGER trigger_sync
     AFTER INSERT ON auth.users
     FOR EACH ROW
     EXECUTE PROCEDURE sync_user_profiles();

I actually did my coding and testing of the functions in pgAdmin directly connected to my local DB but this works fine too: the dashboard will check the code, run it and show you the results from Postgres' execution.

After function exists, you should see an up and down migration locally in your repo. The down migration might be empty - if so you can add this:

DROP TRIGGER IF EXISTS trigger_sync ON auth.users;
DROP FUNCTION IF EXISTS sync_user_profiles;

Note: you could alternately use an NHost Function instead to do work on INSERT event. I also do this when users are signed up in order to get some third party data for the user.

Hope that helps.

pkreipke avatar Aug 11 '22 13:08 pkreipke

How it solves your permission problem:

  • the DB trigger runs at a database user level so can create the row for you, basically as admin
  • you can safely assign select permission to role user on table profiles with a custom check:

With same custom check as post update, pre update {"user_id":{"_eq":"X-Hasura-User-Id"}}

Note: I've allowed users to update profiles.

pkreipke avatar Aug 11 '22 13:08 pkreipke

thanks @pkreipke, using trigger function is indeed working alternative. I just expected that returning new user id after signUp function would be simpler to use and maintain

yureckey avatar Aug 11 '22 15:08 yureckey

Fair enough, I get that there is a use case for that too. Just for discussion:

  • in your case, whatever you do on behalf of the user will be initiated from the client side once you have the ID. Which means it could be repeated or abused by a bad actor. Will need to make sure that can't happen: checking passed userID exists, new profile record doesn't already exist, ....

  • perhaps it's true in your case that the user always signs in and uses your product after signing up. In my experience on consumer apps/websites there is always a drop off of those who were just curious, give a fake email address and don't verify. Ergo, you'd be doing work for and recording info for a new user who doesn't actually become a user. That's true in my version as well (profile created automatically) and you can sweep the DB later and clean up stuff like that but doing important extra work on first sign in might be better (in spite of security issues in point 1). In my code, I consider the profile table just an extension of the user table I can clean up as needed, and better than sticking the data in the users.metadata field.

That's my $0.02 :-). As I mentioned in first comment, I also have a Function that runs on INSERT of new user that does my extra work. LMK if you need some sample code for setting up an event handling Function.

pkreipke avatar Aug 12 '22 14:08 pkreipke

I get this same thing when email needs verification is set as true using the Nhost JS SDK

on signup or sign in using email and password, both session and error return as null

Also mentioned here #545

Parables avatar Aug 29 '22 06:08 Parables

@nhost/nhost-js: ^1.4.10 Nhost CLI v0.7.8 for linux-amd64 Same thing happens even with the Cloud instance

// signup page
const { error, session } = await nhost.auth.signUp({
    email, 
    password,
    options: { redirectTo: `/success?${new URLSearchParams({ onboarding: 'welcome' })}` } // redirectTo doesn't work
});
console.log(error, session); // null, null
// nhost-client.ts
import { NhostClient } from '@nhost/nhost-js';
import {
	PUBLIC_NHOST_BACKEND_URL,
	PUBLIC_NHOST_REGION,
	PUBLIC_NHOST_SUBDOMAIN
} from '$env/static/public';
import { dev } from '$app/environment';

export const nhost = dev
	? new NhostClient({
			backendUrl: PUBLIC_NHOST_BACKEND_URL,
			devTools: true,
			autoSignIn: true,
			clientStorageType: 'cookie' // 'cookie' is for SSR, 'web' is for CSR
	  })
	: new NhostClient({
			subdomain: PUBLIC_NHOST_SUBDOMAIN,
			region: PUBLIC_NHOST_REGION,
			devTools: true,
			autoSignIn: true,
			clientStorageType: 'cookie' // 'cookie' is for SSR, 'web' is for CSR
	  });

Parables avatar Aug 29 '22 06:08 Parables

Yep, just figured out same @Parables. We are willing to allow access to mobile app features without email verification and tested what our flow would be then:

simpler onboarding for sure: signup funnel leads to drop-outs with every step nhost SDK returns user object immediately from Signup: makes sense, user becomes "real". Before that it's just a "thought" in the DB.

pkreipke avatar Aug 30 '22 20:08 pkreipke

Given what I'm reading in this thread, I think things are working as expected. After a signup request, if the user is not automatically signed in, we should not return any user information.

If not, I'm still struggling to understand the specific use case for why we should return the user information.

I'll close this issue for now and re-open it when we have a use case we can discuss around.

elitan avatar Dec 23 '22 13:12 elitan