Skip to content

Conversation

@ebma
Copy link
Member

@ebma ebma commented Oct 31, 2025

Closes #882.

This pull request introduces Supabase-based authentication to the API, including OTP (one-time password) flows, token verification, and user session management. It adds new authentication endpoints, middleware for extracting and verifying user identity from requests, and propagates the authenticated userId throughout the business logic and data models. Several routes now optionally or mandatorily require authentication, and the system is prepared for future endpoint protection. Additionally, the codebase is updated to store and utilize the userId in key models and service layers.

Supabase Authentication Integration

  • Added Supabase configuration variables to .env.example and included @supabase/supabase-js as a dependency in package.json. [1] [2]
  • Implemented SupabaseAuthService with methods for checking user existence, sending and verifying OTPs, verifying and refreshing tokens, and retrieving user profiles. [1] [2]
  • Created AuthController with endpoints for checking email registration, requesting OTP, verifying OTP, refreshing tokens, and verifying tokens. [1] [2]
  • Added /v1/auth routes for authentication endpoints and registered them in the main API router. [1] [2] [3]

Authentication Middleware and Route Protection

  • Added requireAuth and optionalAuth middleware to extract and verify user identity from Bearer tokens, attaching userId to the request.
  • Updated BRLA, Quote, and Ramp routes to use optionalAuth middleware, allowing endpoints to access userId if provided. [1] [2] [3] [4] [5] [6] [7]

User Identity Propagation

  • Modified controllers (brla.controller.ts, quote.controller.ts, ramp.controller.ts) to store userId from the request in database records and service calls. [1] [2] [3] [4] [5] [6]
  • Updated service and type definitions to support userId as part of the request context and data models. [1] [2]

These changes collectively enable secure, user-specific flows across the API, laying the groundwork for robust authentication and authorization using Supabase.

@netlify
Copy link

netlify bot commented Oct 31, 2025

Deploy Preview for vortexfi ready!

Name Link
🔨 Latest commit e5480d0
🔍 Latest deploy log https://app.netlify.com/projects/vortexfi/deploys/69669cbe484c9000080d2cb1
😎 Deploy Preview https://deploy-preview-912--vortexfi.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Oct 31, 2025

Deploy Preview for vortex-sandbox ready!

Name Link
🔨 Latest commit e5480d0
🔍 Latest deploy log https://app.netlify.com/projects/vortex-sandbox/deploys/69669cbe237da30008ec4ce0
😎 Deploy Preview https://deploy-preview-912--vortex-sandbox.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@ebma ebma requested a review from a team December 16, 2025 08:06
});
}

await SupabaseAuthService.sendOTP(email);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this operation is stateless on the backend, right? Maybe we could add an entry to the users table, to mark the last OTP timestamp or any other metadata.

In case we loose the state in the UI or we want to keep track.

// Sync user to local database (upsert)
await User.upsert({
email: email,
id: result.user_id
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the upsert only for handling new users? I assume the userId should never change but I may be wrong.

Copy link
Contributor

@gianfra-t gianfra-t left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice and complete feature, thanks @ebma ! The only thing I would like to discuss is what you think about changing the token into the cookies and avoid storing it in the local storage.
I understand there is a tradeoff in terms of security between both methods.

}),
({ event, context }) => {
// Store tokens in localStorage for session persistence
AuthService.storeTokens({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also wanted to discuss the pros/cons of using localStorage vs cookies (httpOnly) for the tokens.

I believe our application already handles httpOnly cookiens for the SIWE login, so we have an example, which seems to be the preferred way for browser apps.

Do you see this solution better in terms of security, for our case?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have a fair point, thanks for raising this. I think for the time being, the localStorage approach is fine and not that big of a risk. Doing this with cookies seems to be more cumbersome and also restricts in the future if we ever decide to make the Vortex widget embeddable. Not sure when or if that's ever gonna happen but I'm a little scared of changing this now, introducing extra complexity just making our developer experience worse. If you have strong opinions on this, I would be open to consider it though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't think about the possibility of embedding the site, sure.

Let's then check if there is anything we can add to mitigate those risks? With this local storage solution.

But I'm fine if we do it later.

type: DataTypes.UUID
});

await queryInterface.sequelize.query(`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep the userId relation for this one (and any that allows for null) empty instead of using the dummy? Or do you think there is a benefit of using the dummy user here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, well maybe we should just allow it to be null on each table. You are right that the dummy user is not great. I used it so we can enforce the non-null constraint that is logical on some of the tables but now that I think of it, it might be better if it can be null and we just add it later..

Copy link
Contributor

@gianfra-t gianfra-t Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I dont have a strong opinion on either as they both serve the same purpose. null seems a bit easier to deal with after than the dummy.

Oh but if I remember correctly, those fields allow for a null relationship so no need to change that constraint itself.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe to also make the migration easier to follow. Not much more

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of them did, some didn't. But I adjusted it so that the userId is nullable on all the other relations and the code checks if necessary.

@Sharqiewicz
Copy link
Member

@ebma Please let me know when it's ready for review again 🙏

@ebma ebma requested review from Sharqiewicz and gianfra-t January 13, 2026 19:28
@ebma
Copy link
Member Author

ebma commented Jan 13, 2026

@Sharqiewicz I consider the changes ready now :)

@Sharqiewicz
Copy link
Member

@ebma Ok, thanks. I'll review it today

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Account creation on Vortex

4 participants