11import { getLogger } from "@logtape/logtape" ;
2+ import { validatePublicUrl } from "../runtime/url.ts" ;
23import type { ResourceDescriptor } from "./jrd.ts" ;
34
45const logger = getLogger ( [ "fedify" , "webfinger" , "lookup" ] ) ;
56
7+ const MAX_REDIRECTION = 5 ; // TODO: Make this configurable.
8+
69/**
710 * Looks up a WebFinger resource.
811 * @param resource The resource URL to look up.
@@ -26,12 +29,14 @@ export async function lookupWebFinger(
2629 }
2730 let url = new URL ( `${ protocol } //${ server } /.well-known/webfinger` ) ;
2831 url . searchParams . set ( "resource" , resource . href ) ;
32+ let redirected = 0 ;
2933 while ( true ) {
3034 logger . debug (
3135 "Fetching WebFinger resource descriptor from {url}..." ,
3236 { url : url . href } ,
3337 ) ;
3438 let response : Response ;
39+ await validatePublicUrl ( url . href ) ;
3540 try {
3641 response = await fetch ( url , {
3742 headers : { Accept : "application/jrd+json" } ,
@@ -48,10 +53,32 @@ export async function lookupWebFinger(
4853 response . status >= 300 && response . status < 400 &&
4954 response . headers . has ( "Location" )
5055 ) {
51- url = new URL (
56+ redirected ++ ;
57+ if ( redirected >= MAX_REDIRECTION ) {
58+ logger . error (
59+ "Too many redirections ({redirections}) while fetching WebFinger " +
60+ "resource descriptor." ,
61+ { redirections : redirected } ,
62+ ) ;
63+ return null ;
64+ }
65+ const redirectedUrl = new URL (
5266 response . headers . get ( "Location" ) ! ,
5367 response . url == null || response . url === "" ? url : response . url ,
5468 ) ;
69+ if ( redirectedUrl . protocol !== url . protocol ) {
70+ logger . error (
71+ "Redirected to a different protocol ({protocol} to " +
72+ "{redirectedProtocol}) while fetching WebFinger resource " +
73+ "descriptor." ,
74+ {
75+ protocol : url . protocol ,
76+ redirectedProtocol : redirectedUrl . protocol ,
77+ } ,
78+ ) ;
79+ return null ;
80+ }
81+ url = redirectedUrl ;
5582 continue ;
5683 }
5784 if ( ! response . ok ) {
0 commit comments