S
SolidJS•3mo ago
midnight

Unexpected End of JSON Input on API Route

I am working through creating a OIDC workflow. I have a Astro site that sends the user to the Auth endpoint which handles the handshake with Google for Auth and through the redirect_url I send the browser back to the SolidStart App. I have this file at src/routes/auth/callback.ts that works in dev mode but not when deployed:
import { redirect } from "@solidjs/router";
import type { APIEvent } from "@solidjs/start/server";
import { setCookie } from "vinxi/http";

export async function GET({ request, nativeEvent }: APIEvent) {
const { searchParams } = new URL(request.url);
const code = searchParams.get("code");

if (code) {
const response = await fetch(`${import.meta.env.VITE_AUTH_URL}token`, {
method: "POST",
body: new URLSearchParams({
grant_type: "authorization_code",
client_id: "astro",
code,
redirect_uri: import.meta.env.PROD
? `https://${import.meta.env.VITE_APP_URL}/auth/callback`
: "http://localhost:3000/auth/callback",
}),
});

if (response.ok) {
const { access_token } = await response.json();
setCookie(nativeEvent, "auth_token", access_token, {
httpOnly: import.meta.env.PROD,
maxAge: 60 * 60 * 24 * 7, // 7 days
// sameSite: "strict",
});
return redirect("/");
}
}
return redirect(`https://${import.meta.env.VITE_WWW_URL}`, 406);
}
import { redirect } from "@solidjs/router";
import type { APIEvent } from "@solidjs/start/server";
import { setCookie } from "vinxi/http";

