## ActivityPubとその周辺技術についてざっくりと知る ![](GT-front-sj1.png) 白方 健太郎 (@argrath) --- ## Me * 白方 健太郎 (@argrath) * Wandering Programmer * お仕事募集中 --- ## 事前アンケート --- ## mastodon/misskey/fedibird etc... 使ったことある人? --- ## mastodon/misskey/fedibird etc... 今も使っている人? --- ## Mastodon * 連合型マイクロブログサーバ --- ## 連合型 (federated) --- ## 連合型 ![](network-models.jpg) (左から、中央集権型、連合型、分散型)
https://docs.joinmastodon.org/assets/network-models.jpg
--- ## 連合型マイクロブログを成立させるために必要な機能は? * 複数のマイクロブログがあるだけではだめ * cf. TwitterとInstagram ---
ところで
--- ## マイクロブログの基本機能とは? * 単なる掲示板との違いは? --- ## マイクロブログの基本機能 * ユーザーは他のユーザーをフォローできる * フォローしたユーザーの投稿をまとめて一つのタイムラインとして読める --- ## 連合型マイクロブログを成立させるために必要な機能は? * 複数のマイクロブログがあるだけではだめ * cf. TwitterとInstagram * 他のサーバのユーザーをフォローできない ---
リモートフォロー
--- ## リモートフォロー * 他のサーバのユーザーをフォローする機能 * どのサーバのユーザーでもフォローできて自分のタイムラインを作れる * フォローしたいユーザーのサーバに合わせる必要がない * ユーザーは好きなサーバを選べる --- ## リモートフォローを実現するために必要な機能 * ユーザーの位置を発見する * 他のサーバにフォローリクエストを送る * 他のサーバにいるユーザーの更新を受け取る --- ## 発見をどうするか * ex. 「`@argrath@actub.ub32.org`」を解決する方法 --- ## RFC 7033 WebFinger ```url https://{ホスト名}/.well-known/webfinger?resource=acct:{uri} ``` * {ホスト名}はアカウントのホスト名部分を使う * {uri}をアカウント(先頭の`@`なし)に置き換える ex. 「`@argrath@actub.ub32.org`」 ```url https://actub.ub32.org/.well-known/webfinger? resource=acct:argrath@actub.ub32.org ``` --- ```url https://actub.ub32.org/.well-known/webfinger? resource=acct:argrath@actub.ub32.org ``` ``` { "subject": "acct:argrath@actub.ub32.org", "aliases": [ "https://actub.ub32.org/argrath" ], "links": [ { "rel": "http://webfinger.net/rel/profile-page", "type": "text/html", "href": "https://actub.ub32.org/argrath" }, { "rel": "self", "type": "application/activity+json", "href": "https://actub.ub32.org/argrath" } ] } ``` --- ``` { "rel": "self", "type": "application/activity+json", "href": "https://actub.ub32.org/argrath" } ``` * https://actub.ub32.org/argrath --- ## ここからActivityPub --- ## ActivityPub * W3Cが定めた非中央集権型データ交換のためのプロトコル * MIME型: ```text application/ld+json; profile="https://www.w3.org/ns/activitystreams" ``` * 長い * リクエストのAcceptヘッダやレスポンスのContent-typeヘッダにはこれを指定 --- ## ActivityPub * https://actub.ub32.org/argrath = アクター情報の位置 * アクター=ユーザーアカウント --- ## アクター情報 ``` { "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1" ], "id": "https://actub.ub32.org/argrath", "type": "Person", "url": "https://actub.ub32.org/argrath", "inbox": "https://actub.ub32.org/argrath/inbox", "outbox": "https://actub.ub32.org/argrath/outbox", "followers": "https://actub.ub32.org/argrath/followers", "following": "https://actub.ub32.org/argrath/following", "preferredUsername": "argrath", "publicKey": { "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIB...", "id": "https://actub.ub32.org/argrath", "owner": "https://actub.ub32.org/argrath" } } ``` --- ## これは何 * ActivityStreams2 (AS2) で規定されているデータ * 詳細はここでは省略 https://www.w3.org/TR/2017/REC-activitystreams-core-20170523/ --- ## 今回の注目点 ```json "inbox": "https://actub.ub32.org/argrath/inbox", ``` * このアクターに対する通知は全てこのURLにPOSTする --- ## リモートフォローを実現するために必要な機能 * ユーザーの位置を発見する done! * フォローリクエストを送る * 更新通知を受け取る --- ## フォローリクエスト ``` { "@context": "https://www.w3.org/ns/activitystreams", "id": "https://mastodon.social/users/argrath#follows/239706", "type": "Follow", "actor": "https://mastodon.social/users/argrath", "object": "https://actub.ub32.org/argrath" } ``` --- ## フォロー承認 フォローリクエストを投げた時点で基本的には自動的に承認される ``` { "@context": "https://www.w3.org/ns/activitystreams", "id": "https://actub.ub32.org/argrath/accept/1", "type": "Accept", "actor": "https://actub.ub32.org/argrath", "object": { "id": "https://mastodon.social/users/argrath#follows/239706", "type": "Follow", "actor": "https://mastodon.social/users/argrath", "object": "https://actub.ub32.org/argrath" } } ``` --- ## ここで問題にお気づきだろうか… --- ## なりすまし放題! * だれでもinboxにPOSTできる ``` { "@context": "https://www.w3.org/ns/activitystreams", "id": "https://mastodon.social/users/argrath#follows/239706", "type": "Follow", "actor": "https://mastodon.social/users/argrath", "object": "https://actub.ub32.org/argrath" } ``` * "actor"に好きなアクターを書ける ---
HTTP Signatures
--- ## HTTP Signatures * 今年2月にRFC9421に * …なったものは使わない --- ## HTTP Signatures * RFCになる過程で30以上のドラフトが作成され、変更されてきた * ドラフトの過程では互換性は考慮されていない * ActivityPubで使われているのは途中のドラフト版 * https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-09 --- ## HTTP Signatures * HTTPリクエストに署名してSignatureヘッダをつける * 詳細は仕様を参照 --- ## HTTP Signatures ### リクエスト送信側 * 各アクターは鍵ペアを持つ * アクターの管轄サーバが自動生成 * アクターの署名鍵でリクエストに署名 * "Signature"HTTPヘッダに署名をつけてリクエストを送信 ``` Signature: keyId="https://...", algorithm="rsa-sha256", headers="(request-target) host date digest", signature="{署名文字列}" ``` --- ## アクター情報(再掲) ``` { "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1" ], "id": "https://actub.ub32.org/argrath", "type": "Person", "url": "https://actub.ub32.org/argrath", "inbox": "https://actub.ub32.org/argrath/inbox", "outbox": "https://actub.ub32.org/argrath/outbox", "followers": "https://actub.ub32.org/argrath/followers", "following": "https://actub.ub32.org/argrath/following", "preferredUsername": "argrath", "publicKey": { "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIB...", "id": "https://actub.ub32.org/argrath", "owner": "https://actub.ub32.org/argrath" } } ``` --- ## HTTP Signatures ### リクエスト受信側 ```json "publicKey": { "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIB...", "id": "https://actub.ub32.org/argrath", "owner": "https://actub.ub32.org/argrath" }, ``` * 受信側は送信アクターの検証鍵("publicKeyPem")で署名を検証する --- ## リモートフォローを実現するために必要な機能 * ユーザーの位置を発見する done! * フォローリクエストを送る done! * 更新通知を受け取る --- ## 更新通知 * つぶやきが投稿された時にフォロワーに通知する * …の前に: --- ## つぶやき ``` { "@context": "https://www.w3.org/ns/activitystreams", "id": "https://actub.ub32.org/argrath/20180303185450", "type": "Note", "url": "https://actub.ub32.org/argrath/20180303185450", "published": "2018-03-03T09:54:50Z", "content": "はいさーい", "attributedTo": "https://actub.ub32.org/argrath", "to": [ "https://www.w3.org/ns/activitystreams#Public" ], "cc": [ "https://actub.ub32.org/argrath/followers" ] } ``` --- ## 通知 ``` { "@context": "https://www.w3.org/ns/activitystreams", "id": "https://actub.ub32.org/argrath/20180303185450/activity", "type": "Create", "actor": "https://actub.ub32.org/argrath", "to": [ "https://www.w3.org/ns/activitystreams#Public" ], "cc": [ "https://actub.ub32.org/argrath/followers" ], "object": { "id": "https://actub.ub32.org/argrath/20180303185450", "type": "Note", "url": "https://actub.ub32.org/argrath/20180303185450", "published": "2018-03-03T09:54:50Z", "content": "はいさーい", "attributedTo": "https://actub.ub32.org/argrath", "to": [ "https://www.w3.org/ns/activitystreams#Public" ], "cc": [ "https://actub.ub32.org/argrath/followers" ] } } ``` --- ## 通知 ``` { "@context": "https://www.w3.org/ns/activitystreams", "id": "https://actub.ub32.org/argrath/20180303185450/activity", "type": "Create", "actor": "https://actub.ub32.org/argrath", "to": [ "https://www.w3.org/ns/activitystreams#Public" ], "cc": [ "https://actub.ub32.org/argrath/followers" ], "object": { // つぶやき情報 } } ``` * これをinboxにPOST --- ## リモートフォローを実現するために必要な機能 * ユーザーの位置を発見する done! * フォローリクエストを送る done! * 更新通知を受け取る done! --- ## できた! --- ## 第一部完! ---
時間を確認して余裕があれば
以下落ち穂拾い
--- ## ActivityStream2 * もう少しだけ詳しく --- ## フォローリクエスト(再掲) ``` { "@context": "https://www.w3.org/ns/activitystreams", "id": "https://mastodon.social/users/argrath#follows/239706", "type": "Follow", "actor": "https://mastodon.social/users/argrath", "object": "https://actub.ub32.org/argrath" } ``` --- ```json "@context": "https://www.w3.org/ns/activitystreams", ``` * XMLの名前空間+スキーマのようなもの * リンク先にこのJSONが含んでいるデータの情報がある * 配列にして複数書いても良い * 元となっているJSON-LDの機能 --- ```json "id": "https://mastodon.social/users/argrath#follows/239706", ``` * ユニークなID * そのサーバが管轄するURI(基本的にhttps) --- ```json "type": "Follow", ``` * このデータが表している型 --- * ここまでは必須情報、これ以外はオプション * 詳細は仕様を参照 --- ## 終わり * 資料予定地: https://argrath.ub32.org/slide/2024/0720/index.html ![](20240720.png)