Hi, we are using a mixture of our own UI with the pre-build components. we also uses passwordless lo...
i
Hi, we are using a mixture of our own UI with the pre-build components. we also uses passwordless login. My question is if there is a simple way to implement a logic of: 1. if you are have a deep link to our app, get the tenant based on the link 2. try to login to that tenant 3. if you are not register to this tenant just reject the login process and don't do signup to the tenant (which is the default behaviour) In addition if there is a way to do 1, how to I pass SignInAndUp component from 'supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui' the tenant to login to?
Don't know if this is the right answer but it seems like: for 1. I will have to set it to the local storage according to this example: https://supertokens.com/docs/thirdpartypasswordless/common-customizations/multi-tenancy/common-domain-login#step-2-ask-for-the-tenant-id-on-the-login-page and for 3 I would have to do some BE override to chack if the email already exists using the API and if it exists in the specific tenant: https://supertokens.com/docs/thirdpartypasswordless/advanced-customizations/backend-functions-override/usage is that the only option? is the tenant ID we are about to login available in the function override context?
r
you are right. The backend override functinos to get the tenantId as an input. If the tenant doesn't exist though, the API will throw a 500 error to the frontend anyway. So maybe thats already an OK behaviour for you
i
no the tenant exists for sure, I just don't want to let users to directly join a tenant based on deep links and not invites
which function should I override in the BE?
createCode I assume?
r
yup! createCode
or createCodePOST API. In the override.api
i
this if I wish to do the check after the code is created, right? the USER will be created only after the cunsome, am I right?
r
the createCodePOST API is called to create the code and send the user the email / sms
and the consumeCodePOST API is used to consume the code and create the user + the session
i
when I start work with direct logins to tenants, should I expose through my API gateway all of the following endpoints? auth/{tenantId}/signinup/code auth/{tenantId}/signinup/code/consume auth/{tenantId}/session/refresh auth/{tenantId}/signout or all of them except the first one are agnostic to the tenant?
also I would like to modify the tenant durinng the function override. I have tried to just modify the input.tenantId which seems to work but the magic link comes in the email still contains the tenantId from the original request which I assume will cause the FE to fail. how can I handle it?
r
just signinup/code and siginup/code/consume need to have tenantId. The other 2 APIs get the tenantId from the session
which function are you overriding? This should have worked.
i
createCode
i'm doing inside of it:
Copy code
input.tenantId = 'public';
return await originalImplementation.createCode(input)
and I get a in the email that includes the original tenant in the query params which I assume will cause the FE to add it to the path when it tries to verify which will lead to a failure
r
Oh. You are overriding the override.functions
Instead, do this in override.apis
Override the createCodePOST
i
but isn't createCodePOST happens after I called supertokens?
or I miss something in the flow
r
POST is the request method. like GET or POST
the POST just means it's a post API
i
ohhh
r
hahaha
i see your confusion
fair enough
i
naming is everything 🙂
r
yeaaa.. naming is very difficult
i
will give it a try
so just to give a general guideline in which usecase should I override the function and in wich the api?
r
it's really depends on the use case.. the API calls a bunch of functions as part of the API logic. So if you want to affect all those functions somehow, override the API, else override the specific funciton
i
thanks, that works now
one last thing regards the magic link in this context. assuming I have a deep link for my app but I don't have a valid token, I will be redirected to the login page with the redirectToPath query param. If I do the login in the browser it works well, but is there a way to add in this case the deep link to the magic link in the email?
r
Sorry, I don’t understand the question. Could you rephrase?
i
sure, our usecase is: 1. we send weekly email to our clients which contains deep links to the system 2. the client click on one of the links 3. in case the client doesn't have a valid token the FE redirect them to /auth?redirectToPath= if in that stage the client complet the login using the same browser session, meaning type in the OPT code. The FE will redirect the client well to the right page. on the other hand if the client will click the magic link in the OTP email I don't think this will happen because we lost the redirectToPath query param, but maybe i'm wrong. the question is am I wrong? and if not how to make it work 🙂
r
So where do you want to client to end up after login?
i
in the redirectToPath
r
Which is set where? In the url?
i
yes, this is the default logic your components add
r
I’m not sure I fully understand your situation here. The redirectToPath is added when visiting the /auth route from another page. That value is saved in browser storage, so that when the magic link is clicked, the user is redirected to the path that’s mentioned in the browse storage.
The magic link by itself doesn’t have the redirectToPath in it
i
it is not being saved to the storage by default, or we broke something in our implementation
r
Ur using custom UI right?
The behaviour i said happens with our pre built ui
i
yea we do custom UI with your components
but even in that case it won't work if the user open the link in a different browser
r
Yea
i
so the question is if there is a way dynamically pass path params to be added to the magic link?
r
You could override the getRedirectionUrl function in the Passwordless.init function on the frontend
And then in case of the SUCCESS context, check the url in the browse and extract the path from it and redirect the user there
i
but I still need to make this url param to appear somehow in the magic link if I wish it to work cross devices/browsers
r
Yea. That, you can do via override of sendEmail function on the backend
i
yea but I this function to get somehow information from the FE regards the right URL
r
U mean you want to access info from the frontend in this function?
i
yes
r
You can get access to the req object in that function via the userContext
i
I want to FE to pass somehow the redirectToPath valud to the BE so in this function I will be able to append it to the link
You can pass that as a custom prop in the create code api and then read it in the sendEmail function
And add it to the link and then on the frontend, use that in the getRedirectionUrl to redirect the user to the right place
i
so I need to override the createCode api in the FE, right?
r
Well, the preapihook for that
See the link above
i
ohh cool as a BE develop I jumped straigth to the second part 🙂
r
Fair
i
one more question on that topic, so now I do some logic that replace the tenant but the OTP flow fails in the consume call with
RESTART_FLOW_ERROR
the logic replace the tenant in the
createCodePOST
api override. I guess the failure is because the FE doesn't know about the change of the tenant and try to call consume with the old tenant
is there a way to overcome that?
r
you also need to raplce the tenantId in the consumeCodePOST in a similar way
i
fair point
but I don't have there the userId or user email to do the calculation
r
you can get the email based on the preAuthSessionId which is an input to the consumeCodeAPI
the passwordless recipe has a function using which you give it the preAuthSessionId, and it returns the email associated with that
i
listCodesByPreAuthSessionId ?
if this is the function I can't use it cause it requiere tenantId which I don't know
the only option I can think of is to modify the createCodePOST response and add the tenant Id as a header/cookie or in body. I just don't understand where should I modify the FE to read this value
r
right yea. that's the way to go. On the frontend, there is a post API hook which you can hook into to read the custom prop from the response. And then save that in localstorage or somewhere. In the frontend's multitenancy.init, there is a function called getTenantId which you need to provide. In that, you can read from localstorage to return the tenantId you had set.
i
onHandleEvent ?
PASSWORDLESS_CODE_SENT
r
Nope. There is a post api hook config
Similar to how we have pre api hook
At least for the auth-react SDK
i
i'm using supertokens-auth-react
can you send me a link to the docs?
r
Hmm. We don’t have docs for it. Strange
But it should be the same as preApiHook, but instead of calling it that, it’s called postApiHook
i
I couldn't find it either by the types
r
Let me check
i
my thought right now it to add it as a cookie and relay on the browser to send it back to create a limited time cookie that is bound to the login page specifically with strict config but I would prefer to relay on your SDKs if possible
r
Copy code
Passwordless.init({
            contactMethod: "EMAIL",
            async getRedirectionURL(context, userContext) {
                return null;
            },
            postAPIHook: async (context) => {
                if (context.action === "PASSWORDLESS_CREATE_CODE") {
                    let response = context.fetchResponse
                    // TODO..
                }
            }
        }),
go for the route in which you set a custom header response and then save that on the frontend. It's easier i think
but cookie way works too.
i
the header and set it on the FE means I don't need to override the consume function in the BE on the other hand it adds logic to the FE the cookie is BE only solution pros and cons...
r
Yup.
i
i'm a BE guys 🙂 so I can say what I prefer. but I will try the other option as well just to see how it works for me
Your approach won't work cause we don't go throught the
getTenantId
function after we initialize the login process. so becausse i'm changing the tenant in the createCodePOST from the FE side the process already initiated. and even if I override the postAPIHook and set the new tenant to the localstore it won't go through the getTenantId function in the consume code. I think we left only with the cookie part, unless there is something I can do in the preAPIHook,
PASSWORDLESS_CONSUME_CODE
that will change the process in the middle or send this data in the request
r
right. What you can also do is to provide the pre api hook fpr consume code, and then change the URL to replace the tenant id that we pass in with the one that you have. The tenant id is a part of the url like
/auth/<tenantid>/code/consume
i
yea, I guess this is going to be the solution
will think which on is the best