decolua/9router · error

token_endpoint must be a valid URL

Error message

token_endpoint must be a valid URL

What it means

After requiring a non-empty token_endpoint, the validator parses it with new URL(). Anything that isn't an absolute, well-formed URL (relative path, missing scheme, bad characters, bare hostname) throws this error.

Source

Thrown at src/lib/oauth/kiroExternalIdp.js:22

  "login.windows.net",
]);

const DEFAULT_REGION = "us-east-1";
const DEFAULT_EXPIRES_IN = 3600;

function normalizeString(value) {
  return typeof value === "string" ? value.trim() : "";
}

export function validateMicrosoftTokenEndpoint(rawEndpoint) {
  const tokenEndpoint = normalizeString(rawEndpoint);
  if (!tokenEndpoint) throw new Error("token_endpoint is required");

  let parsed;
  try {
    parsed = new URL(tokenEndpoint);
  } catch {
    throw new Error("token_endpoint must be a valid URL");
  }

  if (parsed.protocol !== "https:") {
    throw new Error("token_endpoint must use https");
  }

  const host = parsed.hostname.toLowerCase();
  if (!MICROSOFT_TOKEN_ENDPOINT_HOSTS.has(host)) {
    throw new Error("token_endpoint must be a Microsoft login endpoint");
  }

  return parsed.toString();
}

export function normalizeScope(scopes) {
  if (Array.isArray(scopes)) {
    return scopes.map(normalizeString).filter(Boolean).join(" ");
  }

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Prefix the scheme if missing: value.startsWith("https") ? value : `https://${value}` — but prefer storing the full absolute URL.
  2. Substitute tenant/placeholder values before validation; check for "{" "<" "$" remnants in the configured endpoint.
  3. Copy the token_endpoint verbatim from the IdP's openid-configuration document to guarantee it is absolute and correct.

Example fix

// before
validateMicrosoftTokenEndpoint("login.microsoftonline.com/common/oauth2/v2.0/token");
// after
validateMicrosoftTokenEndpoint("https://login.microsoftonline.com/common/oauth2/v2.0/token");
Defensive patterns

Strategy: validation

Validate before calling

function isAbsoluteHttpsUrl(u) {
  if (typeof u !== "string") return false;
  try { return new URL(u.trim()).protocol === "https:"; } catch { return false; }
}
if (!isAbsoluteHttpsUrl(raw)) throw new Error(`token_endpoint must be an absolute https URL, got: ${raw}`);

Type guard

function isUrl(x) {
  if (typeof x !== "string") return false;
  try { new URL(x); return true; } catch { return false; }
}

Try / catch

try {
  endpoint = validateMicrosoftTokenEndpoint(raw);
} catch (err) {
  if (err.message === "token_endpoint must be a valid URL") {
    throw new Error(`Configured token_endpoint "${raw}" is not an absolute URL — include the https:// scheme and substitute all placeholders`);
  }
  throw err;
}

Prevention

When it happens

Trigger: Passing "login.microsoftonline.com/.../token" (no scheme), "/oauth2/token" (relative), "https://{tenant}/token" (unparsed placeholder left in), or a value with spaces/control characters.

Common situations: Config template placeholder like ${TENANT} or <tenant-id> never substituted; user pasted the endpoint without the https:// prefix; shell/env quoting stripped part of the URL.

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/3d5a3f20a4072bf4. Report an issue: GitHub.