activitypub: implement HTTP Signatures using httpsig library

thanks @ahknight!
pull/27/head
Ryan Barrett 2017-09-19 07:15:38 -07:00
rodzic 2699de6903
commit b123088158
3 zmienionych plików z 30 dodań i 6 usunięć

Wyświetl plik

@ -3,6 +3,7 @@
bs4
feedparser
granary>=1.8
httpsig
mf2py>=1.0.4
mf2util>=0.5.0
mock

Wyświetl plik

@ -13,6 +13,7 @@ import urllib2
from django_salmon import magicsigs, utils
import feedparser
from granary import atom, microformats2
from httpsig.sign import HeaderSigner
import mf2py
import mock
from mock import call
@ -105,9 +106,12 @@ class WebmentionTest(testutil.TestCase):
],
}, kwargs['json'])
expected_headers = copy.copy(common.HEADERS)
expected_headers['Content-Type'] = activitypub.CONTENT_TYPE_AS
self.assertEqual(expected_headers, kwargs['headers'])
headers = kwargs['headers']
self.assertEqual(activitypub.CONTENT_TYPE_AS, headers['Content-Type'])
expected_key = MagicKey.get_by_id('a')
rsa_key = kwargs['auth'].header_signer._rsa._key
self.assertEqual(expected_key.private_pem(), rsa_key.exportKey())
def test_salmon(self, mock_get, mock_post):
orig_atom = requests_response("""\

Wyświetl plik

@ -4,6 +4,7 @@ TODO tests:
* actor/attributedTo could be string URL
* salmon rel via webfinger via author.name + domain
"""
import datetime
import json
import logging
import urlparse
@ -15,6 +16,7 @@ import django_salmon
from django_salmon import magicsigs, utils
import feedparser
from granary import atom, microformats2
from httpsig.requests_auth import HTTPSignatureAuth
import mf2py
import mf2util
from oauth_dropins.webutil import util
@ -93,10 +95,27 @@ class WebmentionHandler(webapp2.RequestHandler):
source_obj['inReplyTo'],
])
# deliver source object to target actor's inbox
# prepare HTTP Signature (required by Mastodon)
# https://w3c.github.io/activitypub/#authorization-lds
# https://tools.ietf.org/html/draft-cavage-http-signatures-07
# https://github.com/tootsuite/mastodon/issues/4906#issuecomment-328844846
source_domain = urlparse.urlparse(source).netloc
key = models.MagicKey.get_or_create(source_domain)
acct = 'acct:me@%s' % source_domain
auth = HTTPSignatureAuth(secret=key.private_pem(), key_id=acct,
algorithm='rsa-sha256')
# deliver source object to target actor's inbox.
headers = {
'Content-Type': activitypub.CONTENT_TYPE_AS,
# required for HTTP Signature
# https://tools.ietf.org/html/draft-cavage-http-signatures-07#section-2.1.3
'Date': datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT'),
}
resp = common.requests_post(
urlparse.urljoin(target, inbox_url), json=source_obj,
headers={'Content-Type': activitypub.CONTENT_TYPE_AS}, log=True)
urlparse.urljoin(target, inbox_url), json=source_obj, auth=auth,
headers=headers, log=True)
def send_salmon(self, source_obj, target_url=None, target_resp=None):
# fetch target HTML page, extract Atom rel-alternate link