(request: Request)
| 192 | }; |
| 193 | |
| 194 | const handleToken = async (request: Request) => { |
| 195 | const params = new URLSearchParams(await request.text()); |
| 196 | const basic = decodeBasic(request.headers.get("authorization")); |
| 197 | const clientId = basic?.username ?? params.get("client_id"); |
| 198 | const clientSecret = basic?.password ?? params.get("client_secret"); |
| 199 | const client = clientId ? clients.get(clientId) : undefined; |
| 200 | if (!clientId || !client) return json({ error: "invalid_client" }, { status: 401 }); |
| 201 | if (client.clientSecret !== null && client.clientSecret !== clientSecret) { |
| 202 | return json({ error: "invalid_client" }, { status: 401 }); |
| 203 | } |
| 204 | const code = params.get("code"); |
| 205 | const redirectUri = params.get("redirect_uri"); |
| 206 | const verifier = params.get("code_verifier"); |
| 207 | const record = code ? authorizationCodes.get(code) : undefined; |
| 208 | if (!code || !redirectUri || !verifier || !record) { |
| 209 | return json({ error: "invalid_grant" }, { status: 400 }); |
| 210 | } |
| 211 | if ( |
| 212 | record.clientId !== clientId || |
| 213 | record.redirectUri !== redirectUri || |
| 214 | record.codeChallenge !== (await codeChallengeForVerifier(verifier)) |
| 215 | ) { |
| 216 | return json({ error: "invalid_grant" }, { status: 400 }); |
| 217 | } |
| 218 | authorizationCodes.delete(code); |
| 219 | const accessToken = `at_${crypto.randomUUID()}`; |
| 220 | const refreshToken = `rt_${crypto.randomUUID()}`; |
| 221 | issuedAccessTokens.add(accessToken); |
| 222 | return json( |
| 223 | { |
| 224 | access_token: accessToken, |
| 225 | refresh_token: refreshToken, |
| 226 | token_type: "Bearer", |
| 227 | expires_in: 3600, |
| 228 | ...(record.scope ? { scope: record.scope } : {}), |
| 229 | }, |
| 230 | { headers: { "cache-control": "no-store" } }, |
| 231 | ); |
| 232 | }; |
| 233 | |
| 234 | const OpenApiEchoItem = Schema.Struct({ id: Schema.Number, name: Schema.String }); |
| 235 | const OpenApiEchoItemsGroup = HttpApiGroup.make("items").add( |
no test coverage detected