fix: bridge IndieAuth token into Mastodon OAuth for media uploads

Store the IndieAuth session token (req.session.access_token) on the
OAuth authorization code document during POST /oauth/authorize. This
token persists through the code→token exchange and is available as
req.mastodonToken.indieauthToken when Mastodon clients make API calls.

Media upload routes now use this bridged token to call the Micropub
media endpoint, which requires IndieAuth authentication.
This commit is contained in:
Ricardo
2026-03-29 17:15:50 +02:00
parent 4c5b6032c1
commit 33ae574b3e
4 changed files with 18 additions and 5 deletions
+12 -2
View File
@@ -98,8 +98,13 @@ router.post(
try { try {
const { application } = req.app.locals; const { application } = req.app.locals;
const collections = req.app.locals.mastodonCollections; const collections = req.app.locals.mastodonCollections;
// Use IndieAuth token stored during OAuth authorization, falling back
// to session token (native reader) or Mastodon token (won't work for
// Micropub media endpoint but covers direct internal calls).
const token = const token =
req.session?.access_token || req.mastodonToken?.accessToken; req.session?.access_token ||
req.mastodonToken?.indieauthToken ||
req.mastodonToken?.accessToken;
const file = req.files?.file; const file = req.files?.file;
if (!file) { if (!file) {
@@ -142,8 +147,13 @@ router.post(
try { try {
const { application } = req.app.locals; const { application } = req.app.locals;
const collections = req.app.locals.mastodonCollections; const collections = req.app.locals.mastodonCollections;
// Use IndieAuth token stored during OAuth authorization, falling back
// to session token (native reader) or Mastodon token (won't work for
// Micropub media endpoint but covers direct internal calls).
const token = const token =
req.session?.access_token || req.mastodonToken?.accessToken; req.session?.access_token ||
req.mastodonToken?.indieauthToken ||
req.mastodonToken?.accessToken;
const file = req.files?.file; const file = req.files?.file;
if (!file) { if (!file) {
+3
View File
@@ -388,6 +388,9 @@ router.post("/oauth/authorize", async (req, res, next) => {
redirectUri: redirect_uri, redirectUri: redirect_uri,
codeChallenge: code_challenge || null, codeChallenge: code_challenge || null,
codeChallengeMethod: code_challenge_method || null, codeChallengeMethod: code_challenge_method || null,
// Store the IndieAuth session token so Mastodon API routes can call
// Micropub/media endpoints on behalf of this user (single-user server).
indieauthToken: req.session?.access_token || null,
createdAt: new Date(), createdAt: new Date(),
expiresAt: new Date(Date.now() + 10 * 60 * 1000), // 10 minutes expiresAt: new Date(Date.now() + 10 * 60 * 1000), // 10 minutes
}); });
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "@rmdes/indiekit-endpoint-activitypub", "name": "@rmdes/indiekit-endpoint-activitypub",
"version": "3.11.3", "version": "3.11.4",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@rmdes/indiekit-endpoint-activitypub", "name": "@rmdes/indiekit-endpoint-activitypub",
"version": "3.11.3", "version": "3.11.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@fedify/debugger": "^2.1.0", "@fedify/debugger": "^2.1.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@rmdes/indiekit-endpoint-activitypub", "name": "@rmdes/indiekit-endpoint-activitypub",
"version": "3.11.3", "version": "3.11.4",
"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",