Hi guys! Got a tricky thing going on that I need s...
# help
j
Hi guys! Got a tricky thing going on that I need some help to think through. I got an SaaS-app running, with NextJS and Supabase. I'm using email + password authentication and I'm also using RLS with pretty much every policy taking use of the uid() helper function from Supabase. Now a different company(I will refer to them as Company B further on), which runs their own app with their own authentication system(JWT based), wants to integrate my app into theirs and I cant find of any good way to make the onboarding and signin-flow work as smooth as possible. I'd like the onboarding flow to create a supabase-user in my database and I must therefore recieve an email and a password from the user, everything fine so long. Does anyone have a good solution to how I can approach the problem that rises when the user visits my app the second time? I don't want to present a login screen to the user, as they're already signed in to Company B's app already, which I will validate through the JWT that they send along to my app.
l
So you want Company B to be your 3rd party auth provider?
custom 3rd party auth provider
j
Yeah, exactly. But I ofc want my own email + password auth to still work as well
l
Yeah, Supabase is internally designed to handle multiple auth providers for one account (for example Google, Twitter, and Email + password)
I think that you will need to do some work in the API route to validate that incoming JWT and create a new JWT (sign it by yourself for Supabase use https://supabase.com/docs/learn/auth-deep-dive/auth-deep-dive-jwts)
j
Hmm yeah, that seems to be something in the right direction. So what you propose is that I create a new API route in my app, which will first validate that the JWT from Company B is valid, and if so I create a new JWT that I somehow use to sign in the user as a "supabase-user"?
Did I get your suggestion correct if I put it that way?
I'm protecting all my API routes right now by validating the Supabase JWT with the help of the jwt_secret. This workflow I can figure out as I will have access to Company B's jwt secret. My biggest concern is how I would go a head to sign in a supabase-user with the help of Company B's JWT.
l
You will need find from Company B's JWT user id of the user in your database and create your JWT for Supabase use. JWT is set in supabase-js by calling supabase.auth.setAuth()
j
So: 1. User starts onboarding my app from Company B's app. After a successful onboarding Company B issues a new JWT containing the newly created user_id (from my supabase db) 2. User comes to my app through Company B's app the second time, and in the JWT that they send along I can extract the id of the supabase user, and with the help of that I can "sign in" the user in supabase-land by issuing a new JWT!?
Sorry if I'm a bit slow, really appreciate that you're taking time to help ❤️
l
Yes, you got it right 👍 you can auth users in Supabase in two ways, by going throw existing auth integration, or by creating your own JWT token 🙂
j
Oh I see. So the setAuth()-function takes an access_token as its only parameter, in my case, will it be good enough with the JWT from Company B? I guess I'll have to construct in a proper way though
l
setAuth is a place for JWT sign by you. You will need to go in the first place to Supabase and find the user you what to sign in (with service key or by direct database access with some SQL client)
You need to be really sure that Company B's JWT is legit/varified, and not some hacking attempt before you create JWT for Supabase use
j
Yeah for sure, I'll keep that in mind.
But I didn't really follow along on the last thing you said though.
So I get the JWT from Company B, I validate it and extract the user_id of the supabase user I want to login. What's next?
l
Now you need to create a new JWT signed by your secret (you will find it in Supabase settings > API > JWT secret) more detail on that JWT is here https://supabase.com/docs/learn/auth-deep-dive/auth-deep-dive-jwts. And use this newly signed token in Supabase SDK.
j
Yeah I'm using the JWT Secret in my API Routes, so that one I can easily grab. So create a new JWT with the help of jsonwebtoken-package, pass in the user_id of the user and sign it with my supabase JWT-secret and then pass this newly created JWT as a parameter to the setAuth-function?
l
It is a little bit complicated because there are two JWT tokens :D. Company B's JWT => your verification => your JWT => authorized interactions with Supabase
j
Aah, think I got it. REALLY appreciate you rubber ducking this with me. I'll maybe ping you later on if I stumble across any other issues. Have a great day man!
l
No problem. Trying to explain something is the best way to learn it!
j
Yeah, exactly. Totally agree. Now I just need to figure out how I can implement this in my useUser-hook 😅 I started this project from this boilerplate: https://github.com/vercel/nextjs-subscription-payments/blob/main/utils/useUser.tsx
l
This is how looks like the JWT content sign by the Supabase for email + password method
Copy code
{
  "aud": "authenticated",
  "exp": 1641933478,
  "sub": "5f85a4b4-f8ec-4bee-8821-5f37f4448a1a",
  "email": "example@example.com",
  "phone": "",
  "app_metadata": {
    "provider": "email",
    "providers": [
      "email"
    ]
  },
  "user_metadata": {
    "name": "Lavka"
  },
  "role": "authenticated"
}
e
@User How did you get your name into the user_metadata. Do you need a custom gotrue implementation to edit this JWT? Is there a way to set the 'aud' value to something else in an easy manner? Thanks.