mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-09 07:25:19 +02:00
continue cleaning up and removing Auth0
This commit is contained in:
parent
5f3ebb14f3
commit
f94eb5b242
10 changed files with 10 additions and 100 deletions
|
@ -50,8 +50,6 @@ const WithAuth = function ({ children }: PropsWithChildren) {
|
||||||
<UserAccountContextProvider>
|
<UserAccountContextProvider>
|
||||||
<AccountContextProvider>
|
<AccountContextProvider>
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
{/* Add, edit, delete connections and manual accounts */}
|
|
||||||
<AccountsManager />
|
<AccountsManager />
|
||||||
</AccountContextProvider>
|
</AccountContextProvider>
|
||||||
</UserAccountContextProvider>
|
</UserAccountContextProvider>
|
||||||
|
|
|
@ -104,7 +104,9 @@ export const authOptions = {
|
||||||
const existingUser = await getAuthUserByEmail(email)
|
const existingUser = await getAuthUserByEmail(email)
|
||||||
if (existingUser) {
|
if (existingUser) {
|
||||||
const isPasswordMatch = await bcrypt.compare(password, existingUser.password!)
|
const isPasswordMatch = await bcrypt.compare(password, existingUser.password!)
|
||||||
if (!isPasswordMatch) throw new Error('Email or password is invalid.')
|
if (!isPasswordMatch) {
|
||||||
|
throw new Error('Email or password is invalid.')
|
||||||
|
}
|
||||||
|
|
||||||
return existingUser
|
return existingUser
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,9 @@ export default function LoginPage() {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (session) router.push('/')
|
if (session) {
|
||||||
|
router.push('/')
|
||||||
|
}
|
||||||
}, [session, router])
|
}, [session, router])
|
||||||
|
|
||||||
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
@ -36,7 +38,6 @@ export default function LoginPage() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// _app.tsx will automatically redirect if not authenticated
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Script
|
<Script
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
import { Router } from 'express'
|
|
||||||
|
|
||||||
// Placeholder router if needed
|
|
||||||
const router = Router()
|
|
||||||
|
|
||||||
export default router
|
|
|
@ -2,7 +2,6 @@ export { default as accountsRouter } from './accounts.router'
|
||||||
export { default as accountRollupRouter } from './account-rollup.router'
|
export { default as accountRollupRouter } from './account-rollup.router'
|
||||||
export { default as connectionsRouter } from './connections.router'
|
export { default as connectionsRouter } from './connections.router'
|
||||||
export { default as usersRouter } from './users.router'
|
export { default as usersRouter } from './users.router'
|
||||||
export { default as authUserRouter } from './auth-user.router'
|
|
||||||
export { default as webhooksRouter } from './webhooks.router'
|
export { default as webhooksRouter } from './webhooks.router'
|
||||||
export { default as plaidRouter } from './plaid.router'
|
export { default as plaidRouter } from './plaid.router'
|
||||||
export { default as finicityRouter } from './finicity.router'
|
export { default as finicityRouter } from './finicity.router'
|
||||||
|
|
|
@ -5,12 +5,10 @@ import classNames from 'classnames'
|
||||||
import { AiOutlineLoading3Quarters as LoadingIcon } from 'react-icons/ai'
|
import { AiOutlineLoading3Quarters as LoadingIcon } from 'react-icons/ai'
|
||||||
import {
|
import {
|
||||||
RiAnticlockwise2Line,
|
RiAnticlockwise2Line,
|
||||||
RiAppleFill,
|
|
||||||
RiArrowGoBackFill,
|
RiArrowGoBackFill,
|
||||||
RiDownloadLine,
|
RiDownloadLine,
|
||||||
RiShareForwardLine,
|
RiShareForwardLine,
|
||||||
} from 'react-icons/ri'
|
} from 'react-icons/ri'
|
||||||
import { UserIdentityList } from '../user-details/UserIdentityList'
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
DatePicker,
|
DatePicker,
|
||||||
|
@ -30,9 +28,8 @@ import { DeleteUserButton } from './DeleteUserButton'
|
||||||
import { DateTime } from 'luxon'
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
export function UserDetails() {
|
export function UserDetails() {
|
||||||
const { useProfile, useAuth0Profile, useUpdateProfile } = useUserApi()
|
const { useProfile, useUpdateProfile } = useUserApi()
|
||||||
|
|
||||||
const auth0ProfileQuery = useAuth0Profile()
|
|
||||||
const updateProfileQuery = useUpdateProfile()
|
const updateProfileQuery = useUpdateProfile()
|
||||||
|
|
||||||
const profileQuery = useProfile()
|
const profileQuery = useProfile()
|
||||||
|
@ -76,17 +73,7 @@ export function UserDetails() {
|
||||||
type="text"
|
type="text"
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
{auth0ProfileQuery.data?.primaryIdentity.provider === 'apple' && (
|
|
||||||
<div className="flex items-center gap-x-1 mt-2 text-gray-100">
|
|
||||||
<span className="text-sm">Apple identity</span>
|
|
||||||
<RiAppleFill className="w-3 h-3" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{auth0ProfileQuery.data && (
|
|
||||||
<UserIdentityList profile={auth0ProfileQuery.data} />
|
|
||||||
)}
|
|
||||||
</LoadingPlaceholder>
|
</LoadingPlaceholder>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useAuth0 } from '@auth0/auth0-react'
|
import { useSession } from 'next-auth/react'
|
||||||
import { Button, Dialog } from '@maybe-finance/design-system'
|
import { Button, Dialog } from '@maybe-finance/design-system'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
@ -12,7 +12,7 @@ export interface FeedbackDialogProps {
|
||||||
|
|
||||||
export function FeedbackDialog({ isOpen, onClose, notImplementedNotice }: FeedbackDialogProps) {
|
export function FeedbackDialog({ isOpen, onClose, notImplementedNotice }: FeedbackDialogProps) {
|
||||||
const [feedback, setFeedback] = useState('')
|
const [feedback, setFeedback] = useState('')
|
||||||
const { user } = useAuth0()
|
const { data: session } = useSession()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog isOpen={isOpen} onClose={onClose}>
|
<Dialog isOpen={isOpen} onClose={onClose}>
|
||||||
|
@ -42,7 +42,7 @@ export function FeedbackDialog({ isOpen, onClose, notImplementedNotice }: Feedba
|
||||||
await axios
|
await axios
|
||||||
.create({ transformRequest: [(data) => JSON.stringify(data)] })
|
.create({ transformRequest: [(data) => JSON.stringify(data)] })
|
||||||
.post('https://hooks.zapier.com/hooks/catch/10143005/buyo6na/', {
|
.post('https://hooks.zapier.com/hooks/catch/10143005/buyo6na/', {
|
||||||
comment: `**From user:** ${user?.sub}\n\n${feedback}`,
|
comment: `**From user:** ${session?.user?.email}\n\n${feedback}`,
|
||||||
page: `**Main app feedback**: ${window.location.href}`,
|
page: `**Main app feedback**: ${window.location.href}`,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
import type { Auth0ContextInterface } from '@auth0/auth0-react'
|
|
||||||
import { createContext } from 'react'
|
|
||||||
import type { PropsWithChildren } from 'react'
|
|
||||||
import { Auth0Provider, type Auth0ProviderOptions } from '@auth0/auth0-react'
|
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
|
|
||||||
export const linkAuth0AccountCtx = createContext<Auth0ContextInterface | null>(
|
|
||||||
null
|
|
||||||
) as Auth0ProviderOptions['context']
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Auth0 Context Provider
|
|
||||||
*
|
|
||||||
* Why 2 configs?
|
|
||||||
*
|
|
||||||
* For user account linking, we need two contexts so that when the secondary
|
|
||||||
* user is authenticated prior to linking, it doesn't log the primary user out.
|
|
||||||
*
|
|
||||||
* @see https://github.com/auth0/auth0-react/issues/425#issuecomment-1303619555
|
|
||||||
*/
|
|
||||||
export function AuthProvider({ children }: PropsWithChildren) {
|
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
const sharedConfig: Auth0ProviderOptions = {
|
|
||||||
domain: process.env.NEXT_PUBLIC_AUTH0_DOMAIN || 'REPLACE_THIS',
|
|
||||||
clientId: process.env.NEXT_PUBLIC_AUTH0_CLIENT_ID || 'REPLACE_THIS',
|
|
||||||
onRedirectCallback: (appState) => router.replace(appState?.returnTo || '/'),
|
|
||||||
authorizationParams: {
|
|
||||||
audience: process.env.NEXT_PUBLIC_AUTH0_AUDIENCE || 'https://maybe-finance-api/v1',
|
|
||||||
screen_hint: router.pathname === '/register' ? 'signup' : 'login',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const isBrowser = typeof window !== 'undefined'
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Auth0Provider
|
|
||||||
{...sharedConfig}
|
|
||||||
useRefreshTokens // https://auth0.com/docs/security/tokens/refresh-tokens/configure-refresh-token-rotation
|
|
||||||
cacheLocation="localstorage"
|
|
||||||
authorizationParams={{
|
|
||||||
...sharedConfig.authorizationParams,
|
|
||||||
redirect_uri: isBrowser ? `${window.location.origin}?primary` : undefined,
|
|
||||||
}}
|
|
||||||
skipRedirectCallback={
|
|
||||||
isBrowser ? window.location.href.includes('?secondary') : undefined
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Auth0Provider
|
|
||||||
{...sharedConfig}
|
|
||||||
authorizationParams={{
|
|
||||||
...sharedConfig.authorizationParams,
|
|
||||||
redirect_uri: isBrowser ? `${window.location.origin}?secondary` : undefined,
|
|
||||||
}}
|
|
||||||
skipRedirectCallback={
|
|
||||||
isBrowser ? window.location.href.includes('?primary') : undefined
|
|
||||||
}
|
|
||||||
context={linkAuth0AccountCtx}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Auth0Provider>
|
|
||||||
</Auth0Provider>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -67,13 +67,7 @@ function createInstance(options?: CreateInstanceOptions) {
|
||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Injects the Auth0 access token into every axios request
|
|
||||||
*
|
|
||||||
* @see https://github.com/auth0/auth0-react/issues/266#issuecomment-919222402
|
|
||||||
*/
|
|
||||||
export function AxiosProvider({ children }: PropsWithChildren) {
|
export function AxiosProvider({ children }: PropsWithChildren) {
|
||||||
// Rather than storing access token in localStorage (insecure), we use this method to retrieve it prior to making API calls
|
|
||||||
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3333'
|
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3333'
|
||||||
|
|
||||||
// Expose a default instance with auth, superjson, headers
|
// Expose a default instance with auth, superjson, headers
|
||||||
|
|
|
@ -5,4 +5,3 @@ export * from './QueryProvider'
|
||||||
export * from './AccountContextProvider'
|
export * from './AccountContextProvider'
|
||||||
export * from './UserAccountContextProvider'
|
export * from './UserAccountContextProvider'
|
||||||
export * from './PopoutProvider'
|
export * from './PopoutProvider'
|
||||||
export * from './AuthProvider'
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue