mirror of https://github.com/jlelse/GoBlog
Sign ActivityPub requests to get remote actor
This commit is contained in:
parent
bb8913d2ad
commit
b4a1972968
|
@ -147,7 +147,7 @@ func (a *goBlog) apHandleInbox(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
blogIri := a.apIri(blog)
|
blogIri := a.apIri(blog)
|
||||||
// Verify request
|
// Verify request
|
||||||
requestActor, requestKey, requestActorStatus, err := a.apVerifySignature(r)
|
requestActor, requestKey, requestActorStatus, err := a.apVerifySignature(r, blogIri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Send 401 because signature could not be verified
|
// Send 401 because signature could not be verified
|
||||||
a.serveError(w, r, err.Error(), http.StatusUnauthorized)
|
a.serveError(w, r, err.Error(), http.StatusUnauthorized)
|
||||||
|
@ -188,7 +188,7 @@ func (a *goBlog) apHandleInbox(w http.ResponseWriter, r *http.Request) {
|
||||||
// Do
|
// Do
|
||||||
switch activity["type"] {
|
switch activity["type"] {
|
||||||
case "Follow":
|
case "Follow":
|
||||||
a.apAccept(blogName, blog, activity)
|
a.apAccept(blogName, blogIri, blog, activity)
|
||||||
case "Undo":
|
case "Undo":
|
||||||
if object, ok := activity["object"].(map[string]any); ok {
|
if object, ok := activity["object"].(map[string]any); ok {
|
||||||
ot := cast.ToString(object["type"])
|
ot := cast.ToString(object["type"])
|
||||||
|
@ -234,14 +234,14 @@ func (a *goBlog) apHandleInbox(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusOK)
|
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)
|
verifier, err := httpsig.NewVerifier(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Error with signature header etc.
|
// Error with signature header etc.
|
||||||
return nil, "", 0, err
|
return nil, "", 0, err
|
||||||
}
|
}
|
||||||
keyID := verifier.KeyId()
|
keyID := verifier.KeyId()
|
||||||
actor, statusCode, err := a.apGetRemoteActor(keyID)
|
actor, statusCode, err := a.apGetRemoteActor(keyID, blogIri)
|
||||||
if err != nil || actor == nil || statusCode != 0 {
|
if err != nil || actor == nil || statusCode != 0 {
|
||||||
// Actor not found or something else bad
|
// Actor not found or something else bad
|
||||||
return nil, keyID, statusCode, err
|
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>`)
|
_, _ = 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) {
|
func (a *goBlog) apGetRemoteActor(iri, ownBlogIri string) (*asPerson, int, error) {
|
||||||
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, iri, nil)
|
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, iri, strings.NewReader(""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
req.Header.Set("Accept", contenttype.AS)
|
req.Header.Set("Accept", contenttype.AS)
|
||||||
req.Header.Set(userAgent, appUserAgent)
|
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)
|
resp, err := a.httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
|
@ -367,7 +377,7 @@ func (a *goBlog) apUndelete(p *post) {
|
||||||
a.apPost(p)
|
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
|
// it's a follow, write it down
|
||||||
newFollower := follow["actor"].(string)
|
newFollower := follow["actor"].(string)
|
||||||
log.Println("New follow request:", newFollower)
|
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
|
// actor and object are equal
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
follower, status, err := a.apGetRemoteActor(newFollower)
|
follower, status, err := a.apGetRemoteActor(newFollower, blogIri)
|
||||||
if err != nil || status != 0 {
|
if err != nil || status != 0 {
|
||||||
// Couldn't retrieve remote actor info
|
// Couldn't retrieve remote actor info
|
||||||
log.Println("Failed to retrieve remote actor info:", newFollower)
|
log.Println("Failed to retrieve remote actor info:", newFollower)
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.goblog.app/app/pkgs/bufferpool"
|
"go.goblog.app/app/pkgs/bufferpool"
|
||||||
|
@ -77,17 +76,13 @@ func (a *goBlog) apSendSigned(blogIri, to string, activity []byte) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
iri, err := url.Parse(to)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r.Header.Set("Accept-Charset", "utf-8")
|
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(userAgent, appUserAgent)
|
||||||
r.Header.Set("Accept", contenttype.ASUTF8)
|
r.Header.Set("Accept", contenttype.ASUTF8)
|
||||||
r.Header.Set(contentType, contenttype.ASUTF8)
|
r.Header.Set(contentType, contenttype.ASUTF8)
|
||||||
r.Header.Set("Host", iri.Host)
|
|
||||||
// Sign request
|
// 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()
|
a.apPostSignMutex.Lock()
|
||||||
err = a.apPostSigner.SignRequest(a.apPrivateKey, blogIri+"#main-key", r, activity)
|
err = a.apPostSigner.SignRequest(a.apPrivateKey, blogIri+"#main-key", r, activity)
|
||||||
a.apPostSignMutex.Unlock()
|
a.apPostSignMutex.Unlock()
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -18,7 +18,7 @@ require (
|
||||||
github.com/disintegration/imaging v1.6.2
|
github.com/disintegration/imaging v1.6.2
|
||||||
github.com/dmulholl/mp3lib v1.0.0
|
github.com/dmulholl/mp3lib v1.0.0
|
||||||
github.com/elnormous/contenttype v1.0.3
|
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/emersion/go-smtp v0.15.0
|
||||||
github.com/go-chi/chi/v5 v5.0.7
|
github.com/go-chi/chi/v5 v5.0.7
|
||||||
github.com/go-fed/httpsig v1.1.0
|
github.com/go-fed/httpsig v1.1.0
|
||||||
|
@ -59,7 +59,7 @@ require (
|
||||||
// master
|
// master
|
||||||
github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38
|
github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38
|
||||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
|
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/sync v0.0.0-20220907140024-f12130a52804
|
||||||
golang.org/x/text v0.3.7
|
golang.org/x/text v0.3.7
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -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 h1:5DrD4LGO3ohab+jPplwE/LlY9JqmkYdssz4Zu7xl8Cs=
|
||||||
github.com/elnormous/contenttype v1.0.3/go.mod h1:ngVcyGGU8pnn4QJ5sL4StrNgc/wmXZXy5IQSBuHOFPg=
|
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-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-20220912192320-0145f2c60ead h1:fI1Jck0vUrXT8bnphprS1EoVRe2Q5CKCX8iDlpqjQ/Y=
|
||||||
github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
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 h1:3+hMGMGrqP/lqd7qoxZc1hTU8LY8gHV9RFGWlqSDmP8=
|
||||||
github.com/emersion/go-smtp v0.15.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
|
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=
|
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-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-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-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220907135653-1e95f45603a7 h1:1WGATo9HAhkWMbfyuVU0tEFP88OIkUvwaHFveQPvzCQ=
|
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI=
|
||||||
golang.org/x/net v0.0.0-20220907135653-1e95f45603a7/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
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-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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
|
Loading…
Reference in New Issue