maybe icon indicating copy to clipboard operation
maybe copied to clipboard

DRAFT: Replace Auth

Open tmyracle opened this issue 1 year ago • 9 comments

I wanted to provide a draft PR on this to make sure everyone is aligned with the path I'm going down here. Comments, feedback, recommendations all greatly appreciated. This is a big change!

but first, here's a demo showing registration, sign out, and signing back in:

https://github.com/maybe-finance/maybe/assets/1218724/85103c7a-10f2-491d-a1a6-3854f150048c

A lot going on here, here's a quick breakdown:

  • Add NextAuth/AuthJS
  • Implement email/password register/auth (figured its easiest for self host, can add more providers later)
  • Add routes and services for finding existing user by email, creating user
  • Add Register and Sign In pages, took best stab at styling using design library (if you have mocks from back in the day I'm happy to match previous styles)
  • The newly added Auth models are all prefixed with "Auth" to prevent collisions with existing User and Account models
  • Add authId to User model
  • Update _app.tsx logic to check for session and redirect to sign in if user doesn't have session

TO-DO:

  • Update JWT to match fields that were populated by Auth0
  • ~~Update middleware and JWT checks~~
  • ~~Create User and associate with AuthUser~~
  • ~~Figure out how to kick off onboarding for new users~~
  • Continue replacing Auth0 functionality with NextAuth
  • ??? Probably a lot more that we'll find as we continue fixing things.

Hopefully this is some decent progress on #16

tmyracle avatar Jan 12 '24 18:01 tmyracle

Amazing. Thanks for the first pass on this, @tmyracle!

Shpigford avatar Jan 12 '24 18:01 Shpigford

Nice work @tmyracle !

credentials provider is discouraged, see https://authjs.dev/getting-started/providers/credentials-tutorial

@Shpigford do you specifically want user/pass logins or would you consider some oAuth options as well? considering the purpose of this app, I think a more secure method would be suitable theres an open PR for native passkey support, I have it running and can help with implementation if you want to go that way

McPizza0 avatar Jan 12 '24 20:01 McPizza0

@Shpigford do you specifically want user/pass logins or would you consider some oAuth options as well?

User/email + pass should be the entry point and then in the future we can add other providers if there's demand. No reason to google/apple/facebook/etc at this stage.

Shpigford avatar Jan 12 '24 22:01 Shpigford

Made a little more progress I think? I can at least access some of the app. Had to rework things to place nice with Express since NextAuth expects just a Next.js environment, hence the cookie parsing in the middleware check. Now when registering it is creating the User object in the database automatically and associating it with the AuthUser object that is owned by NextAuth.

CleanShot 2024-01-12 at 18 35 51 CleanShot 2024-01-12 at 18 35 59 CleanShot 2024-01-12 at 18 49 44

tmyracle avatar Jan 13 '24 00:01 tmyracle

Onboarding is back, also fixed a few react warnings/bugs. Video here: https://github.com/maybe-finance/maybe/assets/1218724/b5b0db6b-ced7-48c4-95c5-13e11a553f16

Looks like Auth0 took care of sending email verification so I'll need to go in and create an email and related services to handle sending the email verification and handling updating when user clicks the link in the email. For now I just added a flag to skip adding the email verification step to onboarding.

Next going to remove all use of the Auth0 libraries, server endpoints, and anything else that might be calling Auth0.

tmyracle avatar Jan 13 '24 05:01 tmyracle

Looks like Auth0 took care of sending email verification so I'll need to go in and create an email and related services to handle sending the email verification and handling updating when user clicks the link in the email. For now I just added a flag to skip adding the email verification step to onboarding.

@tmyracle I agree with this move. Let's keep the flag to skip email verification and then we'll address email sending and email verification in a future issue.

Shpigford avatar Jan 13 '24 15:01 Shpigford

@Shpigford do you specifically want user/pass logins or would you consider some oAuth options as well?

User/email + pass should be the entry point and then in the future we can add other providers if there's demand. No reason to google/apple/facebook/etc at this stage.

Part of me would suggest to at least enable google and Microsoft (personal + 365) login support as a lot of home lab users use these services to secure their self-hosted stuff, myself included.

Enabling support for OpenID connect workflows would be enough to make this flexible for everyone and I think this is a must have for a self-hosted app.

coman3 avatar Jan 13 '24 20:01 coman3

@coman3 i 100% planning on supporting it, but it's just outside the scope/purpose of this issue/PR.

Shpigford avatar Jan 13 '24 20:01 Shpigford

AuthJS is very flexible, once in place it can support any provider with a few lines in. Let the man do the ground work and later come and introduce google sign in if you want

PierreAndreis avatar Jan 13 '24 21:01 PierreAndreis

This looks awesome! Thanks for all the work on this, y'all.

When I try to run this locally, I get the following error, which makes me think my API service isn't running somehow? Anyone seen this/have an idea how to resolve?

useUserApi.ts:55 
GET http://localhost:3333/v1/users/onboarding/main net::ERR_CONNECTION_REFUSED

kkoppenhaver avatar Jan 14 '24 06:01 kkoppenhaver

This looks awesome! Thanks for all the work on this, y'all.

When I try to run this locally, I get the following error, which makes me think my API service isn't running somehow? Anyone seen this/have an idea how to resolve?


useUserApi.ts:55 

GET http://localhost:3333/v1/users/onboarding/main net::ERR_CONNECTION_REFUSED

Hmm yeah looks like server might not be running. See anything in the console logs? Can also hit localhost:3333/health and check if you get an ok message back to make sure it's running.

tmyracle avatar Jan 14 '24 07:01 tmyracle

Looks like it's just refusing to connect all together (see screenshot).

Screenshot 2024-01-14 at 1 13 24 AM

When I boot it up, I get

error: uncaughtException: Must provide a clientSecret
ArgumentError: Must provide a clientSecret

So I'm thinking maybe that's it? But that would make it seem like it's still looking at Auth0 for that secret...

kkoppenhaver avatar Jan 14 '24 07:01 kkoppenhaver

I was able to get this working. I just needed NX_AUTH0_MGMT_CLIENT_SECRET and NX_AUTH0_CLIENT_SECRET to have a value. And then NX_SESSION_SECRET and NEXTAUTH_SECRET needed to be filled out.

Screenshot 2024-01-14 at 1 44 27 AM

🎉

kkoppenhaver avatar Jan 14 '24 07:01 kkoppenhaver

Ok did a bunch of cleanup, should be pretty close to move to ready for review. I decided to remove the admin router for now, I'll leave it up to @Shpigford if he wants to remove the admin functionality or re-write it to work without Auth0 which would involve re-working the roles framework and refactoring how roles are assigned since those are currently owned by the Auth0 pages and sign up flow.

Things out of scope for now, but should be addressed in next PR since this is already massive:

  • Update all of the tests, they won't run now since there's a lot of Auth0 mocking
  • Use Postmark to add email validation since this was taken care of by Auth0 previously (if we want this added back)
  • Revisit admin functionality depending on whether it's a necessary feature for OSS version

Depending on decisions here we can spin up some new issues for folks to tackle some of these items.

tmyracle avatar Jan 14 '24 17:01 tmyracle

Gonna go ahead and make this ready for review @Shpigford. The focus is getting an initial auth replacement implemented and pull out Auth0 and things that depend on it so that we can unblock development for other folks that want to contribute. This effort isn't complete, but I feel like its a good stopping point that achieves the goal stated above and can be built upon with future changes.

Future PRs will address:

  • Updating tests and add additional tests for NextAuth/Auth.js for coverage
  • Adding in email verification using Postmark (Auth0 handled this previously)
  • Add forgot password flow with Postmark as email provider (might look at abstracting this so people can use whatever email provider they want)
  • Remove remaining auth0 dependencies in package.json
  • Implementing roles (if that's something that is necessary for the open source version of this)

Issues for those changes will be added once this is reviewed and merged 🚀

tmyracle avatar Jan 14 '24 17:01 tmyracle

@tmyracle really great work! after registration, I'm getting an "Unable to load onboarding" error and this in the console:

Error in token validation JWEDecryptionFailed: decryption operation failed
    at gcmDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/runtime/decrypt.js:67:15)
    at decrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/runtime/decrypt.js:92:20)
    at flattenedDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/jwe/flattened/decrypt.js:143:52)
    at compactDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/jwe/compact/decrypt.js:18:23)
    at jwtDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/jwt/decrypt.js:8:23)
    at decode (/Users/joshpigford/Development/maybe/node_modules/next-auth/jwt/index.js:66:7) {
  code: 'ERR_JWE_DECRYPTION_FAILED'
}