export async function GET({ request, nativeEvent }: APIEvent) {
const { searchParams } = new URL(request.url);
const code = searchParams.get("code");

if (code) {
const response = await fetch(`${import.meta.env.VITE_AUTH_URL}token`, {
method: "POST",
body: new URLSearchParams({
grant_type: "authorization_code",
client_id: "astro",
code,
redirect_uri: import.meta.env.PROD
? `https://${import.meta.env.VITE_APP_URL}/auth/callback`
: "http://localhost:3000/auth/callback",
}),
});

if (response.ok) {
const { access_token } = await response.json();
setCookie(nativeEvent, "auth_token", access_token, {
httpOnly: import.meta.env.PROD,
maxAge: 60 * 60 * 24 * 7, // 7 days
// sameSite: "strict",
});
return redirect("/");
}
}
return redirect(`https://${import.meta.env.VITE_WWW_URL}`, 406);
}
Locally on my machine it works just fine but when deployed I get a 500 Request error Unexpected end of JSON input with the OIDC code in the URL bar: my.domain.com/auth/callback?code=eyJhbGci... If I pull the code out and put it into jwt.io to validate, its valid and expected. I dont know where to go from here to debug further and would love some guidance on where to investigate and understand where my bug is.
18 Replies
Jasmin
Jasmin•3mo ago
is the VITE_AUTH_URL env variable set on your deployment?
midnight
midnightOP•3mo ago
It is, I validated by logging it to the console in aws cloudwatch.
Jasmin
Jasmin•3mo ago
okay, the errors says that the response doesn't return a json, can you console.log it before calling .json()?
midnight
midnightOP•3mo ago
All the variables seem to be set as expected. I added a console.log statement right below the if (response.ok) so I can see it gets all the way there but it seems to fall over at the const { access_token} = line. Yeah, Are you saying to add a console.log(response) in the if (response.ok) { statement?
Jasmin
Jasmin•3mo ago
yes, just above .json()
midnight
midnightOP•3mo ago
Just added it, let me do a deploy since I cant replicate in dev mode
midnight
midnightOP•3mo ago
2024-08-23T15:58:22.972Z 419cfb7f-c87b-436f-9629-9f8302e7d52b INFO LOGGING REPONSE Response {
status: 200,
statusText: 'OK',
headers: Headers {
date: 'Fri, 23 Aug 2024 15:58:22 GMT',
'content-type': 'application/json; charset=UTF-8',
'content-length': '0',
connection: 'keep-alive',
'x-amzn-requestid': '926d3979-c395-427b-b786-560539e80e53',
'x-amzn-trace-id': 'root=1-66c8b19e-4f26f4101c402e915b7ba487;parent=246adf27c28d6bf4;sampled=0;lineage=37c3db30:0'
},
body: ReadableStream { locked: false, state: 'readable', supportsBYOB: true },
bodyUsed: false,
ok: true,
redirected: false,
type: 'basic',
url: 'https://jtizmo3keiw3zxsgiqwkwkxdfm0ldelm.lambda-url.us-east-2.on.aws/token'
}
2024-08-23T15:58:22.972Z 419cfb7f-c87b-436f-9629-9f8302e7d52b INFO LOGGING REPONSE Response {
status: 200,
statusText: 'OK',
headers: Headers {
date: 'Fri, 23 Aug 2024 15:58:22 GMT',
'content-type': 'application/json; charset=UTF-8',
'content-length': '0',
connection: 'keep-alive',
'x-amzn-requestid': '926d3979-c395-427b-b786-560539e80e53',
'x-amzn-trace-id': 'root=1-66c8b19e-4f26f4101c402e915b7ba487;parent=246adf27c28d6bf4;sampled=0;lineage=37c3db30:0'
},
body: ReadableStream { locked: false, state: 'readable', supportsBYOB: true },
bodyUsed: false,
ok: true,
redirected: false,
type: 'basic',
url: 'https://jtizmo3keiw3zxsgiqwkwkxdfm0ldelm.lambda-url.us-east-2.on.aws/token'
}
No description
midnight
midnightOP•3mo ago
I added the "LOGGING RESPONSE` part to make it easier to find in the AWS console.
Jasmin
Jasmin•3mo ago
and what is the content of the body when you do response.text()?
midnight
midnightOP•3mo ago
Ill update and deploy. I did get a typescript error that the access_token does not exist on string. Body is unusable: Body has already been read from the web browser and this in aws logs:
2024-08-23T16:12:57.389Z dfc39f63-261c-4b80-811f-e2b3006e2031 INFO LOGGING REPONSE Promise {
<pending>,
[Symbol(async_id_symbol)]: 628,
[Symbol(trigger_async_id_symbol)]: 567,
[Symbol(kResourceStore)]: {
event: H3Event {
__is_event__: true,
node: [Object],
web: [Object],
context: [Object],
_method: 'GET',
_path: '/auth/callback?code=eyJh...redacted...&state',
_headers: Headers {
'cloudfront-is-android-viewer': 'false',
referer: 'https://accounts.google.com/',
'x-amzn-tls-version': 'TLSv1.2',
'cloudfront-viewer-country': 'US',
'sec-fetch-site': 'cross-site',
2024-08-23T16:12:57.389Z dfc39f63-261c-4b80-811f-e2b3006e2031 INFO LOGGING REPONSE Promise {
<pending>,
[Symbol(async_id_symbol)]: 628,
[Symbol(trigger_async_id_symbol)]: 567,
[Symbol(kResourceStore)]: {
event: H3Event {
__is_event__: true,
node: [Object],
web: [Object],
context: [Object],
_method: 'GET',
_path: '/auth/callback?code=eyJh...redacted...&state',
_headers: Headers {
'cloudfront-is-android-viewer': 'false',
referer: 'https://accounts.google.com/',
'x-amzn-tls-version': 'TLSv1.2',
'cloudfront-viewer-country': 'US',
'sec-fetch-site': 'cross-site',
I need to edit this later to remove my info
Jasmin
Jasmin•3mo ago
:thinkies: response.text() shouldn't return this error you need to await response.text() afaik and then you can see the plain response which isn't a json it seems you can ignore the other error at the bottom, that's because you call text() and json() and both want to consume the body
midnight
midnightOP•3mo ago
Yeah, seems like it returns a jwt encoded response for the code. I think the problem I am trying to understand is why does this work when running locally on my machine. Let me check something locally though
midnight
midnightOP•3mo ago
Yeah, running in dev mode, the original code works and sets the auth_token to
...redacted...
...redacted...
No description
Jasmin
Jasmin•3mo ago
please watch out sharing your tokens like this xD I don't know what could be the cause of this bth
midnight
midnightOP•3mo ago
Theres nothing sensitive 😅 just an email address
Jasmin
Jasmin•3mo ago
okay :) and you're sure that the environment variable are the same? other than that I don't know
midnight
midnightOP•3mo ago
Yeah they should be but I can add logging in to validate again against localhost. Auth resides in lambda at all times so it shouldnt change other than redirecting to localhost in dev or to the solidstart app when deployed. I appreciate your help though! Ill keep poking at it and see what I can figure out, its been two days troubleshooting so I was starting to think it was something obvious I did. I have to step away for a little (prob for the best to let the mind churn on it) but thank you again for taking time to help!
Jasmin
Jasmin•3mo ago
no problem!
Want results from more Discord servers?
Add your server