mirror of
https://github.com/svemagie/indiekit-endpoint-activitypub.git
synced 2026-04-02 15:44:58 +02:00
feat: add remote follow / authorize interaction support
Add OStatus subscribe template to WebFinger responses so remote servers (WordPress AP, Misskey, etc.) can discover and redirect users to complete follow interactions. Unauthenticated users are sent to login first, then redirected to the existing reader profile page with follow/unfollow UI.
This commit is contained in:
5
index.js
5
index.js
@@ -60,6 +60,7 @@ import {
|
|||||||
} from "./lib/controllers/featured-tags.js";
|
} from "./lib/controllers/featured-tags.js";
|
||||||
import { resolveController } from "./lib/controllers/resolve.js";
|
import { resolveController } from "./lib/controllers/resolve.js";
|
||||||
import { publicProfileController } from "./lib/controllers/public-profile.js";
|
import { publicProfileController } from "./lib/controllers/public-profile.js";
|
||||||
|
import { authorizeInteractionController } from "./lib/controllers/authorize-interaction.js";
|
||||||
import { myProfileController } from "./lib/controllers/my-profile.js";
|
import { myProfileController } from "./lib/controllers/my-profile.js";
|
||||||
import { noteObjectController } from "./lib/controllers/note-object.js";
|
import { noteObjectController } from "./lib/controllers/note-object.js";
|
||||||
import {
|
import {
|
||||||
@@ -173,6 +174,10 @@ export default class ActivityPubEndpoint {
|
|||||||
// dereference the Note ID during Create activity verification.
|
// dereference the Note ID during Create activity verification.
|
||||||
router.get("/quick-replies/:id", noteObjectController(self));
|
router.get("/quick-replies/:id", noteObjectController(self));
|
||||||
|
|
||||||
|
// Authorize interaction — remote follow / subscribe endpoint.
|
||||||
|
// Remote servers redirect users here via the WebFinger subscribe template.
|
||||||
|
router.get("/authorize_interaction", authorizeInteractionController(self));
|
||||||
|
|
||||||
// HTML fallback for actor URL — serve a public profile page.
|
// HTML fallback for actor URL — serve a public profile page.
|
||||||
// Fedify only serves JSON-LD; browsers get 406 and fall through here.
|
// Fedify only serves JSON-LD; browsers get 406 and fall through here.
|
||||||
router.get("/users/:identifier", publicProfileController(self));
|
router.get("/users/:identifier", publicProfileController(self));
|
||||||
|
|||||||
45
lib/controllers/authorize-interaction.js
Normal file
45
lib/controllers/authorize-interaction.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Authorize Interaction controller — handles the remote follow / authorize
|
||||||
|
* interaction flow for ActivityPub federation.
|
||||||
|
*
|
||||||
|
* When a remote server (WordPress AP, Misskey, etc.) discovers our WebFinger
|
||||||
|
* subscribe template, it redirects the user here with ?uri={actorOrPostUrl}.
|
||||||
|
*
|
||||||
|
* Flow:
|
||||||
|
* 1. Missing uri → render error page
|
||||||
|
* 2. Unauthenticated → redirect to login, then back here
|
||||||
|
* 3. Authenticated → redirect to the reader's remote profile page
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function authorizeInteractionController(plugin) {
|
||||||
|
return async (req, res) => {
|
||||||
|
const uri = req.query.uri || req.query.acct;
|
||||||
|
if (!uri) {
|
||||||
|
return res.status(400).render("activitypub-authorize-interaction", {
|
||||||
|
title: "Authorize Interaction",
|
||||||
|
mountPath: plugin.options.mountPath,
|
||||||
|
error: "Missing uri parameter",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up acct: prefix if present
|
||||||
|
const resource = uri.replace(/^acct:/, "");
|
||||||
|
|
||||||
|
// Check authentication — if not logged in, redirect to login
|
||||||
|
// then back to this page after auth
|
||||||
|
const session = req.session;
|
||||||
|
if (!session?.access_token) {
|
||||||
|
const returnUrl = `${plugin.options.mountPath}/authorize_interaction?uri=${encodeURIComponent(uri)}`;
|
||||||
|
return res.redirect(
|
||||||
|
`/session/login?redirect=${encodeURIComponent(returnUrl)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authenticated — redirect to the remote profile viewer in our reader
|
||||||
|
// which already has follow/unfollow/like/boost functionality
|
||||||
|
const encodedUrl = encodeURIComponent(resource);
|
||||||
|
return res.redirect(
|
||||||
|
`${plugin.options.mountPath}/admin/reader/profile?url=${encodedUrl}`,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -262,6 +262,18 @@ export function setupFederation(options) {
|
|||||||
// instance actor's keys for outgoing fetches), which Fedify doesn't yet
|
// instance actor's keys for outgoing fetches), which Fedify doesn't yet
|
||||||
// support out of the box. Re-enable once Fedify adds this capability.
|
// support out of the box. Re-enable once Fedify adds this capability.
|
||||||
|
|
||||||
|
// --- WebFinger custom links ---
|
||||||
|
// Add OStatus subscribe template so remote servers (WordPress AP, Misskey, etc.)
|
||||||
|
// can redirect users to our authorize_interaction page for remote follow.
|
||||||
|
federation.setWebFingerLinksDispatcher((_ctx, _resource) => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
rel: "http://ostatus.org/schema/1.0/subscribe",
|
||||||
|
template: `${publicationUrl}${mountPath.replace(/^\//, "")}/authorize_interaction?uri={uri}`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
// --- Inbox listeners ---
|
// --- Inbox listeners ---
|
||||||
const inboxChain = federation.setInboxListeners(
|
const inboxChain = federation.setInboxListeners(
|
||||||
`${mountPath}/users/{identifier}/inbox`,
|
`${mountPath}/users/{identifier}/inbox`,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@rmdes/indiekit-endpoint-activitypub",
|
"name": "@rmdes/indiekit-endpoint-activitypub",
|
||||||
"version": "2.0.24",
|
"version": "2.0.25",
|
||||||
"description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
|
"description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"indiekit",
|
"indiekit",
|
||||||
|
|||||||
10
views/activitypub-authorize-interaction.njk
Normal file
10
views/activitypub-authorize-interaction.njk
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{% extends "document.njk" %}
|
||||||
|
|
||||||
|
{% from "prose/macro.njk" import prose with context %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% if error %}
|
||||||
|
{{ prose({ text: error }) }}
|
||||||
|
{% endif %}
|
||||||
|
<p><a href="{{ mountPath }}/">Return to dashboard</a></p>
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user