Skip to content

Authenticated GET on a container returns Turtle body with application/ld+json content-type, ignoring Accept #325

Description

@melvincarvalho

Summary

With --conneg enabled, an authenticated GET on a container returns a Turtle body but labels the response Content-Type: application/ld+json, regardless of the requested Accept. The same request without auth correctly returns JSON-LD. This breaks any client that trusts either the Accept negotiation or the Content-Type header (which is most of them).

Repro

Server:

JSS_SINGLE_USER_PASSWORD=hunter2 jss start --port 4443 --root ~/main --single-user --idp --conneg

Get a token:

TOKEN=$(curl -s -X POST http://localhost:4443/idp/credentials \
  -H "Content-Type: application/json" \
  -d '{"username":"me","password":"hunter2"}' | jq -r .access_token)

Without auth — JSON-LD body, JSON-LD content-type ✓

$ curl -sI -H "Accept: application/ld+json, text/turtle;q=0.5" http://localhost:4443/me/profile/card.jsonld | grep -i content-type
content-type: application/ld+json; charset=utf-8

$ curl -s -H "Accept: application/ld+json, text/turtle;q=0.5" http://localhost:4443/me/ | head -3
{
  "@context": {
    "ldp": "http://www.w3.org/ns/ldp#",

With auth — Turtle body, JSON-LD content-type

$ curl -sI -H "Authorization: Bearer $TOKEN" -H "Accept: application/ld+json, text/turtle;q=0.5" http://localhost:4443/me/ | grep -i content-type
content-type: application/ld+json

$ curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/ld+json, text/turtle;q=0.5" http://localhost:4443/me/ | head -3
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.

The body is plainly Turtle, the header says JSON-LD. Even when I request Accept: application/ld+json explicitly (no Turtle in the Accept at all), the auth path still serves Turtle.

Expected

Either:

  • Body matches Accept — auth path honors the same q-weighted negotiation as the anonymous path. Default to JSON-LD (the documented native format) when client prefers it.
  • Header matches body — at minimum, the Content-Type label should reflect what's actually in the body.

Probably both. JSON-LD is JSS's native format; Turtle should only come back when the client asks for it.

Why it matters

Clients that do if (contentType.includes('json')) JSON.parse(body) get a parse error on perfectly conformant requests. The mislabel is the worst part — a sniff (e.g. "first non-whitespace char is { or @") can route around it, but every consumer shouldn't have to.

Environment

  • jss 0.0.155 (latest published)
  • node v24.5.0
  • Linux x86_64

Likely a divergence between two response paths inside the auth middleware vs. the anonymous handler. Happy to look at the conneg layer if you want a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions