首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >来自https://www.googleapis.com/oauth2/v4/token.的意外响应不给"access_token",只给"id_token“

来自https://www.googleapis.com/oauth2/v4/token.的意外响应不给"access_token",只给"id_token“
EN

Stack Overflow用户
提问于 2022-07-04 22:51:50
回答 1查看 131关注 0票数 1

我正在尝试获得一个访问令牌,这样我就可以使用。

看来这是我唯一能做到的办法。我使用的是Cloudflare工作人员,因为这需要在浏览器上运行,所以我认为一些库可以方便我无法使用的工作。

我在实习,给我这个任务的人给我寄了这份文件。

代码语言:javascript
运行
复制
{
  "type": "service_account",
  "project_id": "...",
  "private_key_id": "...",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMII...NF0=\n-----END PRIVATE KEY-----\n",
  "client_email": "...",
  "client_id": "...",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "..."
}

我已经可以使用该文件创建音频,方法是将文件的路径作为特定的环境变量,然后使用gcloud CLI工具打印访问令牌,然后使用它。但我不知道记号变了。

现在,我正在尝试使用JWT令牌。

这是我为测试JWT而创建的一个文件。

它创建JWT,但是当我执行POST请求以在响应中获取access_token时,我只得到id_token

代码语言:javascript
运行
复制
const jwt = require("jsonwebtoken");

const credentials = require("./credentials.json");

const corsHeaders = {
  "Content-Type": "application/json",
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Methods": "GET, HEAD, POST, OPTIONS",
  "Access-Control-Allow-Headers": "Authorization",
  "Access-Control-Allow-Credentials" : true,
}

async function main() {
  const JWTToken = jwt.sign({
    "iss": credentials.client_email,
    "sub": credentials.client_email,
    "scope": "https://texttospeech.googleapis.com/$discovery/rest?version=v1",
    //"aud": credentials.token_uri,
    "aud": "https://www.googleapis.com/oauth2/v4/token",
    "exp": Math.floor(+new Date() / 1000) + 60 * 45,
    "iat": Math.floor(+new Date() / 1000),
  }, credentials.private_key, {
    "algorithm": "RS256",
    "header": {
      "kid": credentials.private_key_id,
      "typ": "JWT",
      "alg": "RS256",
    }
  });

  const JWTBody = new URLSearchParams();

  JWTBody.append("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer");
  JWTBody.append("assertion", JWTToken);
  
  let JWTResponse;
  
  try {
    //JWTResponse = await fetch("https://oauth2.googleapis.com/token", {
    JWTResponse = await fetch("https://www.googleapis.com/oauth2/v4/token", {
      method: "POST",
      body: JWTBody,
    });
  } catch (e) {
    console.error(e);
    return new Response(`${e.name}: ${e.message}`, {
      status: 500,
      statusText: "Internal Server Error",
      headers: new Headers(corsHeaders),
    });
  }
  
  let JWTResponseBody;

  if (JWTResponse.ok) {
    JWTResponseBody = await JWTResponse.json();

    console.log("JWT", JWTResponseBody);
    console.log("JWT ACCESS_TOKEN", JWTResponseBody["access_token"]);
  } else {
    console.error("HTTP status code: ", JWTResponse.status, JWTResponse.statusText, JWTResponse);
  
    return new Response("HTTP status code: " + JWTResponse.status + JWTResponse.statusText, {
      status: 500,
      statusText: "Internal Server Error",
      headers: new Headers(corsHeaders),
    });
  }

  const TTSGoogleAPIsEndpoint = new URL("https://texttospeech.googleapis.com");
  const TTSRESTResources = {
    synthesize: new URL("/v1/text:synthesize", TTSGoogleAPIsEndpoint),
    list: new URL("/v1/voices", TTSGoogleAPIsEndpoint),
  };

  let response;

  try {
    response = await fetch(TTSRESTResources.synthesize, {
      method: "POST",
      headers: new Headers({
        "Authorization": `Bearer ${JWTResponseBody["access_token"]}`,
        "Content-Type": "application/json; charset=utf-8",
      }),
      body: JSON.stringify({
        "audioConfig": {
          "audioEncoding": "LINEAR16",
          "pitch": 0,
          "speakingRate": 1
        },
        "input": {
          "ssml": "<speak> <emphasis level=\"strong\">To be</emphasis> <break time=\"200ms\"/> or not to be? </speak>"
        },
        "voice": {
          "languageCode": "en-US",
          "name": "en-US-Standard-A"
        }
      }),
    });
  } catch (e) {
    console.error(e);
    return new Response(`${e.name}: ${e.message}`, {
      status: 500,
      statusText: "Internal Server Error",
      headers: new Headers(corsHeaders),
    });
  }

  if (response.ok) {
    const audio = await response.json();

    console.log(audio);
  } else {
    console.error("HTTP status code: ", response.status, response.statusText);
    console.log(response.headers.get("WWW-Authenticate"));

    return new Response("HTTP status code: " + response.status + response.statusText, {
      status: 500,
      statusText: "Internal Server Error",
      headers: new Headers(corsHeaders),
    });
  }
}

main();

当我运行代码时,它会打印如下:

代码语言:javascript
运行
复制
(node:53185) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
JWT {
  id_token: 'eyJh ... THE ID_TOKEN ... BSZw'
}
JWT ACCESS_TOKEN undefined
HTTP status code:  401 Unauthorized
Bearer realm="https://accounts.google.com/", error="invalid_token"

我已经在控制台上记录了JWTToken,并在邮递员上完成了邮件请求。它给出了相同的响应,只有id_token

我认为问题可能是JWT的有效负载内容,我不知道它的作用域是否正确,如果我需要使用https://www.googleapis.com/oauth2/v4/token URL或aud凭据中的范围。对于我需要用于fetch()的URL也是一样的。但我想我测试了所有的网址可能性,它从来没有给access_token

谢谢

解决方案

JWT有效负载上的作用域是错误的。它必须是"scope": "https://www.googleapis.com/auth/cloud-platform",

约翰·汉利回答。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-05 06:32:04

您的代码指定了一个不存在的OAuth作用域(格式完全错误)。

代码语言:javascript
运行
复制
async function main() {
  const JWTToken = jwt.sign({
    "iss": credentials.client_email,
    "sub": credentials.client_email,
    "scope": "https://www.googleapis.com/auth/cloud-platform",
    ...

URI https://www.googleapis.com/oauth2/v4/token是正确的。您还可以使用auth_urihttps://accounts.google.com/o/oauth2/auth中的值。

这将解决JWT访问令牌的问题。如果你有进一步的问题,文本到语音API,张贴一个新的问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72862609

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档