Skip to content

Commit fc549de

Browse files
authored
reverting old callback (#281)
* reverting old callback * to more recent version
1 parent 6e43b6a commit fc549de

File tree

2 files changed

+139
-21
lines changed

2 files changed

+139
-21
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use client'
2+
3+
import {useSearchParams} from 'next/navigation'
4+
import {useEffect} from 'react'
5+
import {FullScreenCenter} from '@/components/FullScreenCenter'
6+
7+
/**
8+
* Workaround for searchParams being empty on production. Will ahve to check
9+
* @see https://github.com/vercel/next.js/issues/43077#issuecomment-1383742153
10+
*/
11+
export const dynamic = 'force-dynamic'
12+
13+
/** https://beta.nextjs.org/docs/api-reference/file-conventions/page#searchparams-optional */
14+
export default function OAuthCallback() {
15+
const searchParams = useSearchParams()
16+
const code = searchParams.get('code')
17+
const state = searchParams.get('state')
18+
19+
useEffect(() => {
20+
if (
21+
code &&
22+
state &&
23+
Buffer.from(state, 'base64').toString('utf8').startsWith('conn_')
24+
) {
25+
// Just close the window - parent that opens this in a popup after redirect will read params directly
26+
window.close()
27+
}
28+
}, [code, state])
29+
30+
return (
31+
<FullScreenCenter>
32+
<span className="mb-2">Processing authentication...</span>
33+
</FullScreenCenter>
34+
)
35+
}
Lines changed: 104 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,118 @@
1-
'use client'
2-
3-
import {useSearchParams} from 'next/navigation'
4-
import {useEffect} from 'react'
1+
import '@openint/app-config/register.node'
2+
import {cookies} from 'next/headers'
3+
import {redirect} from 'next/navigation'
4+
import {kAccessToken} from '@openint/app-config/constants'
5+
import {envRequired} from '@openint/app-config/env'
6+
import type {Id} from '@openint/cdk'
7+
import {initNangoSDK, NangoConnect} from '@openint/cdk'
8+
import type {FrameMessage} from '@openint/connect'
59
import {FullScreenCenter} from '@/components/FullScreenCenter'
10+
import {serverSideHelpersFromViewer} from '@/lib-server'
11+
import {serverComponentGetViewer} from '@/lib-server/server-component-helpers'
12+
import {kConnectSession, zConnectSession} from '../../shared'
13+
import {CallbackEffect} from './CallbackEffect'
14+
15+
export const metadata = {
16+
title: 'OpenInt Oauth Callback',
17+
}
618

719
/**
820
* Workaround for searchParams being empty on production. Will ahve to check
9-
* @see https://github.com/vercel/next.js/issues/43077#issuecomment-1383742153
10-
*/
21+
@@ -23,104 +11,25 @@ export const metadata = {
1122
export const dynamic = 'force-dynamic'
1223
1324
/** https://beta.nextjs.org/docs/api-reference/file-conventions/page#searchparams-optional */
14-
export default function OAuthCallback() {
15-
const searchParams = useSearchParams()
16-
const code = searchParams.get('code')
17-
const state = searchParams.get('state')
18-
19-
useEffect(() => {
20-
if (
21-
code &&
22-
state &&
23-
Buffer.from(state, 'base64').toString('utf8').startsWith('conn_')
24-
) {
25-
// Just close the window - parent that opens this in a popup after redirect will read params directly
26-
window.close()
25+
export default async function ConnectCallback({
26+
searchParams,
27+
}: {
28+
// Only accessible in PageComponent rather than layout component
29+
// @see https://github.com/vercel/next.js/issues/43704
30+
searchParams: Record<string, string | string[] | undefined>
31+
}) {
32+
// TODO: Can we use cookies-next to read cookie in this environment?
33+
const cookie = cookies().get(kConnectSession)
34+
if (!cookie) {
35+
console.warn('No cookie found, redirecting to openint')
36+
// Temporary hack to redirect to the right place to accomodate for oauth url not fully changed yet
37+
const url = new URL('https://app.venice.is/connect/callback')
38+
for (const [key, value] of Object.entries(searchParams)) {
39+
url.searchParams.append(key, value as string)
40+
}
41+
return redirect(url.toString())
42+
}
43+
const msg = await (async (): Promise<FrameMessage | null> => {
44+
try {
45+
const res = await NangoConnect.doOauthCallback(searchParams)
46+
if (!res) {
47+
// This means that we are using the @nango/frontend websocket client...
48+
return null
49+
}
50+
if (!cookie) {
51+
return {
52+
type: 'ERROR',
53+
data: {code: 'BAD_REQUEST', message: 'No session found'},
54+
}
55+
}
56+
if (res.eventType !== 'AUTHORIZATION_SUCEEDED') {
57+
return {
58+
type: 'ERROR',
59+
data: {code: res.data.authErrorType, message: res.data.authErrorDesc},
60+
}
61+
}
62+
const session = zConnectSession.parse(JSON.parse(cookie.value))
63+
const viewer = await serverComponentGetViewer({
64+
searchParams: {[kAccessToken]: session.token},
65+
})
66+
const connectionId = res.data.connectionId as Id['conn']
67+
if (session.connectionId !== connectionId) {
68+
console.warn('Revoking due to unmatched connectionId')
69+
const nango = initNangoSDK({
70+
headers: {authorization: `Bearer ${envRequired.NANGO_SECRET_KEY}`},
71+
})
72+
await nango.DELETE('/connection/{connectionId}', {
73+
params: {
74+
path: {connectionId: res.data.connectionId},
75+
query: {provider_config_key: res.data.providerConfigKey},
76+
},
77+
})
78+
return {
79+
type: 'ERROR',
80+
data: {
81+
code: 'FORBIDDEN',
82+
message: `Session connectionId (${session.connectionId}) not matching connected connectionId ${connectionId}`,
83+
},
84+
}
85+
}
86+
const {caller} = serverSideHelpersFromViewer(viewer)
87+
await caller.postConnect([res.data, res.data.providerConfigKey, {}])
88+
return {
89+
type: 'SUCCESS',
90+
data: {connectionId: res.data.connectionId as Id['conn']},
91+
}
92+
} catch (err) {
93+
console.error('[oauth] Error during connect', err)
94+
return {
95+
type: 'ERROR',
96+
data: {code: 'INTERNAL_SERVER_ERROR', message: `${err}`},
97+
}
2798
}
28-
}, [code, state])
99+
})()
100+
console.log('[oauth] callback result', msg)
29101

102+
// How do we do redirect here?
30103
return (
31104
<FullScreenCenter>
32-
<span className="mb-2">Processing authentication...</span>
105+
{msg && (
106+
<>
107+
<span className="mb-2">{msg.type} </span>
108+
<span className="mb-2">
109+
{msg.type === 'ERROR'
110+
? `[${msg.data.code}] ${msg.data.message}`
111+
: msg.data.connectionId}
112+
</span>
113+
</>
114+
)}
115+
<CallbackEffect msg={msg} autoClose={!msg} />
33116
</FullScreenCenter>
34117
)
35118
}

0 commit comments

Comments
 (0)