Skip to content

Commit

Permalink
more on guides
Browse files Browse the repository at this point in the history
  • Loading branch information
michelson committed Sep 12, 2023
1 parent 63dfb18 commit a20651b
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ This library provides a simple interface to work with the ActivityPub protocol i
- Signature verification for secured interactions.
- Simple Sinatra example to demonstrate usage.

For usage guides on RubyOnRails please check the[guides folder](guides/).

## Installation

```bash
Expand Down
File renamed without changes.
115 changes: 115 additions & 0 deletions guides/inboxes-rails.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
### Implementing ActivityPub Inbox and Outbox in Rails

#### 1. Database Setup:

To store incoming and outgoing activities, you'll need to set up the appropriate database tables.

```bash
rails generate model Activity content:text actor:references type:string object:references target:references published:datetime
```

Then run `rails db:migrate`.

#### 2. Routes:

Define routes for the inbox and outbox.

```ruby
# config/routes.rb
resources :actors do
member do
post :inbox
get :outbox
end
end
```

#### 3. Controller:

Set up your controller to handle the incoming and outgoing requests.

```ruby
# app/controllers/actors_controller.rb
class ActorsController < ApplicationController
def inbox
# Parse the incoming ActivityPub request.
activity = ActivityPub::Activity.from_h(params.require(:activity).permit!)

# Process the incoming activity.
case activity.type
when "Create"
# Handle the creation of a new activity.
when "Follow"
# Handle a new follow request.
end

# Respond to the request.
head :created
end

def outbox
# For the sake of simplicity, we're just displaying all activities related to an actor.
@activities = Activity.where(actor: params[:id])
end
end
```

#### 4. Model:

Your `Activity` model will hold the core logic for processing activities.

```ruby
# app/models/activity.rb
class Activity < ApplicationRecord
belongs_to :actor

# You can add validation and methods to process specific activity types.

validates :type, presence: true

def process_incoming
# Logic to process an incoming activity.
end

def send_outgoing
# Logic to send an outgoing activity.
end
end
```

#### 5. Views:

You may or may not need views, as a lot of this is server-to-server communication. However, for the outbox, it's useful to have a visual representation.

```erb
<!-- app/views/actors/outbox.html.erb -->
<% @activities.each do |activity| %>
<div class="activity">
<strong>Type:</strong> <%= activity.type %><br>
<strong>Content:</strong> <%= activity.content %><br>
<!-- Add more fields as necessary -->
</div>
<% end %>
```

#### 6. Processing Activities:

When receiving an activity in the inbox, you'll want to process it according to its type. This could be acknowledging a follow request, storing a new note or message, updating your local state based on a delete activity, etc.

When sending an activity from the outbox, you'll want to serialize your activity to the correct format, ensure you're addressing it to the correct recipients, handle any necessary authentication or HTTP signatures, and handle possible failures in delivery.

#### 7. Integration with ActivityPub:

Ensure that you integrate the ActivityPub-specific functionalities, like HTTP Signatures, JSON-LD parsing, etc.

### Tips:

- **Separation of Concerns:** Keep the ActivityPub logic separate from your core application logic. Consider using service objects or separate classes/modules to encapsulate ActivityPub-specific behaviors.

- **Security:** Ensure you're verifying any incoming requests to ensure they're genuine. HTTP Signatures are a key component of this for ActivityPub.

- **Testing:** Given the complexity of server-to-server interactions and the various ways an activity can be formatted, testing is crucial. Use Rails' testing capabilities along with libraries like `webmock` to mock external requests.

- **Documentation:** The ActivityPub specification is thorough but can be dense. Regularly refer back to it, and consider looking at other implementations or communities for guidance.

By following the above guidance and building upon the basic setup provided, you should be able to effectively implement and customize an ActivityPub inbox and outbox in a Rails app.
71 changes: 71 additions & 0 deletions guides/signature-rails.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
### HTTP Signatures in ActivityPub with Rails:

**HTTP Signatures** provide a standard way for servers to verify the authenticity and integrity of HTTP messages. They're crucial in a decentralized environment like ActivityPub.

#### 1. Generating a key pair:

Before you can sign anything, you need a public/private key pair. The private key will reside on the server doing the signing, and the public key will be shared with others to verify the signature.

```bash
openssl genpkey -algorithm RSA -out private.pem
openssl pkey -in private.pem -pubout -out public.pem
```

#### 2. Storing the keys:

Store your private key securely on your server. You can serve the public key via your Actor's `publicKey` field in ActivityPub.

#### 3. Signing the request:

When sending an ActivityPub request from your server:

- Create a signature string based on certain headers of your HTTP message.
- Use your private key to sign this string.
- Add the signature to the `Signature` header of your HTTP request.

Ruby has several libraries that can help with this, e.g., `http-signature-ruby`.

#### 4. Verifying incoming requests:

For incoming ActivityPub messages:

- Retrieve the public key from the Actor's profile that sent the request.
- Use this key to verify the signature in the `Signature` header against the headers of the incoming message.

This verifies both the authenticity (it's genuinely from who it claims to be from) and the integrity (the message wasn't tampered with in transit).

### JSON-LD Parsing in ActivityPub with Rails:

**JSON-LD** (JSON Linked Data) is a method of encoding Linked Data using JSON. ActivityPub uses it to provide a context for terms used in messages, ensuring consistent interpretation across different implementations.

#### 1. Adding context:

When sending an ActivityPub message, include a `@context` field, typically with the value "https://www.w3.org/ns/activitystreams".

```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Note",
"content": "Hello World"
}
```

#### 2. Parsing incoming JSON-LD:

When receiving a message, you'll want to interpret it in the context provided:

- Libraries like `json-ld` can help expand messages to a full form, ensuring that shorthand terms are fully understood in their context.

For Rails, you can parse JSON-LD as you would parse typical JSON but be mindful of the `@context` and terms used. The key is understanding that JSON-LD provides a way to disambiguate terms that might have different meanings in different contexts.

### Tips:

- **Security First**: Always validate incoming data. Never assume that just because a message has a valid signature, its content is safe or well-formed.

- **Testing**: Implement thorough tests for your signing and verification logic. Ensure that you can correctly sign messages, and that you correctly reject invalid signatures or tampered messages.

- **Standards are Your Friend**: When in doubt, refer to the [HTTP Signatures spec](https://tools.ietf.org/html/draft-cavage-http-signatures-12) and the [JSON-LD spec](https://www.w3.org/TR/json-ld/). ActivityPub has a well-defined spec, but it does intersect with other standards like these, so sometimes you'll need to look outside the main ActivityPub documentation for clarity.

- **Libraries**: Take advantage of Ruby and Rails libraries. Many of these functionalities, especially HTTP Signatures, can be tricky to get right. Established libraries often have the benefit of community scrutiny and testing.

Combining the above approaches will allow you to securely send and verify ActivityPub messages in a Rails context, while also ensuring that the semantics of those messages are correctly understood.

0 comments on commit a20651b

Please sign in to comment.