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

Configure Feed

Select the types of activity you want to include in your feed.

feat: validate the profle url matches indieauth spec

+14 -4
+13 -3
src/routes/api.ts
··· 1 1 import { db } from "../db"; 2 - import { verifyDomain } from "./indieauth"; 2 + import { verifyDomain, validateProfileURL } from "./indieauth"; 3 3 4 4 function getSessionUser( 5 5 req: Request, ··· 171 171 return Response.json({ error: "Name is required" }, { status: 400 }); 172 172 } 173 173 174 - // If URL is being set, verify domain has rel="me" link back to profile 174 + // If URL is being set, validate format and verify domain ownership 175 175 if (url && typeof url === "string") { 176 + // 1. Validate URL format per IndieAuth spec 177 + const validation = validateProfileURL(url); 178 + if (!validation.valid) { 179 + return Response.json( 180 + { error: validation.error || "Invalid URL format" }, 181 + { status: 400 }, 182 + ); 183 + } 184 + 185 + // 2. Verify domain has rel="me" link back to profile 176 186 const origin = process.env.ORIGIN || "http://localhost:3000"; 177 187 const indikoProfileUrl = `${origin}/u/${user.username}`; 178 188 179 - const verification = await verifyDomain(url, indikoProfileUrl); 189 + const verification = await verifyDomain(validation.canonicalUrl!, indikoProfileUrl); 180 190 if (!verification.success) { 181 191 return Response.json( 182 192 { error: verification.error || "Failed to verify domain" },
+1 -1
src/routes/indieauth.ts
··· 119 119 } 120 120 121 121 // Validate profile URL per IndieAuth spec 122 - function validateProfileURL(urlString: string): { valid: boolean; error?: string; canonicalUrl?: string } { 122 + export function validateProfileURL(urlString: string): { valid: boolean; error?: string; canonicalUrl?: string } { 123 123 let url: URL; 124 124 try { 125 125 url = new URL(urlString);