# webfinger Simple WebFinger server that returns static resources. Written with Python and FastAPI. ## Deployment ### Add static resources as a quickstart - Create a `resource/` folder. This will map to the `?resource=` query parameter. - Put a .jrd file in there; anything before the .jrd will be served via that `resource` query parameter. - Currently, the "subject" will be ignored (as the `resource` will be used directly). - Otherwise, `links` and `aliases` and `properties` will be served normally. - Symlinks will be resolved as well. Try using a URI as a symlink and maybe put it in `aliases` too! Example `resource/acct:a@trwnh.com.jrd` ```json { "subject": "acct:a@trwnh.com", "aliases": ["https://ap.trwnh.com/actors/7057bc10-db1c-4ebe-9e00-22cf04be4e5e", "https://trwnh.com/~a", "acct:trwnh@ap.trwnh.com"], "links": [ { "rel": "self", "type": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"", "href": "https://trwnh.com/actors/7057bc10-db1c-4ebe-9e00-22cf04be4e5e" }, { "rel": "https://webfinger.net/rel/profile-page/", "type": "text/html", "href": "https://trwnh.com/~a" } ] } ``` If your resource URI has slashes in it and would therefore be an invalid UNIX path, it must be percent-encoded. For example, to have the WebFinger server respond to a lookup for `?resource=https://trwnh.com/~a`, you can create a symlink with the path `resource/https%3A%2F%2Ftrwnh.com%2F~a.jrd` like so: ```sh cd resource ln -s "acct:a@trwnh.com" "https%3A%2F%2Ftrwnh.com%2F~a.jrd" ``` ### Running the server Environment variables you may use: - `RESOURCE_DIR`: specify the directory from which resources will be served #### ...with PDM ```bash pdm install pdm run uvicorn webfinger:app --port 7033 ``` You can also run `pdm run start` or `pdm run python -m webfinger` #### ...with virtualenv ```bash virtualenv .venv source .venv/bin/activate pip install -r requirements.txt uvicorn webfinger:app --port 7033 ``` You can also run `python -m webfinger` ### Post-run proxy or redirect You probably want to proxy `/.well-known/webfinger` to localhost:7033 or otherwise host a webfinger service externally and redirect to that instead. For simple deployments on a single domain, you probably want to set up a reverse proxy to the running Uvicorn process (by default, this will be hosted at `localhost:7033`). This will allow you to serve WebFinger via your own domain, without a trailing port. Since WebFinger specifies HTTPS requests, your reverse proxy must support HTTPS. Example nginx proxy_pass to localhost: ``` location /.well-known/webfinger { proxy_pass localhost:7033; } ``` It's recommended that you do any redirects to external services with an HTTP 307 Temporary Redirect. Why not HTTP 302? This is because HTTP 302 does not usually preserve the HTTP method -- some browsers (especially older ones) will treat 302 as 303, issuing a GET request to the new Location regardless of the original request's method. Example nginx redirect to external service: ``` location /.well-known/webfinger { add_header Access-Control-Allow-Origin *; return 307 https://webfinger.example$request_uri; } ``` ## Development `pdm run dev` or `uvicorn webfinger:app --reload` ### TODO #### some api for managing JRD documents basic create/update/delete? #### MAYBE support authorization and private attributes? ```text As with all web resources, access to the WebFinger resource could require authentication. Further, failure to provide required credentials might result in the server forbidding access or providing a different response than had the client authenticated with the server. Likewise, a WebFinger resource MAY provide different responses to different clients based on other factors, such as whether the client is inside or outside a corporate network. As a concrete example, a query performed on the internal corporate network might return link relations to employee pictures, whereas link relations for employee pictures might not be provided to external entities. ``` - [ ] idk if i'm gonna do this but maybe if you authenticate as the owner of the JRD then you can see things like phone numbers and email addresses? ```text Systems or services that expose personal data via WebFinger MUST provide an interface by which users can select which data elements are exposed through the WebFinger interface. For example, social networking sites might allow users to mark certain data as "public" and then utilize that marking as a means of determining what information to expose via WebFinger. The information published via WebFinger would thus comprise only the information marked as public by the user. Further, the user has the ability to remove information from publication via WebFinger by removing this marking. WebFinger MUST NOT be used to provide any personal data unless publishing that data via WebFinger by the relevant service was explicitly authorized by the person whose information is being shared. Publishing one's personal data within an access-controlled or otherwise limited environment on the Internet does not equate to providing implicit authorization of further publication of that data via WebFinger. ``` - [ ] if the above gets done, then there should be a dashboard to choose which information is public and which is not. this probably breaks static serving though, or at least private info should be stored in a database and merged into the final response #### MAYBE rate limit and proxy webfinger requests ```text It is RECOMMENDED that implementers of WebFinger server software take steps to mitigate abuse, including malicious over-use of the server and harvesting of user information. Although there is no mechanism that can guarantee that publicly accessible WebFinger databases won't be harvested, rate-limiting by IP address will prevent or at least dramatically slow harvest by private individuals without access to botnets or other distributed systems. The reason these mitigation strategies are not mandatory is that the correct choice of mitigation strategy (if any) depends greatly on the context. Implementers should not construe this as meaning that they do not need to consider whether to use a mitigation strategy, and if so, what strategy to use. WebFinger client developers should also be aware of potential abuse by spammers or those phishing for information about users. As an example, suppose a mail client was configured to automatically perform a WebFinger query on the sender of each received mail message. If a spammer sent an email using a unique identifier in the 'From' header, then when the WebFinger query was performed, the spammer would be able to associate the request with a particular user's email address. This would provide information to the spammer, including the user's IP address, the fact the user just checked email, what kind of WebFinger client the user utilized, and so on. For this reason, it is strongly advised that clients not perform WebFinger queries unless authorized by the user to do so. ``` - [ ] if/when i add a REST API, the api could have a method to do a lookup proxied through the server. this would allow applications to not leak user IPs so long as they actually use the REST API