-
Notifications
You must be signed in to change notification settings - Fork 1
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
ENG-0000 fix(portal,1ui): Fix Privy auth issues #939
Merged
Merged
Changes from 10 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
c9580df
Adds a second check to the logic in _index
jonathanprozzi 09c6f87
fix: Add refresh route and refactor auth guarding.
0xjojikun 16b2114
squash
0xjojikun a5606f9
Fix logout & redirect
0xjojikun 159e604
fix app route returning undefined
0xjojikun 7e8b934
Merge branch 'main' into joji/eng-0000-adjust-privy-token-logic
0xjojikun b9d11cf
Update apps/portal/app/.client/privy-refresh.tsx
0xjojikun 2474915
Update apps/portal/app/.client/privy-refresh.tsx
0xjojikun adaf6f3
Update apps/portal/app/.client/privy-refresh.tsx
0xjojikun 8ff2c05
Update apps/portal/app/.client/privy-refresh.tsx
0xjojikun 21c0c2e
lint fix
0xjojikun File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,61 @@ | ||
import { useEffect } from 'react' | ||
|
||
import { useCallback, useEffect, useState } from 'react' | ||
import logger from '@lib/utils/logger' | ||
import LoadingLogo from '@components/loading-logo' | ||
import { usePrivy } from '@privy-io/react-auth' | ||
import { useRevalidator } from '@remix-run/react' | ||
|
||
export default function PrivyRefresh() { | ||
export default function PrivyRefresh({ | ||
refreshPath, | ||
redirectTo, | ||
}: { | ||
refreshPath: string | ||
redirectTo: string | ||
}) { | ||
const { ready, getAccessToken } = usePrivy() | ||
const { revalidate } = useRevalidator() | ||
const [accessToken, setAccessToken] = useState<string | null>(null) | ||
|
||
useEffect(() => { | ||
async function refresh() { | ||
if (ready) { | ||
await getAccessToken() | ||
revalidate() | ||
const refresh = useCallback(async () => { | ||
try { | ||
if (!ready) { | ||
return | ||
} | ||
|
||
logger('Getting access token...') | ||
const idToken = await getAccessToken() | ||
logger('Access token:', idToken) | ||
setAccessToken(idToken) | ||
} catch (error) { | ||
console.error('Failed to refresh session:', error) | ||
} | ||
}, [ready]) | ||
|
||
useEffect(() => { | ||
refresh() | ||
}, [ready, revalidate]) | ||
}, [refresh]) | ||
useEffect(() => { | ||
if (accessToken) { | ||
// instead of revalidating, redirect to same route and replace true | ||
logger('Redirecting to', `${refreshPath}?redirectTo=${redirectTo}`) | ||
window.location.replace(`${refreshPath}?redirectTo=${redirectTo}`) | ||
} | ||
}, [accessToken]) | ||
|
||
return <div /> | ||
return ( | ||
<div className="fixed inset-0 flex items-center justify-center"> | ||
<div | ||
0xjojikun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
role="status" | ||
className="flex flex-col items-center gap-4" | ||
aria-label="Refreshing session" | ||
> | ||
<LoadingLogo size={50} /> | ||
<div className="flex flex-col items-center gap-1"> | ||
<p className="text-base text-foreground/70 font-medium"> | ||
Reconnecting your session... | ||
</p> | ||
<p className="text-sm text-muted-foreground"> | ||
This will only take a moment. | ||
</p> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,8 +9,8 @@ import { RedirectOptions } from 'app/types' | |
|
||
import { | ||
getPrivyAccessToken, | ||
getPrivyClient, | ||
getPrivySessionToken, | ||
getPrivyUserById, | ||
isOAuthInProgress, | ||
verifyPrivyAccessToken, | ||
} from './privy' | ||
|
@@ -21,13 +21,38 @@ export async function getUserId(request: Request): Promise<string | null> { | |
} | ||
|
||
export async function getUser(request: Request): Promise<User | null> { | ||
const userId = await getUserId(request) | ||
return userId ? await getPrivyUserById(userId) : null | ||
const privyIdToken = getPrivyAccessToken(request) | ||
const privyClient = getPrivyClient() | ||
|
||
if (!privyIdToken) { | ||
logger('No Privy ID token found') | ||
return null | ||
} | ||
|
||
try { | ||
// First verify the token is valid | ||
const verifiedClaims = await verifyPrivyAccessToken(request) | ||
if (!verifiedClaims) { | ||
logger('Invalid Privy token') | ||
return null | ||
} | ||
|
||
// Then get the full user object directly using the verified user ID | ||
const user = await privyClient.getUserById(verifiedClaims.userId) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! |
||
logger('Successfully fetched user by ID', user.wallet?.address) | ||
return user | ||
} catch (error) { | ||
logger('Error fetching user', error) | ||
return null | ||
} | ||
} | ||
|
||
export async function getUserWallet(request: Request): Promise<string | null> { | ||
const user = await getUser(request) | ||
return user?.wallet?.address ?? null | ||
if (!user) { | ||
return null | ||
} | ||
return user.wallet?.address ?? null | ||
} | ||
|
||
export async function requireUserId( | ||
|
@@ -99,15 +124,19 @@ export async function handlePrivyRedirect({ | |
const accessToken = getPrivyAccessToken(request) | ||
const sessionToken = getPrivySessionToken(request) | ||
const isOAuth = await isOAuthInProgress(request.url) | ||
|
||
if (isOAuth) { | ||
// Do not redirect or interrupt the flow. | ||
return | ||
} else if (!accessToken || !sessionToken) { | ||
return null | ||
} | ||
|
||
if (!accessToken || !sessionToken) { | ||
const redirectUrl = await getRedirectToUrl(request, path, options) | ||
throw redirect(redirectUrl) | ||
} | ||
logger('Hit end of handlePrivyRedirect', accessToken, sessionToken, isOAuth) | ||
return | ||
|
||
// Explicitly return null when we reach the end | ||
return null | ||
} | ||
|
||
export async function setupAPI(request: Request) { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import React from 'react' | ||
|
||
interface LoadingLogoProps { | ||
size?: number | ||
} | ||
|
||
const LoadingLogo: React.FC<LoadingLogoProps> = ({ size = 300 }) => { | ||
return ( | ||
<div className="animate-pulse-slow"> | ||
<svg | ||
width={size} | ||
height={size} | ||
viewBox="0 0 300 300" | ||
fill="none" | ||
xmlns="http://www.w3.org/2000/svg" | ||
className="animate-spin-slow" | ||
> | ||
<g> | ||
<path | ||
fillRule="evenodd" | ||
clipRule="evenodd" | ||
d="M160.133 0.342656C161.316 0.422794 162.196 1.46156 162.099 2.64387L161.591 8.82711C161.494 10.0094 160.457 10.8874 159.273 10.8086C139.849 9.51442 120.36 12.2998 102.063 18.995C83.0936 25.9362 65.8577 36.9143 51.5472 51.1704C37.2366 65.4264 26.1927 82.6202 19.179 101.563C12.4141 119.834 9.55422 139.312 10.7742 158.742C10.8485 159.926 9.96653 160.959 8.78386 161.052L2.59873 161.536C1.41605 161.629 0.380659 160.745 0.305042 159.561C-1.03277 138.616 2.03942 117.614 9.33229 97.9174C16.8739 77.5486 28.749 59.0606 44.1367 43.7316C59.5245 28.4025 78.0577 16.5981 98.4551 9.13438C118.18 1.91679 139.193 -1.07515 160.133 0.342656ZM239.534 32.3403C240.253 31.3963 240.071 30.0472 239.116 29.3424C219.597 14.9257 196.871 5.45943 172.889 1.75665C171.717 1.57563 170.631 2.3965 170.466 3.57137L169.608 9.71569C169.443 10.8906 170.263 11.9744 171.435 12.1567C193.634 15.6087 214.672 24.3715 232.757 37.6992C233.712 38.403 235.059 38.2215 235.777 37.2775L239.534 32.3403ZM282.833 219.68C282.282 220.731 280.976 221.117 279.934 220.551L274.481 217.59C273.439 217.024 273.054 215.721 273.604 214.67C288.233 186.71 292.96 154.593 286.973 123.567C280.985 92.5419 264.648 64.4899 240.665 43.9811C239.764 43.2101 239.636 41.8569 240.393 40.9436L244.352 36.167C245.109 35.2537 246.464 35.1262 247.367 35.8963C273.221 57.9579 290.834 88.1641 297.282 121.578C303.731 154.991 298.622 189.583 282.833 219.68ZM1.27663 169.528C1.12219 168.352 1.96743 167.285 3.14571 167.148L9.30789 166.428C10.4862 166.29 11.5512 167.134 11.7069 168.31C14.0852 186.273 19.9402 203.6 28.9445 219.324C29.534 220.353 29.1992 221.67 28.1789 222.276L22.8433 225.441C21.8231 226.047 20.5039 225.711 19.9132 224.682C10.1588 207.691 3.82726 188.953 1.27663 169.528ZM232.933 272.402C233.598 273.384 233.342 274.721 232.351 275.373C216.191 285.987 198.125 293.381 179.146 297.141C159.465 301.039 139.201 300.95 119.555 296.878C99.9087 292.805 81.279 284.833 64.7687 273.433C48.8478 262.439 35.2097 248.473 24.6004 232.31C23.9495 231.318 24.2461 229.99 25.247 229.353L30.4818 226.023C31.4828 225.387 32.809 225.683 33.461 226.674C43.3158 241.653 55.9698 254.597 70.7349 264.792C86.0895 275.395 103.415 282.809 121.686 286.596C139.957 290.383 158.802 290.467 177.106 286.841C194.707 283.354 211.464 276.506 226.461 266.679C227.453 266.029 228.787 266.284 229.453 267.266L232.933 272.402ZM277.015 229.794C277.646 228.789 277.323 227.467 276.31 226.85L271.01 223.626C269.996 223.009 268.676 223.332 268.044 224.336C259.058 238.605 247.559 251.128 234.105 261.295C233.159 262.01 232.949 263.353 233.65 264.31L237.314 269.317C238.014 270.274 239.359 270.484 240.306 269.769C254.871 258.787 267.311 245.24 277.015 229.794ZM257.757 150C257.757 209.512 209.512 257.757 150 257.757C90.4879 257.757 42.2437 209.512 42.2437 150C42.2437 90.4879 90.4879 42.2437 150 42.2437C209.512 42.2437 257.757 90.4879 257.757 150ZM280.668 150C280.668 222.166 222.166 280.668 150 280.668C77.8342 280.668 19.332 222.166 19.332 150C19.332 77.8342 77.8342 19.332 150 19.332C222.166 19.332 280.668 77.8342 280.668 150Z" | ||
className="fill-foreground/50 " | ||
/> | ||
</g> | ||
</svg> | ||
</div> | ||
) | ||
} | ||
|
||
export default LoadingLogo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { useEffect, useState } from 'react' | ||
|
||
const usePageVisibility = () => { | ||
const [isVisible, setIsVisible] = useState(!document.hidden) | ||
|
||
useEffect(() => { | ||
const handleVisibilityChange = () => { | ||
setIsVisible(!document.hidden) | ||
} | ||
|
||
// Add event listener | ||
document.addEventListener('visibilitychange', handleVisibilityChange) | ||
|
||
// Cleanup | ||
return () => { | ||
document.removeEventListener('visibilitychange', handleVisibilityChange) | ||
} | ||
}, []) | ||
|
||
return isVisible | ||
} | ||
|
||
export default usePageVisibility |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this would force the logout to ensure it's cleared fully before logging in?