Skip to content

fix(auth): serve /.well-known/jwks.json past the .json rewrite; drop dead v1 .json routes - #684

Merged
ryceg merged 1 commit into
mainfrom
fix/wellknown-jwks-json
Aug 12, 2026
Merged

fix(auth): serve /.well-known/jwks.json past the .json rewrite; drop dead v1 .json routes#684
ryceg merged 1 commit into
mainfrom
fix/wellknown-jwks-json

Conversation

@ryceg

@ryceg ryceg commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Problem

JsonExtensionMiddleware strips any .json suffix before routing (legacy Nightscout content-negotiation), exempting only /openapi. /.well-known/jwks.json — the exact URL both discovery documents advertise as jwks_uri — was therefore rewritten to /.well-known/jwks, which matches no endpoint. A relying party fetching our JWKS got a 401 (no endpoint metadata, so [AllowAnonymous] never applied).

The same rewrite made three v1 .json route templates unreachable dead code that also published duplicate OpenAPI operations: DeviceStatusController.GetDeviceStatusJson, FoodController.GetFoodJson, StatusController.GetStatusJson. All three were pure delegations to their stripped siblings, so removing them changes no behaviour (status.json responses still go through GetStatus, which returns JSON when the middleware forces the Accept header).

Fix

  • The /openapi special case becomes a LiteralJsonPrefixes exemption list covering /openapi and /.well-known.
  • The three vestigial v1 actions are deleted, along with a test that invoked one of them directly (a line-for-line duplicate of the sibling's test).

Tests

New WellKnownControllerTests: a theory over both discovery documents that reads the advertised jwks_uri out of the served document, GETs that exact URL, and asserts the key set comes back. Both cases fail (401) without the middleware exemption — verified by reverting once.

Full unit suite: 5142 passed / 0 failed. The v1 parity/golden tests covering status.json et al. request the URLs, not the actions, and stay green.

Noted while here (not in this PR)

The discovery documents serialize with MVC's default camelCase policy, emitting jwksUri/authorizationEndpoint instead of the spec-mandated jwks_uri/authorization_endpoint. A strict OIDC relying party won't find the fields. The new test reads the property name-agnostically so it doesn't pin that as correct.

Follow-up from #651.

https://claude.ai/code/session_01NwnN3ND2eSXKAxJteNWSXb

JsonExtensionMiddleware strips a .json suffix from every path outside
/openapi before routing, so the jwks_uri both discovery documents
advertise never reached WellKnownController and relying parties could not
fetch the key set. Exempt /.well-known alongside /openapi.

The same rewrite made the v1 devicestatus.json, food.json and status.json
route declarations unreachable; they only ever delegated to their stripped
siblings, so drop them and the OpenAPI operations they published for paths
that do not exist.

Claude-Session: https://claude.ai/code/session_01NwnN3ND2eSXKAxJteNWSXb
@github-actions

Copy link
Copy Markdown
Contributor

Preview Container Images

Published for commit 3a13971 with tag pr-684-3a13971.

Image Status Package URI
nocturne-api ✅ Published package ghcr.io/nightscout/nocturne/nocturne-api:pr-684-3a13971
nocturne-demo ✅ Published package ghcr.io/nightscout/nocturne/nocturne-demo:pr-684-3a13971
nocturne-web ✅ Published package ghcr.io/nightscout/nocturne/nocturne-web:pr-684-3a13971

This comment is updated on each push to this PR.

@ryceg
ryceg merged commit 152c0ee into main Aug 12, 2026
16 checks passed
@ryceg
ryceg deleted the fix/wellknown-jwks-json branch August 12, 2026 11:58
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.

1 participant