Skip to content

NoxManga: Fix 401 by signing API requests - #18482

Merged
AwkwardPeak7 merged 2 commits into
keiyoushi:mainfrom
Biglongs1:noxmanga-signed-requests
Aug 19, 2026
Merged

NoxManga: Fix 401 by signing API requests#18482
AwkwardPeak7 merged 2 commits into
keiyoushi:mainfrom
Biglongs1:noxmanga-signed-requests

Conversation

@Biglongs1

Copy link
Copy Markdown
Contributor

Closes #17907

The source moved from noxtoons.com to noxmangas.org and its API moved from xodneo.site to /api/v1 on the site's own domain. That API now rejects unsigned requests with 401 {"error":"Assinatura de requisição obrigatória"}, which is what users are hitting.

The site loads /_nix/signer.js, which carries the current slot, a rotating token and the secret used to sign each path. SignatureInterceptor parses that script and signs every API call with base64url(SHA-256("METHOD|path|siteId|slot|token|key")), sending X-Site-ID, X-Web-Slot, X-Web-Token and X-Web-Signature, and re-fetching the signer on a 401.

Two details worth knowing for future maintenance:

  • Sec-Fetch-Site is required. Without it the server falls back to a different scheme and asks for X-Signature + X-Timestamp instead.
  • The token is bound to the User-Agent, so the signer request and the API request have to go through the same client/headers.

Other changes:

  • Migrated to KeiSource.
  • Rate limiting is now scoped to /api/. It previously applied to every request, and since the chapter images are served from the same host (/ii/...), a 120 page chapter had a ~40s floor of artificial waiting.
  • Filters for sort, type, status, demographic and content, plus genres fetched from /api/v1/genres.
  • contentWarning set to MIXED (the site has an adult section alongside regular content).
  • Chapter URLs keep the old /ler/ key so existing reading history is preserved, while getChapterUrl points to the site's new /read/ reader.

Tested on an emulator with Mihon: popular, latest, text search, URL search, filters, details, chapter list and reading pages.

Checklist:

  • Updated versionCode value in build.gradle.kts
  • Updated baseVersionCode in build.gradle.kts (if updated multisrc theme code)
  • Referenced all related issues in the PR body (e.g. "Closes #xyz")
  • Set the contentWarning configuration in build.gradle.kts appropriately
  • Have not changed source names
  • Have explicitly kept the id if a source's name or language were changed
  • Have tested the modifications by compiling and running the extension through Android Studio
  • Have removed web_hi_res_512.png when adding a new extension
  • This PR is AI-assisted, I have reviewed the changes manually and confirmed they are not slop

The source moved to noxmangas.org and its API now rejects unsigned requests. Adds an interceptor that derives the slot, token and secret from the site signer script and signs every API call, refreshing it on 401. Also migrates the source to KeiSource.
?.let { append(" - ", it) }
}
chapter_number = number
date_upload = publishedAt?.let(Instant::parseOrNull)?.toEpochMilliseconds() ?: 0L

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use Instant.tryParse

}
chapter_number = number
date_upload = publishedAt?.let(Instant::parseOrNull)?.toEpochMilliseconds() ?: 0L
memo = buildJsonObject { put("id", id) }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if id is unique, perhaps set id in url and rest of needed data in memo

import java.io.IOException
import java.security.MessageDigest

class SignatureInterceptor(private val baseUrl: String) : Interceptor {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make this a lambda so baseurl is always captured from source.baseUrl

Use Instant.tryParse, store the chapter id in the url with the rest in memo, and take the base url as a lambda in the interceptor.
@AwkwardPeak7
AwkwardPeak7 merged commit 829cbe0 into keiyoushi:main Aug 19, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error 401 on NoxManga

2 participants