Skip to content

Commit

Permalink
app: fix invalid login errors (#706)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xBigBoss authored Sep 8, 2024
1 parent db55bf9 commit 740826e
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 13 deletions.
1 change: 1 addition & 0 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@wagmi/core": "^2.13.1",
"app": "workspace:*",
"debug": "^4.3.6",
"ms": "^2.1.3",
"p-queue": "^8.0.1",
"superjson": "^1.13.1",
"viem": "^2.18.2",
Expand Down
27 changes: 22 additions & 5 deletions packages/api/src/routers/account-recovery/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ import {
getPasskey,
isChallengeExpired,
} from 'app/utils/account-recovery'
import { mintAuthenticatedJWTToken } from 'app/utils/jwt'
import { mintAuthenticatedJWTToken, mintJWTToken } from 'app/utils/jwt'
import { verifyMessage, hexToBytes } from 'viem'
import { verifySignature } from 'app/utils/userop'
import { COSEECDHAtoXY } from 'app/utils/passkeys'
import { byteaToHex } from 'app/utils/byteaToHex'
import { supabaseAdmin } from 'app/utils/supabase/admin'
import ms from 'ms'

const logger = debug('api:routers:account-recovery')

Expand Down Expand Up @@ -119,11 +120,27 @@ export const accountRecoveryRouter = createTRPCRouter({
// identify user from identifier
const userId = await getUserIdByIdentifier(recoveryType, identifier)
const jwt = mintAuthenticatedJWTToken(userId)
const encodedJwt = encodeURIComponent(JSON.stringify([jwt, null, null, null, null, null]))
const expiresIn = ms('7d') / 1000
const options = {
expiresIn,
}
logger('minting new jwt', options)
const jwt = mintJWTToken('authenticated', 'authenticated', userId, options)
const encodedJwt = encodeURIComponent(
JSON.stringify([
jwt,
'not-used', // refresh token
null,
null,
null,
null,
])
)
console.log(`Account recovered - Recovery type: [${recoveryType}]. User: [${userId}].`)
ctx.res.setHeader('Set-Cookie', `sb-${SUPABASE_SUBDOMAIN}-auth-token=${encodedJwt}; Path=/`)
ctx.res.setHeader(
'Set-Cookie',
`sb-${SUPABASE_SUBDOMAIN}-auth-token=${encodedJwt}; Path=/; Max-Age=${expiresIn}; SameSite=Lax`
)
return {
jwt,
}
Expand Down
48 changes: 42 additions & 6 deletions packages/app/features/splash/screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
H1,
LinearGradient,
Paragraph,
Spinner,
Stack,
XStack,
YStack,
Expand All @@ -27,6 +28,8 @@ import { signChallenge } from 'app/utils/signChallenge'
import { useRouter } from 'solito/router'
import { bytesToHex, hexToBytes } from 'viem'
import { useAuthScreenParams } from 'app/routers/params'
import { useQuery } from '@tanstack/react-query'
import { assert } from 'app/utils/assert'

export function SplashScreen() {
return (
Expand Down Expand Up @@ -72,21 +75,21 @@ export function SplashScreen() {
icon={<IconEthereum size="$6" />}
backgroundColor="$blue10"
/>
<Section
title="DEFI INTEGRATION"
description="Access decentralized finance protocols directly"
icon={<Check color="white" size={60} />}
backgroundColor="$purple10"
/>
<Section
title="SECURE SMART CONTRACTS"
description="Leverage Ethereum's smart contract capabilities"
icon={<Check color="white" size={60} />}
backgroundColor="$green10"
/>
<Section
title="JOIN THE ETHEREUM ECOSYSTEM"
description="Be part of the future of finance"
Expand Down Expand Up @@ -254,14 +257,25 @@ function AuthButtons() {
const { mutateAsync: getChallengeMutateAsync } = api.challenge.getChallenge.useMutation({
retry: false,
})
const {
data: challengeData,
isLoading: isLoadingChallenge,
error: challengeError,
} = useQuery({
queryKey: ['challenge'],
queryFn: async () => await getChallengeMutateAsync(),
enabled: !!getChallengeMutateAsync,
})

const { mutateAsync: validateSignatureMutateAsync } = api.challenge.validateSignature.useMutation(
{ retry: false }
)

const handleSignIn = async () => {
setIsSigningIn(true)
try {
const challengeData = await getChallengeMutateAsync()
assert(!!challengeData, 'Challenge data is missing')
assert(!!challengeData.challenge, 'Challenge challenge is missing')

const rawIdsB64: { id: string; userHandle: string }[] = []
const { encodedWebAuthnSig, accountName, keySlot } = await signChallenge(
Expand Down Expand Up @@ -295,6 +309,16 @@ function AuthButtons() {

useEffect(() => () => toast.hide(), [toast])

useEffect(() => {
if (challengeError) {
toast.show(challengeError.message, {
preset: 'error',
isUrgent: true,
duration: 10000000,
})
}
}, [challengeError, toast])

return (
<XStack
gap={'$size.0.9'}
Expand All @@ -305,8 +329,20 @@ function AuthButtons() {
w="100%"
alignSelf="center"
>
<SubmitButton size="$4" w="$12" onPress={handleSignIn} disabled={isSigningIn}>
<ButtonText>{isSigningIn ? 'SIGNING IN...' : 'SIGN-IN'}</ButtonText>
<SubmitButton
size="$4"
w="$12"
onPress={handleSignIn}
disabled={isSigningIn || isLoadingChallenge || !!challengeError}
>
{(() => {
switch (true) {
case isLoadingChallenge:
return <Spinner size="small" color={'$color11'} />
default:
return <ButtonText>{isSigningIn ? 'SIGNING IN...' : 'SIGN-IN'}</ButtonText>
}
})()}
</SubmitButton>

<Button {...signUpLink} borderColor="$primary" variant="outlined" size="$4" w="$12">
Expand Down
4 changes: 4 additions & 0 deletions packages/app/provider/auth/AuthStateChangeHandler.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { useSupabase } from 'app/utils/supabase/useSupabase'
import { useEffect } from 'react'
import { useRouter } from 'solito/router'
import debugBase from 'debug'

const debug = debugBase('app:utils:useRedirectAfterSignOut')

const useRedirectAfterSignOut = () => {
const supabase = useSupabase()
const router = useRouter()
useEffect(() => {
const signOutListener = supabase.auth.onAuthStateChange((event) => {
if (event === 'SIGNED_OUT') {
debug('SIGNED_OUT')
router.replace('/')
}
})
Expand Down
2 changes: 2 additions & 0 deletions packages/app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
"baseUrl": ".",
"paths": {
"app/*": ["./*"],
"@my/api": ["../api/src"],
"@my/api/*": ["../api/src/*"],
"@my/ui": ["../ui/src"],
"@my/ui/*": ["../ui/src/*"],
"@my/wagmi": ["../wagmi/src"],
Expand Down
7 changes: 6 additions & 1 deletion packages/app/utils/jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ export const mintAuthenticatedJWTToken = (sub: string): string => {
return mintJWTToken('authenticated', 'authenticated', sub, options)
}

const mintJWTToken = (aud: string, role: string, sub: string, options?: SignOptions): string => {
export const mintJWTToken = (
aud: string,
role: string,
sub: string,
options?: SignOptions
): string => {
const payload = {
aud,
role,
Expand Down
3 changes: 2 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6230,6 +6230,7 @@ __metadata:
"@wagmi/core": "npm:^2.13.1"
app: "workspace:*"
debug: "npm:^4.3.6"
ms: "npm:^2.1.3"
p-queue: "npm:^8.0.1"
superjson: "npm:^1.13.1"
viem: "npm:^2.18.2"
Expand Down Expand Up @@ -26576,7 +26577,7 @@ __metadata:
languageName: node
linkType: hard

"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1":
"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.3":
version: 2.1.3
resolution: "ms@npm:2.1.3"
checksum: 10/aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d
Expand Down

0 comments on commit 740826e

Please sign in to comment.