Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

[v2] Incompatibility with refresh_tokens from Azure when client_id=resource_id

Abierto
#2,718 2 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@claude ya está trabajando en esto.

Desde el 26/8/2026.

  • #2720 de @claude — abierto
  • #2937 de @thegodshatetexas — abierto

Evaluación

Dificultad
3/5
Tiempo estimado
1-2 días
Aptitud para principiantes
72/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
typescript

Línea de trabajo

Comienza con la llamada a refreshAuthorization en el ejemplo repro.mjs proporcionado y sigue cómo se construye su solicitud de refresh. Ejecuta la reproducción contra Azure, compara los scopes de la solicitud inicial y de la solicitud de refresh, y verifica que el token de acceso actualizado funciona correctamente cuando client_id y resource_id coinciden.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

v2
What happened?

I have some MCP servers which require access_tokens from login.microsoftonline.com, and for which the OAuth client ID and the OAuth resource ID are the same Azure app.

All AI agent harnesses can successfully authenticate to these MCP servers initially, but several fail to fetch new access_tokens when they expire using the refresh_token.

This is because some MCP client libraries (including this one) don't handle the scope parameter when using a refresh_token in the way that Azure requires. This leads to the following misleading error message:

$ node repro.mjs "${my_tenantid}" "${my_clientid}" "api://${my_clientid}/access_as_user"
...
InvalidRequestError: AADSTS90009: Application 'REDACTED'(REDACTED) is requesting a token for it
self. This scenario is supported only if resource is specified using the GUID based App Identifier. Trace ID: REDACTED Correlation ID: REDACTED Timestamp: 2026-08-26 01:06:39Z

One way to fix this error actually has nothing to do with whether an app is requesting a token for itself or not - it is to pass along the same scope parameter with the refresh request as was used in the original request.

How's the support for other harnesses?

Other related issues:

What did you expect?

No response

Code to reproduce
import { randomUUID } from "node:crypto";
import http from "node:http";
import { exchangeAuthorization, refreshAuthorization, startAuthorization } from "@modelcontextprotocol/client";

const [tenant, clientId, apiScope] = process.argv.slice(2);
if (!tenant || !clientId || !apiScope) {
  console.error('Usage: node repro.mjs TENANT_ID CLIENT_ID "API_SCOPE"');
  process.exit(2);
}

const root = `https://login.microsoftonline.com/${tenant}/oauth2/v2.0`;
const redirectUri = "http://localhost:53682/callback";
const scope = `openid profile offline_access ${apiScope}`;
const clientInformation = { client_id: clientId };
const metadata = {
  authorization_endpoint: `${root}/authorize`,
  token_endpoint: `${root}/token`,
  response_types_supported: ["code"],
  code_challenge_methods_supported: ["S256"],
};
const state = randomUUID();
const { authorizationUrl, codeVerifier } = await startAuthorization(root, {
  metadata, clientInformation, redirectUrl: redirectUri, scope, state,
});

const authorizationCode = await new Promise((resolve, reject) => {
  const server = http.createServer((request, response) => {
    const url = new URL(request.url, redirectUri);
    if (url.pathname !== "/callback") return response.writeHead(404).end();
    const code = url.searchParams.get("code");
    const error = url.searchParams.get("error");
    const valid = url.searchParams.get("state") === state;
    response.end(valid && code ? "Authorization complete." : "Authorization failed.");
    server.close();
    if (error) reject(new Error(error));
    else if (!valid || !code) reject(new Error("Invalid OAuth callback"));
    else resolve(code);
  });
  server.once("error", reject);
  server.listen(53682, () => console.log(`Open this URL:\n\n${authorizationUrl}\n`));
});

const trace = (label) => async (url, init) => {
  const body = new URLSearchParams(init.body.toString());
  console.log(`${label}:`, { grant_type: body.get("grant_type"), scope: body.get("scope") ?? "<redacted>" });
  return fetch(url, init);
};
const initial = await exchangeAuthorization(root, {
  metadata, clientInformation, authorizationCode, codeVerifier, redirectUri,
  addClientAuthentication: async (_headers, body) => {
    body.set("client_id", clientId);
    body.set("scope", scope);
  },
  fetchFn: trace("initial request"),
});
if (!initial.refresh_token) throw new Error("No refresh token returned");
console.log("Initial access and refresh tokens received.");

const refreshed = await refreshAuthorization(root, {
  metadata, clientInformation, refreshToken: initial.refresh_token,
  fetchFn: trace("refresh request"),
});
console.log("Refreshed access token received:", !!refreshed.access_token);
SDK version

1.29.0 and also 2.0.0

Area

Auth

Lenguaje dominante
TypeScript
Estrellas
13.6k
Forks
2.3k
Merge medio
1 d 2 h
PR fusionados (30 d)
51

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de modelcontextprotocol/typescript-sdk

Todos los issues de modelcontextprotocol/typescript-sdk

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.