my own indieAuth provider! indiko.dunkirk.sh/docs
indieauth oauth2-server

feat: canonicalize urls

dunkirk.sh b4ac71ea 753ff31e

verified
Changed files
+20 -8
src
routes
+20 -8
src/routes/indieauth.ts
··· 568 568 569 569 // Validate required OAuth 2.0 parameters 570 570 const responseType = params.get("response_type"); 571 - const clientId = params.get("client_id"); 572 - const redirectUri = params.get("redirect_uri"); 571 + const rawClientId = params.get("client_id"); 572 + const rawRedirectUri = params.get("redirect_uri"); 573 573 const state = params.get("state"); 574 574 const codeChallenge = params.get("code_challenge"); 575 575 const codeChallengeMethod = params.get("code_challenge_method"); ··· 580 580 return new Response("Unsupported response_type", { status: 400 }); 581 581 } 582 582 583 - if (!clientId || !redirectUri || !state || !codeChallenge) { 583 + if (!rawClientId || !rawRedirectUri || !state || !codeChallenge) { 584 584 return new Response("Missing required parameters", { status: 400 }); 585 585 } 586 + 587 + // Canonicalize URLs for consistent storage and comparison 588 + const clientId = canonicalizeURL(rawClientId); 589 + const redirectUri = canonicalizeURL(rawRedirectUri); 586 590 587 591 // Validate redirect_uri is a valid URL 588 592 try { ··· 1349 1353 } 1350 1354 1351 1355 const action = body.action; 1352 - const clientId = body.client_id; 1353 - const redirectUri = body.redirect_uri; 1356 + const rawClientId = body.client_id; 1357 + const rawRedirectUri = body.redirect_uri; 1354 1358 const state = body.state; 1355 1359 const codeChallenge = body.code_challenge; 1356 1360 const me = body.me || null; 1357 1361 1358 - if (!clientId || !redirectUri || !state || !codeChallenge) { 1362 + if (!rawClientId || !rawRedirectUri || !state || !codeChallenge) { 1359 1363 return new Response("Missing required parameters", { status: 400 }); 1360 1364 } 1365 + 1366 + // Canonicalize URLs for consistent storage and comparison 1367 + const clientId = canonicalizeURL(rawClientId); 1368 + const redirectUri = canonicalizeURL(rawRedirectUri); 1361 1369 1362 1370 if (action === "deny") { 1363 1371 return Response.redirect( ··· 1459 1467 const { 1460 1468 grant_type, 1461 1469 code, 1462 - client_id, 1470 + client_id: raw_client_id, 1463 1471 client_secret, 1464 - redirect_uri, 1472 + redirect_uri: raw_redirect_uri, 1465 1473 code_verifier, 1466 1474 } = body; 1475 + 1476 + // Canonicalize URLs for consistent comparison with stored values 1477 + const client_id = raw_client_id ? canonicalizeURL(raw_client_id) : undefined; 1478 + const redirect_uri = raw_redirect_uri ? canonicalizeURL(raw_redirect_uri) : undefined; 1467 1479 1468 1480 if (grant_type !== "authorization_code" && grant_type !== "refresh_token") { 1469 1481 return Response.json(