webfinger.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. package webfinger
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net/http"
  7. "net/url"
  8. "strings"
  9. "github.com/owncast/owncast/utils"
  10. )
  11. // GetWebfingerLinks will return webfinger data for an account.
  12. func GetWebfingerLinks(account string) ([]map[string]interface{}, error) {
  13. type webfingerResponse struct {
  14. Links []map[string]interface{} `json:"links"`
  15. }
  16. account = strings.TrimLeft(account, "@") // remove any leading @
  17. accountComponents := strings.Split(account, "@")
  18. fediverseServer := accountComponents[1]
  19. // Reject any requests to our internal network or loopback.
  20. if utils.IsHostnameInternal(fediverseServer) {
  21. return nil, errors.New("unable to use provided host as a valid fediverse server")
  22. }
  23. // HTTPS is required.
  24. requestURL, err := url.Parse("https://" + fediverseServer)
  25. if err != nil {
  26. return nil, fmt.Errorf("unable to parse fediverse server host %s", fediverseServer)
  27. }
  28. requestURL.Path = "/.well-known/webfinger"
  29. query := requestURL.Query()
  30. query.Add("resource", fmt.Sprintf("acct:%s", account))
  31. requestURL.RawQuery = query.Encode()
  32. // Do not support redirects.
  33. client := &http.Client{
  34. CheckRedirect: func(req *http.Request, via []*http.Request) error {
  35. return http.ErrUseLastResponse
  36. },
  37. }
  38. response, err := client.Get(requestURL.String())
  39. if err != nil {
  40. return nil, err
  41. }
  42. defer response.Body.Close()
  43. var links webfingerResponse
  44. decoder := json.NewDecoder(response.Body)
  45. if err := decoder.Decode(&links); err != nil {
  46. return nil, err
  47. }
  48. return links.Links, nil
  49. }