fix(client/sse): extract protected resource from eventsource 401

Previously the SSE connection would always default to the
`/.well-known/oauth-protected-resource` URI, ignoring the `resource_metadata`
portion of the `www-authenticate` returned in a 401.

Extract the metadata from the initial 401, so RS servers with
custom protected resource URIs (as in RFC9728, [section 3.1][1]))
continue to work as expected.

[1]: https://datatracker.ietf.org/doc/html/rfc9728#section-3.1
This commit is contained in:
Chris Dickinson 2025-06-20 12:54:29 -07:00
commit d89e854133
No known key found for this signature in database

View file

@ -117,23 +117,35 @@ export class SSEClientTransport implements Transport {
}
private _startOrAuth(): Promise<void> {
const fetchImpl = (this?._eventSourceInit?.fetch || fetch) as typeof fetch
return new Promise((resolve, reject) => {
this._eventSource = new EventSource(
this._url.href,
this._eventSourceInit ?? {
fetch: (url, init) => this._commonHeaders().then((headers) => fetch(url, {
...init,
headers: {
...headers,
Accept: "text/event-stream"
{
...this._eventSourceInit,
fetch: async (url, init) => {
const headers = await this._commonHeaders()
const response = await fetchImpl(url, {
...init,
headers: new Headers({
...headers,
Accept: "text/event-stream"
})
})
if (response.status === 401 && response.headers.has('www-authenticate')) {
this._resourceMetadataUrl = extractResourceMetadataUrl(response);
}
})),
return response
},
},
);
this._abortController = new AbortController();
this._eventSource.onerror = (event) => {
if (event.code === 401 && this._authProvider) {
this._authThenStart().then(resolve, reject);
return;
}