* This function ensures that an oauth state was indeed encoded for the browser * session performing the oauth callback. * * @param event The H3 event object, used to read and delete the cookie * @param state The JSON string containing the original state and id * @returns The original OAuth stat
(event: H3Event, state: string | null)
| 183 | * @throws An error if the id is missing or invalid, indicating a potential issue with cookies or expired state |
| 184 | */ |
| 185 | function decodeOAuthState(event: H3Event, state: string | null): OAuthStateData { |
| 186 | if (!state) { |
| 187 | // May happen during transition period (if a user initiated auth flow before |
| 188 | // the release with the new state handling, then tries to complete it after |
| 189 | // the release). |
| 190 | throw createError({ |
| 191 | statusCode: 400, |
| 192 | message: 'Missing state parameter', |
| 193 | }) |
| 194 | } |
| 195 | |
| 196 | // The state sting was encoded using encodeOAuthState. No need to protect |
| 197 | // against JSON parsing since the StateStore should ensure it's integrity. |
| 198 | const decoded = JSON.parse(state) as { data: OAuthStateData; id: string } |
| 199 | const requestCookieName = `${OAUTH_REQUEST_COOKIE_PREFIX}_${decoded.id}` |
| 200 | |
| 201 | if (getCookie(event, requestCookieName) != null) { |
| 202 | // The cookie will never be used again since the state store ensure unique |
| 203 | // nonces, but we delete it to clean up any remnants of the authentication |
| 204 | // flow. |
| 205 | deleteCookie(event, requestCookieName, { |
| 206 | httpOnly: true, |
| 207 | secure: !import.meta.dev, |
| 208 | sameSite: 'lax', |
| 209 | path: event.path.split('?', 1)[0], |
| 210 | }) |
| 211 | } else { |
| 212 | throw createError({ |
| 213 | statusCode: 400, |
| 214 | message: 'Missing authentication state. Please enable cookies and try again.', |
| 215 | }) |
| 216 | } |
| 217 | |
| 218 | return decoded.data |
| 219 | } |
| 220 | |
| 221 | /** |
| 222 | * Fetches the mini profile for the authenticated user, including their avatar if available. |