Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace Auth #37

Merged
merged 24 commits into from
Jan 14, 2024
Merged

Replace Auth #37

merged 24 commits into from
Jan 14, 2024

Conversation

tmyracle
Copy link
Contributor

@tmyracle tmyracle commented Jan 12, 2024

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:

CleanShot.2024-01-12.at.12.02.23.mp4

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
/claim #16

@Shpigford
Copy link
Member

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

@@ -148,6 +149,7 @@ app.use('/tools', devOnly, toolsRouter)
app.use('/v1', webhooksRouter)

app.use('/v1', publicRouter)
app.use('/v1/auth-users', authUserRouter)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Need to figure out a better authorization pattern for this route / refactor checking for existing user by email and creating new users so those routes aren't open to the wild.

@McPizza0
Copy link

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

@Shpigford
Copy link
Member

@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.

@tmyracle
Copy link
Contributor Author

tmyracle commented Jan 13, 2024

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
Copy link
Contributor Author

tmyracle commented Jan 13, 2024

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.

@Shpigford
Copy link
Member

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.

Copy link

@gamedevsam gamedevsam left a comment

Choose a reason for hiding this comment

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

I think you need to look for uses of useAuth0Profile and replace or delete those. Great work though, this is very exciting!

apps/client/pages/_app.tsx Outdated Show resolved Hide resolved
apps/client/pages/api/auth/[...nextauth].ts Show resolved Hide resolved
apps/client/pages/login.tsx Outdated Show resolved Hide resolved
apps/client/pages/login.tsx Show resolved Hide resolved
apps/server/src/app/routes/auth-user.router.ts Outdated Show resolved Hide resolved
@@ -276,6 +286,7 @@ router.get(
})
)

// TODO: Remove this endpoint or refactor to work with new Auth

Choose a reason for hiding this comment

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

Are these comments relevant? I don't understand their purpose.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's purely for me to track things down as I continue working on this. I wanted to share a draft to get feedback on overall direction. They'll be removed as the changes are made.

const { useDelete } = useUserApi()

const deleteUser = useDelete({
onSuccess() {
toast.success(`Account deleted`)
setTimeout(() => logout({ logoutParams: { returnTo: window.location.origin } }), 500)
setTimeout(() => signOut(), 500)

Choose a reason for hiding this comment

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

Why is there a delay to log out here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good question, will dig deeper

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm guessing its to give time for the Toast to be displayed so the user has verification that the account was deleted prior to logging them out.

import { useEffect } from 'react'
import * as Sentry from '@sentry/react'
import { useSession } from 'next-auth/react'

export default function APM() {
Copy link
Contributor

Choose a reason for hiding this comment

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

What does APM stand for?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe its Application Performance Monitoring

@coman3
Copy link

coman3 commented Jan 13, 2024

@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.

@Shpigford
Copy link
Member

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

@PierreAndreis
Copy link

PierreAndreis commented Jan 13, 2024

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

@kkoppenhaver
Copy link

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

@tmyracle
Copy link
Contributor Author

tmyracle commented Jan 14, 2024

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.

@kkoppenhaver
Copy link

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
Copy link

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

🎉

@tmyracle
Copy link
Contributor Author

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Testing will be addressed in future PR, focusing on unblocking dev and getting app functional.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Testing will be addressed in future PR, focusing on unblocking dev and getting app functional.

@@ -59,6 +59,8 @@ export function AddFirstAccount({ title, onNext }: StepProps) {
loader={BrowserUtil.enhancerizerLoader}
src={`financial-institutions/white/${src}.svg`}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These assets are missing so they won't load during onboarding. @Shpigford do you have these or should we plan to replace them?

@tmyracle tmyracle marked this pull request as ready for review January 14, 2024 17:24
@tmyracle
Copy link
Contributor Author

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 tmyracle changed the title DRAFT: Replace Auth Replace Auth Jan 14, 2024
@Shpigford
Copy link
Member

@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 Shpigford added this to the v1.0.0 milestone Jan 14, 2024
@tmyracle
Copy link
Contributor Author

@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?

@Shpigford
Copy link
Member

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. 🎉

@coltonehrman
Copy link
Contributor

@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?

@tmyracle
Copy link
Contributor Author

@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.

@coltonehrman
Copy link
Contributor

Was able to run locally fine! :D LGTM 🎉

@Shpigford
Copy link
Member

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 Shpigford merged commit 4705620 into maybe-finance:main Jan 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.