{"record":{"id":"5aaec42a53eb2700","repo":"usebruno/bruno","slug":"access-token-url-is-required-for-oauth2-password-c","errorCode":null,"errorMessage":"Access Token URL is required for OAuth2 password credentials flow","messagePattern":"Access Token URL is required for OAuth2 password credentials flow","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/bruno-requests/src/auth/oauth2-helper.ts","lineNumber":215,"sourceCode":"};\n\n/**\n * Fetches an OAuth2 token using password grant\n */\nconst fetchTokenPassword = async (oauth2Config: OAuth2Config, axiosInstance?: AxiosInstance) => {\n  const {\n    accessTokenUrl,\n    clientId,\n    clientSecret,\n    username,\n    password,\n    scope,\n    credentialsPlacement = 'basic_auth_header',\n    additionalParameters\n  } = oauth2Config;\n\n  if (!accessTokenUrl) {\n    throw new Error('Access Token URL is required for OAuth2 password credentials flow');\n  }\n\n  if (!username) {\n    throw new Error('Username is required for OAuth2 password credentials flow');\n  }\n\n  if (!password) {\n    throw new Error('Password is required for OAuth2 password credentials flow');\n  }\n\n  if (!clientId) {\n    throw new Error('Client ID is required for OAuth2 password credentials flow');\n  }\n\n  const requestConfig: RequestConfig = {\n    method: 'POST',\n    url: accessTokenUrl,\n    headers: {","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/usebruno/bruno/blob/9bdd81c7bdc57006e5f5ebffb79321a8d979f712/packages/bruno-requests/src/auth/oauth2-helper.ts#L197-L233","documentation":"Thrown by fetchTokenPassword at the start of the resource-owner password grant when accessTokenUrl is missing. The password grant still requires a token endpoint to exchange username/password for a token, so the helper aborts before constructing the POST.","triggerScenarios":"getOAuth2AccessToken invoked with grantType='password' but accessTokenUrl empty/undefined. Often happens when the same config object is reused from a client_credentials setup that never set the URL.","commonSituations":"Switching grant types in a shared config without re-filling the token URL; the token URL field cleared during a migration; env var missing in a staging environment.","solutions":["Set accessTokenUrl on the config before calling the password flow.","Verify the URL is a valid absolute HTTPS endpoint accepted by the authorization server.","Validate the whole config shape up front (see validationCode) to catch this and the username/password/clientId checks at once."],"exampleFix":"// before\nconst config = { grantType: 'password', username: user, password: pass, clientId: id };\n\n// after\nconst config = {\n  grantType: 'password',\n  accessTokenUrl: 'https://auth.example.com/oauth/token',\n  username: user,\n  password: pass,\n  clientId: id\n};","handlingStrategy":"validation","validationCode":"function validatePasswordConfig(c) {\n  if (!c.accessTokenUrl) throw new Error('accessTokenUrl missing for password flow');\n  if (!c.username) throw new Error('username missing');\n  if (!c.password) throw new Error('password missing');\n  if (!c.clientId) throw new Error('clientId missing');\n}\nvalidatePasswordConfig(config);","typeGuard":"function isPasswordGrantReady(c) {\n  return c.grantType === 'password'\n    && typeof c.accessTokenUrl === 'string' && c.accessTokenUrl.length > 0\n    && typeof c.username === 'string' && !!c.password && typeof c.clientId === 'string';\n}","tryCatchPattern":"try { await getOAuth2AccessToken(config, tokenStore); }\ncatch (e) { if (e.message.includes('password credentials flow')) { /* surface to user */ } else throw e; }","preventionTips":["Validate the full password-grant config in one place before invoking the helper.","Do not reuse a client_credentials config object for the password flow without re-checking fields.","Unit-test the validator against configs missing each individual field."],"tags":["oauth2","validation","configuration","password-grant"],"backgroundTag":null,"analyzedSha":"9bdd81c7bdc57006e5f5ebffb79321a8d979f712","analyzedAt":"2026-08-13T04:09:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}