Sign ActivityPub requests to get remote actor

This commit is contained in:
Jan-Lukas Else 2022-09-13 23:05:53 +02:00
parent bb8913d2ad
commit b4a1972968
4 changed files with 26 additions and 21 deletions

View File

@ -147,7 +147,7 @@ func (a *goBlog) apHandleInbox(w http.ResponseWriter, r *http.Request) {
}
blogIri := a.apIri(blog)
// Verify request
requestActor, requestKey, requestActorStatus, err := a.apVerifySignature(r)
requestActor, requestKey, requestActorStatus, err := a.apVerifySignature(r, blogIri)
if err != nil {
// Send 401 because signature could not be verified
a.serveError(w, r, err.Error(), http.StatusUnauthorized)
@ -188,7 +188,7 @@ func (a *goBlog) apHandleInbox(w http.ResponseWriter, r *http.Request) {
// Do
switch activity["type"] {
case "Follow":
a.apAccept(blogName, blog, activity)
a.apAccept(blogName, blogIri, blog, activity)
case "Undo":
if object, ok := activity["object"].(map[string]any); ok {
ot := cast.ToString(object["type"])
@ -234,14 +234,14 @@ func (a *goBlog) apHandleInbox(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}
func (a *goBlog) apVerifySignature(r *http.Request) (*asPerson, string, int, error) {
func (a *goBlog) apVerifySignature(r *http.Request, blogIri string) (*asPerson, string, int, error) {
verifier, err := httpsig.NewVerifier(r)
if err != nil {
// Error with signature header etc.
return nil, "", 0, err
}
keyID := verifier.KeyId()
actor, statusCode, err := a.apGetRemoteActor(keyID)
actor, statusCode, err := a.apGetRemoteActor(keyID, blogIri)
if err != nil || actor == nil || statusCode != 0 {
// Actor not found or something else bad
return nil, keyID, statusCode, err
@ -267,13 +267,23 @@ func handleWellKnownHostMeta(w http.ResponseWriter, r *http.Request) {
_, _ = io.WriteString(w, `<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Link rel="lrdd" type="application/xrd+xml" template="https://`+r.Host+`/.well-known/webfinger?resource={uri}"/></XRD>`)
}
func (a *goBlog) apGetRemoteActor(iri string) (*asPerson, int, error) {
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, iri, nil)
func (a *goBlog) apGetRemoteActor(iri, ownBlogIri string) (*asPerson, int, error) {
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, iri, strings.NewReader(""))
if err != nil {
return nil, 0, err
}
req.Header.Set("Accept", contenttype.AS)
req.Header.Set(userAgent, appUserAgent)
// Sign request
req.Header.Set("Date", time.Now().UTC().Format("Mon, 02 Jan 2006 15:04:05")+" GMT")
req.Header.Set("Host", req.URL.Host)
a.apPostSignMutex.Lock()
err = a.apPostSigner.SignRequest(a.apPrivateKey, ownBlogIri+"#main-key", req, []byte(""))
a.apPostSignMutex.Unlock()
if err != nil {
return nil, 0, err
}
// Do request
resp, err := a.httpClient.Do(req)
if err != nil {
return nil, 0, err
@ -367,7 +377,7 @@ func (a *goBlog) apUndelete(p *post) {
a.apPost(p)
}
func (a *goBlog) apAccept(blogName string, blog *configBlog, follow map[string]any) {
func (a *goBlog) apAccept(blogName, blogIri string, blog *configBlog, follow map[string]any) {
// it's a follow, write it down
newFollower := follow["actor"].(string)
log.Println("New follow request:", newFollower)
@ -376,7 +386,7 @@ func (a *goBlog) apAccept(blogName string, blog *configBlog, follow map[string]a
// actor and object are equal
return
}
follower, status, err := a.apGetRemoteActor(newFollower)
follower, status, err := a.apGetRemoteActor(newFollower, blogIri)
if err != nil || status != 0 {
// Couldn't retrieve remote actor info
log.Println("Failed to retrieve remote actor info:", newFollower)

View File

@ -9,7 +9,6 @@ import (
"io"
"log"
"net/http"
"net/url"
"time"
"go.goblog.app/app/pkgs/bufferpool"
@ -77,17 +76,13 @@ func (a *goBlog) apSendSigned(blogIri, to string, activity []byte) error {
if err != nil {
return err
}
iri, err := url.Parse(to)
if err != nil {
return err
}
r.Header.Set("Accept-Charset", "utf-8")
r.Header.Set("Date", time.Now().UTC().Format("Mon, 02 Jan 2006 15:04:05")+" GMT")
r.Header.Set(userAgent, appUserAgent)
r.Header.Set("Accept", contenttype.ASUTF8)
r.Header.Set(contentType, contenttype.ASUTF8)
r.Header.Set("Host", iri.Host)
// Sign request
r.Header.Set("Date", time.Now().UTC().Format("Mon, 02 Jan 2006 15:04:05")+" GMT")
r.Header.Set("Host", r.URL.Host)
a.apPostSignMutex.Lock()
err = a.apPostSigner.SignRequest(a.apPrivateKey, blogIri+"#main-key", r, activity)
a.apPostSignMutex.Unlock()

4
go.mod
View File

@ -18,7 +18,7 @@ require (
github.com/disintegration/imaging v1.6.2
github.com/dmulholl/mp3lib v1.0.0
github.com/elnormous/contenttype v1.0.3
github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead
github.com/emersion/go-smtp v0.15.0
github.com/go-chi/chi/v5 v5.0.7
github.com/go-fed/httpsig v1.1.0
@ -59,7 +59,7 @@ require (
// master
github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
golang.org/x/net v0.0.0-20220907135653-1e95f45603a7
golang.org/x/net v0.0.0-20220909164309-bea034e7d591
golang.org/x/sync v0.0.0-20220907140024-f12130a52804
golang.org/x/text v0.3.7
gopkg.in/yaml.v3 v3.0.1

8
go.sum
View File

@ -140,8 +140,8 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
github.com/elnormous/contenttype v1.0.3 h1:5DrD4LGO3ohab+jPplwE/LlY9JqmkYdssz4Zu7xl8Cs=
github.com/elnormous/contenttype v1.0.3/go.mod h1:ngVcyGGU8pnn4QJ5sL4StrNgc/wmXZXy5IQSBuHOFPg=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac h1:tn/OQ2PmwQ0XFVgAHfjlLyqMewry25Rz7jWnVoh4Ggs=
github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead h1:fI1Jck0vUrXT8bnphprS1EoVRe2Q5CKCX8iDlpqjQ/Y=
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-smtp v0.15.0 h1:3+hMGMGrqP/lqd7qoxZc1hTU8LY8gHV9RFGWlqSDmP8=
github.com/emersion/go-smtp v0.15.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -624,8 +624,8 @@ golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220907135653-1e95f45603a7 h1:1WGATo9HAhkWMbfyuVU0tEFP88OIkUvwaHFveQPvzCQ=
golang.org/x/net v0.0.0-20220907135653-1e95f45603a7/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=