Outlook OAuth2访问邮件

时间:2015-08-20 14:42:11

标签: java email outlook oauth-2.0

我关注此帖:Outlook RestGettingStarted。从我的Java应用程序,我试图获得AccessToken和RefreshToken。当我发出授权代码请求时,它结束为以下错误:

  

很抱歉,但我们在登录时遇到了麻烦。我们收到了不好的消息   请求。

     

其他技术信息:相关ID:   ed838d66-5f2e-4cfb-9223-a29082ecb26f时间戳:2015-08-20 10:20:09Z   AADSTS90011:'资源'请求参数不受支持。

注意:根据文档说明网址格式正确。

所以,我删除了#34;资源"从我的代码查询参数。并重定向在浏览器中授权URL。在用户同意后,我获得了授权码。使用此代码我获得了AccessToken。但是,当我尝试连接Outlook IMAP服务器时,它失败了。 Java参考链接了解详细信息:Java OAuth2 但它给了我错误:

  

[AUTHENTICATIONFAILED] OAuth身份验证失败。

注意:我添加了正确的范围和用户电子邮件。

然后使用获得的访问令牌我进行了Mail Rest API调用以从用户收件箱中获取邮件。它结束了以下错误:

  

HTTP响应:   {"错误":{"代码":" MailboxNotEnabledForRESTAPI","消息":" REST API是   此邮箱尚不支持。"}}

任何人都可以帮助我关注:

  • 确切原因是什么:" AADSTS90011:'资源'请求参数不受支持"在遵循Outlook开发文档之后。

  • 如何解决" MailboxNotEnabledForRESTAPI"错误。

  • 是否可以使用正确的AccessToken使用java邮件API连接到Outlook IMAP服务器?

1 个答案:

答案 0 :(得分:0)

我最近碰到了这个,但不记得哪个解决了它。一个主要问题是在文档中它是变化的。它会告诉你附加" resource",但那是像Azure这样的东西。

以下是我使用的代码:

首先发送请求:

      private static final String USER_OAUTH2_AUTHORIZE_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";

      public String getOAuthDialog(Http.Request request) {
        return USER_OAUTH2_AUTHORIZE_URL
           + "?client_id=" + config.getClientId()
           + "&redirect_uri=" + getOutlookLoginRedirect(request)
           + "&response_type=code"
           + "&scope=https%3A%2F%2Foutlook.office.com%2Fmail.send%20" +
             "https%3A%2F%2Foutlook.office.com%2Fmail.readwrite%20" + 
             "offline_access%20openid%20email%20profile"
           + "&state=" + crypto.generateSignedToken();
       }

范围是最困难的事情。我找到了许多不起作用的。并且我不清楚我需要用空格分隔它们。

然后他们会向您发送一个请求到您提供的重定向网址。它将包含您需要交换的范围内所请求数据的代码。提供的重定向网址必须完全相同。您还需要在平台 - >添加平台 - >重定向URI->添加网址

下的应用程序门户上注册重定向网址
  private static final String USER_ACCESS_TOKEN_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
  private Map<String, String> sendOutlookUserOAuthRequest(Http.Request request, String code) {
    WSClient ws = WS.client();

    HttpParameters params = new HttpParameters();
    params.put("client_id", config.getClientId(), true);
    params.put("client_secret", config.getClientSecret(), true);
    params.put("code", code, true);
    params.put("redirect_uri", getOutlookLoginRedirect(request), true);
    params.put("grant_type", "authorization_code");
    String postParams = OAuthUtil.parametersToString(params);

    WSRequest wsRequest = ws.url(USER_ACCESS_TOKEN_URL)
        .setMethod("POST")
        .setContentType("application/x-www-form-urlencoded")
        .setBody(postParams);

    WSResponse wsResponse = wsRequest.execute().get(10, TimeUnit.SECONDS);

    Map<String, String> result = new HashMap<>();
    if (wsResponse.getStatus() != HttpStatus.SC_OK) {
      return result;
    }

    JsonNode node = wsResponse.asJson();
    if (node.hasNonNull("access_token")) {
      result.put("access_token", node.get("access_token").asText());
    }
    if (node.hasNonNull("refresh_token")) {
      result.put("refresh_token", node.get("refresh_token").asText());
    }

    if (node.hasNonNull("id_token")) {
      String[] tokenSplit = node.get("id_token").asText().split("\\.");
      if (tokenSplit.length >= 2) {
        try {
          JSONObject jsonObject = new JSONObject(new String(Base64.getDecoder().decode(tokenSplit[1])));
          if (jsonObject.has("name")) {
            result.put("name", jsonObject.get("name").toString());
          }
          if (jsonObject.has("email")) {
            result.put("outlookUid", jsonObject.get("email").toString());
          } else if (jsonObject.has("preferred_username")) {
            result.put("outlookUid", jsonObject.get("preferred_username").toString());
          }
        } catch (JSONException e) {
          log.error("Error extracting outlookUid from id_token: ", e);
        }
      }
    }

    return result;
  }

您可能需要的另一个请求是更新刷新令牌:

  private String getAccessTokenFromRefreshToken(User user) {

    WSClient ws = WS.client();
    HttpParameters params = new HttpParameters();
    params.put("client_id", config.getClientId(), true);
    params.put("client_secret", config.getClientSecret(), true);
    params.put("grant_type", "refresh_token");
    params.put("refresh_token", user.getOutlookRefreshToken());
    String postParams = OAuthUtil.parametersToString(params);

    WSRequest wsRequest = ws.url(USER_ACCESS_TOKEN_URL)
        .setMethod("POST")
        .setContentType("application/x-www-form-urlencoded")
        .setBody(postParams);

    WSResponse wsResponse = wsRequest.execute().get(10, TimeUnit.SECONDS);
    if (wsResponse.getStatus() != HttpStatus.SC_OK) {
      log.error("Failure to refresh outlook access token for user: " + user +
          ". Received status: " + wsResponse.getStatus() + " : " + wsResponse.getStatusText());
      return null;
    }
    JsonNode node = wsResponse.asJson();
    if (node.hasNonNull("access_token")) {
      String accessToken = node.get("access_token").asText();
      return accessToken;
    } else {
      log.error("Outlook refresh token failure, 'access_token' not present in response body: " + wsResponse.getBody());
      return null;
    }
  }

我遇到的一个问题花了比我希望的更长的时间来获取clientId和clientSecret。这是因为微软使用的语言并不是最明确的。客户端ID和应用程序ID可互换使用。客户端密钥也是您在Application Portal上创建的密码,不要与您可以生成的私钥混淆。

所以你实际上想要application_id和密码,尽管他们将它们称为client_id和client_secret,并没有直接指示绘制的线条。

这是假设您已在Outlook Application Portal上设置应用程序。 https://apps.dev.microsoft.com/

我希望这会有所帮助,虽然我认为你可能已经解决了这个问题。