11import type { OAuthSession } from '@atproto/oauth-client-node'
22import { NodeOAuthClient , OAuthCallbackError } from '@atproto/oauth-client-node'
3- import { createError , getQuery , sendRedirect } from 'h3'
3+ import { createError , getQuery , sendRedirect , setCookie , getCookie , deleteCookie } from 'h3'
44import type { H3Event } from 'h3'
55import { getOAuthLock } from '#server/utils/atproto/lock'
66import { useOAuthStorage } from '#server/utils/atproto/storage'
77import { SLINGSHOT_HOST } from '#shared/utils/constants'
88import { useServerSession } from '#server/utils/server-session'
99import { handleResolver } from '#server/utils/atproto/oauth'
10+ import { handleApiError } from '#server/utils/error-handler'
1011import type { DidString } from '@atproto/lex'
1112import { Client } from '@atproto/lex'
1213import * as com from '#shared/types/lexicons/com'
1314import * as app from '#shared/types/lexicons/app'
1415import { isAtIdentifierString } from '@atproto/lex'
16+ import { scope , getOauthClientMetadata } from '#server/utils/atproto/oauth'
17+ import { UNSET_NUXT_SESSION_PASSWORD } from '#shared/utils/constants'
1518// @ts -expect-error virtual file from oauth module
1619import { clientUri } from '#oauth/config'
1720
@@ -121,7 +124,7 @@ type OAuthStateData = {
121124 redirectPath : string
122125}
123126
124- const SID_COOKIE_NAME = 'atproto_oauth_sid'
127+ const SID_COOKIE_PREFIX = 'atproto_oauth_sid'
125128const SID_COOKIE_VALUE = '1'
126129
127130/**
@@ -145,11 +148,13 @@ const SID_COOKIE_VALUE = '1'
145148 */
146149function encodeOAuthState ( event : H3Event , data : OAuthStateData ) : string {
147150 const sid = generateRandomHexString ( )
148- setCookie ( event , `${ SID_COOKIE_NAME } : ${ sid } ` , SID_COOKIE_VALUE , {
151+ setCookie ( event , `${ SID_COOKIE_PREFIX } _ ${ sid } ` , SID_COOKIE_VALUE , {
149152 maxAge : 60 * 5 ,
150153 httpOnly : true ,
151154 // secure only if NOT in dev mode
152155 secure : ! import . meta. dev ,
156+ sameSite : 'lax' ,
157+ path : event . path ,
153158 } )
154159 return JSON . stringify ( { data, sid } )
155160}
@@ -184,11 +189,13 @@ function decodeOAuthState(event: H3Event, state: string | null): OAuthStateData
184189 // against JSON parsing since the StateStore should ensure it's integrity.
185190 const decoded = JSON . parse ( state ) as { data : OAuthStateData ; sid : string }
186191
187- const sid = getCookie ( event , `${ SID_COOKIE_NAME } : ${ decoded . sid } ` )
192+ const sid = getCookie ( event , `${ SID_COOKIE_PREFIX } _ ${ decoded . sid } ` )
188193 if ( sid === SID_COOKIE_VALUE ) {
189- deleteCookie ( event , `${ SID_COOKIE_NAME } : ${ decoded . sid } ` , {
194+ deleteCookie ( event , `${ SID_COOKIE_PREFIX } _ ${ decoded . sid } ` , {
190195 httpOnly : true ,
191196 secure : ! import . meta. dev ,
197+ sameSite : 'lax' ,
198+ path : event . path ,
192199 } )
193200 } else {
194201 throw createError ( {
@@ -254,10 +261,11 @@ async function getAvatar(did: DidString, pds: string) {
254261 } )
255262
256263 const validatedResponse = app . bsky . actor . profile . main . validate ( profileResponse . value )
264+ const cid = validatedResponse . avatar ?. ref
257265
258- if ( validatedResponse . avatar ?. ref ) {
266+ if ( cid ) {
259267 // Use Bluesky CDN for faster image loading
260- avatar = `https://cdn.bsky.app/img/feed_thumbnail/plain/${ did } /${ validatedResponse . avatar ?. ref } @jpeg`
268+ avatar = `https://cdn.bsky.app/img/feed_thumbnail/plain/${ did } /${ cid } @jpeg`
261269 }
262270 }
263271 } catch {
0 commit comments