Shpigford avatar Jan 14 '24 18:01 Shpigford

@tmyracle really great work! after registration, I'm getting an "Unable to load onboarding" error and this in the console:

Error in token validation JWEDecryptionFailed: decryption operation failed
    at gcmDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/runtime/decrypt.js:67:15)
    at decrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/runtime/decrypt.js:92:20)
    at flattenedDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/jwe/flattened/decrypt.js:143:52)
    at compactDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/jwe/compact/decrypt.js:18:23)
    at jwtDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/jwt/decrypt.js:8:23)
    at decode (/Users/joshpigford/Development/maybe/node_modules/next-auth/jwt/index.js:66:7) {
  code: 'ERR_JWE_DECRYPTION_FAILED'
}

Hmm, I'm assuming you have NEXTAUTH_SECRET populated in your .env?

tmyracle avatar Jan 14 '24 18:01 tmyracle

Hmm, I'm assuming you have NEXTAUTH_SECRET populated in your .env?

@tmyracle Doh. Totally missed needing to do that! I'm set. Works great. 🎉

Shpigford avatar Jan 14 '24 18:01 Shpigford

@tmyracle really great work! after registration, I'm getting an "Unable to load onboarding" error and this in the console:

Error in token validation JWEDecryptionFailed: decryption operation failed
    at gcmDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/runtime/decrypt.js:67:15)
    at decrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/runtime/decrypt.js:92:20)
    at flattenedDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/jwe/flattened/decrypt.js:143:52)
    at compactDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/jwe/compact/decrypt.js:18:23)
    at jwtDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/jwt/decrypt.js:8:23)
    at decode (/Users/joshpigford/Development/maybe/node_modules/next-auth/jwt/index.js:66:7) {
  code: 'ERR_JWE_DECRYPTION_FAILED'
}

