【问题标题】:Invalid grant when authenticating to Google向 Google 进行身份验证时授权无效
【发布时间】:2023-03-26 16:41:02
【问题描述】:

我正在尝试连接到 Google Calendar API。我已经按照Google calendar quick start for Java中的步骤操作了

{ "error" : "invalid_grant", "error_description" : "错误请求" }

你能告诉我如何调试这个吗?不幸的是,错误消息没有帮助,我已经尝试了关于堆栈溢出或其他地方的这个特定错误的所有方法

每次我获得不同凭据的相同访问令牌时:

访问令牌:{user=Class{accessToken=null, refreshToken="" expirationTimeMilliseconds=null}}

代码:

public class CalendarServiceImpl implements CalendarService {

    public static final String APPLICATION_NAME = "GoogleCalenderApi";
    public static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
    public static final String TOKENS_DIRECTORY_PATH = "/data.json";
    public static final List<String> SCOPES = Collections.singletonList(CalendarScopes.CALENDAR);
    public static final String CREDENTIALS_FILE_PATH = "/data.json";

    public Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT, HttpServletRequest request)
            throws IOException {

        InputStream in = CalendarServiceImpl.class.getResourceAsStream(CREDENTIALS_FILE_PATH);

        if (in == null) {
            log.info("Resource not found: " + CREDENTIALS_FILE_PATH);
            throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
        }

        GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY,
                clientSecrets, SCOPES)
                        .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
                        .setAccessType("offline")
                        .build();

        System.out.println("Access token: " + flow.getCredentialDataStore());

        LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(80)
                .build();


        return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
    }

    public void createCalendarEvent(String candidateMailId, String companyEmailId, DateTime fromTime, DateTime toTime,
            String summary, String description, HttpServletRequest request)
            throws GeneralSecurityException, IOException {
        final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();

        Event event = new Event().setSummary(summary).setLocation("Test").setDescription(description);

        EventDateTime start = new EventDateTime().setDateTime(fromTime).setTimeZone("Asia/Kolkata");
        event.setStart(start);

        EventDateTime end = new EventDateTime().setDateTime(toTime).setTimeZone("Asia/Kolkata");
        event.setEnd(end);

        String[] recurrence = new String[] { "RRULE:FREQ=DAILY" };
        event.setRecurrence(Arrays.asList(recurrence));

        EventAttendee[] attendees = new EventAttendee[] { new EventAttendee().setEmail(candidateMailId),
                new EventAttendee().setEmail(companyEmailId) };
        event.setAttendees(Arrays.asList(attendees));

        EventReminder[] reminderOverrides = new EventReminder[] { new EventReminder().setMethod("email").setMinutes(10),
                new EventReminder().setMethod("popup").setMinutes(10), };
        Event.Reminders reminders = new Event.Reminders().setUseDefault(false)
                .setOverrides(Arrays.asList(reminderOverrides));
        event.setReminders(reminders);


        // Build service account credential.
        Credential credential = getCredentials(HTTP_TRANSPORT, request);
        log.info("got  credential:" + event);

        Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
                .setApplicationName(APPLICATION_NAME).build();


        String calendarId = "primary";
        try {
            System.out.printf("Event started" + event);
            event = service.events().insert(calendarId, event).setSendUpdates("all").execute();
        } catch (IOException e) {
            log.info("event  IOException:" + e);
            e.getMessage();
        }
        log.info("Event created:" + event.getHtmlLink());

    }

}

【问题讨论】:

  • 请编辑您的问题并包含您的代码,您使用的是 Java 还是 Curl 您的问题包含两者。
  • 如果您尝试manual HTTP POST request using CURL,则说明您没有遵循 Java 快速入门。您是否为您的请求提供访问令牌?
  • @Iamblichus :我正在为请求提供访问令牌链接:“token_uri”:“oauth2.googleapis.com/token”,
  • 请编辑您的问题并包含您的代码,如果没有看到您的代码,我们将无法帮助您。
  • @DaImTo 我正在使用 java。

标签: java google-api google-oauth google-calendar-api google-api-java-client


【解决方案1】:

您似乎正在使用 AuthorizationCodeInstalledApp,据统计它是用于已安装的应用程序。对于需要使用 AuthorizationCodeFlow 的 Web 应用程序。

官方例子可以在这里找到 Web server application

public class CalendarServletSample extends AbstractAuthorizationCodeServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
    // do stuff
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new GoogleAuthorizationCodeFlow.Builder(
        new NetHttpTransport(), JacksonFactory.getDefaultInstance(),
        "[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
        Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
        DATA_STORE_FACTORY).setAccessType("offline").build();
  }

  @Override
  protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
    // return user ID
  }
}

public class CalendarServletCallbackSample extends AbstractAuthorizationCodeCallbackServlet {

  @Override
  protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential)
      throws ServletException, IOException {
    resp.sendRedirect("/");
  }

  @Override
  protected void onError(
      HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse)
      throws ServletException, IOException {
    // handle error
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new GoogleAuthorizationCodeFlow.Builder(
        new NetHttpTransport(), JacksonFactory.getDefaultInstance()
        "[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
        Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
        DATA_STORE_FACTORY).setAccessType("offline").build();
  }

  @Override
  protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
    // return user ID
  }
}

AuthorizationCodeFlow 在运行代码的机器中打开同意浏览器窗口。当您将某些东西作为网站运行时,它需要在客户端计算机上打开,以便用户可以看到它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-29
    相关资源
    最近更新 更多