2015-08-20 63 views
0

我关注此帖:Outlook RestGettingStarted。从我的Java应用程序中,我试图获取AccessToken和RefreshToken。当我提出的授权码请求,它结束到以下错误:展望OAuth2访问邮件

Sorry, but we’re having trouble signing you in. We received a bad request.

Additional technical information: Correlation ID: ed838d66-5f2e-4cfb-9223-a29082ecb26f Timestamp: 2015-08-20 10:20:09Z AADSTS90011: The 'resource' request parameter is not supported.

注: URL形成是按文件正确。

所以,我从我的代码中删除了“资源”查询参数。并在浏览器中重定向授权网址。在用户同意书上我获得了授权代码。使用这段代码我得到了AccessToken。但是当我尝试与Outlook IMAP服务器连接时,它失败了。 Java的参考链接了解详细信息:Java OAuth2 但它给我的错误:

[AUTHENTICATIONFAILED] OAuth authentication failed.

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

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

HTTP response: {"error":{"code":"MailboxNotEnabledForRESTAPI","message":"REST API is not yet supported for this mailbox."}}

谁能帮我下:

  • 什么是确切的原因:“AADSTS90011:在‘资源’的请求参数不支持”下面的Outlook后dev文档。

  • 如何解决“MailboxNotEnabledForRESTAPI”错误。

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

回答

0

我最近碰到过这个,但是不记得哪个解决了它。文档中的一个主要问题在于它有所不同。它会告诉你附加“资源”,但这是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(); 
     } 

范围是找出最困难的事情。我发现很多不起作用的。而且我不清楚是否需要用空格将它们分开。

然后他们会向您发送一个请求给您提供的重定向网址。它将包含一个代码,您需要在范围中交换您请求的数据。提供的重定向网址需要完全相同。你也需要注册的平台 - 在你的应用程序门户网站重定向URL>添加平台 - >重定向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_id和密码,虽然他们把它们称为client_id和client_secret,并没有直接指示绘制的线条。

这都假设您已经在Outlook应用程序门户上设置了一个应用程序。 https://apps.dev.microsoft.com/

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