Hmm, I'm assuming you have NEXTAUTH_SECRET populated in your .env?

Maybe we could include a basic secret as part of the example instead of leaving it empty?

coltonehrman avatar Jan 14 '24 18:01 coltonehrman

@tmyracle really great work! after registration, I'm getting an "Unable to load onboarding" error and this in the console:

Error in token validation JWEDecryptionFailed: decryption operation failed
    at gcmDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/runtime/decrypt.js:67:15)
    at decrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/runtime/decrypt.js:92:20)
    at flattenedDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/jwe/flattened/decrypt.js:143:52)
    at compactDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/jwe/compact/decrypt.js:18:23)
    at jwtDecrypt (/Users/joshpigford/Development/maybe/node_modules/jose/dist/node/cjs/jwt/decrypt.js:8:23)
    at decode (/Users/joshpigford/Development/maybe/node_modules/next-auth/jwt/index.js:66:7) {
  code: 'ERR_JWE_DECRYPTION_FAILED'
}

Hmm, I'm assuming you have NEXTAUTH_SECRET populated in your .env?

Maybe we could include a basic secret as part of the example instead of leaving it empty?

Updated the README to add instructions for populating prior to install and run. I don't like leaving placeholder secrets because it's easy for people to not change them and introduce vulnerabilities.

tmyracle avatar Jan 14 '24 18:01 tmyracle

Was able to run locally fine! :D LGTM 🎉

coltonehrman avatar Jan 14 '24 18:01 coltonehrman

Alrighty, so 3 folks confirmed running it with the new auth. I'm gonna call it. YOLO, etc etc.

AMAZING job on this @tmyracle!

Shpigford avatar Jan 14 '24 18:01 Shpigford