[英]EWS API to access Office365 with oAuth2
我們有一個守護程序應用程序,它使用 EWS API 通過基本身份驗證訪問 office365/Exchange 服務器。 我正在嘗試實施 Oauth2。 有很多文件。 但是,它們通常已經過時並引起了更多的混亂。 我遵循了這個文檔https://docs.microsoft.com/en-us/azure/active-directory/develop/scenario-daemon-overview ,它似乎是最新的。 我做了以下步驟:
注冊應用
文檔: https : //docs.microsoft.com/en-us/azure/active-directory/develop/scenario-daemon-app-registration - 在 Azure AD 中使用應用程序密碼注冊一個機密,即使用證書。 生成的秘密被記錄下來。 - 選擇“僅限此組織目錄中的帳戶”。
- 請求對 Exchange full_access_as_app 和 Mail.Read 的應用程序權限的 API 權限。 授予管理員同意。
獲取令牌
文檔: https : //docs.microsoft.com/en-us/azure/active-directory/develop/scenario-daemon-acquire-token?tabs=java我原型使用協議來獲取令牌
POST /{tenant}/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id={myAppClientId}
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret={myAppSecret}
&grant_type=client_credentials
我得到了令牌
{
"token_type": "Bearer",
"expires_in": 3599,
"ext_expires_in": 3599,
"access_token": "……thetoken…"
}
在我的應用程序中調用 EWS API
我的應用程序使用基本身份驗證。 我通過添加 Authorization 標頭(“Authorization”、“Bearer”+ accessToken)對其進行了修改; 基本上,prepareWebRequest() 函數是通過添加 Authorization 標頭來覆蓋的。 與基本身份驗證情況相比,請求具有額外的授權標頭和承載令牌。
對於基本授權已起作用的同一個 EWS API 調用,響應為 401,x-ms-diagnostics 2000003;reason="受眾聲明值對當前資源無效。受眾聲明是“ https://graph.microsoft。 com ',請求 url 是 ' https://outlook.office365.com/EWS/Exchange.asmx ',資源類型是 'Exchange'。";error_category="invalid_resource"
在 stackoverflow 中研究,人們建議使用以下作為范圍值來獲取第 2 步中的令牌: https://outlook.office365.com/full_access_as_app https://outlook.office.com/Mail.Read我試過,都返回了“ invalid_scope”錯誤。 似乎兩者以前都有效,但不再有效。 按照工作范圍值格式,我嘗試使用https://outlook.office.com/.default作為范圍值。 我能夠得到一個令牌! 但是,當我在 EWS API 中使用此令牌訪問郵箱時,我收到了 500 錯誤而不是 401。
應該怎樣做才能讓它發揮作用? 訪問 office365 郵箱的正確范圍是什么?
更多代碼片段
這是為 oauth2 添加的新類
package microsoft.exchange.webservices.data;
import java.util.Map;
public final class BearerTokenCredentials extends ExchangeCredentials {
private static final String BEARER_TOKEN_FORMAT_REGEX = "^[-._~+/A-Za-z0-9]+=*$";
private static final String AUTHORIZATION = "Authorization";
private static final String BEARER_AUTH_PREAMBLE = "Bearer ";
private String token;
public String getToken() {
return token;
}
public BearerTokenCredentials(String bearerToken) {
if (bearerToken == null) {
throw new IllegalArgumentException("Bearer token can not be null");
}
this.validateToken(bearerToken);
this.token = bearerToken;
}
protected void validateToken(String bearerToken) throws IllegalArgumentException {
if (!bearerToken.matches(BEARER_TOKEN_FORMAT_REGEX)) {
throw new IllegalArgumentException("Bearer token format is invalid.");
}
}
@Override
public void prepareWebRequest(HttpWebRequest request) {
Map<String, String> headersMap = request.getHeaders();
String bearerValue = BEARER_AUTH_PREAMBLE + token;
headersMap.put(AUTHORIZATION, bearerValue);
//headersMap.put("X-AnchorMailbox","esj_office365_imap@genesyslab.onmicrosoft.com");
request.setHeaders(headersMap);
}
}
使用令牌訪問 EWS/Exchange ews-java-api 2.0-patched
ExchangeService service = new
ExchangeService(ExchangeVersion.Exchange2010_SP2); //version is
Exchange2010_SP2
service.setTraceEnabled(true);
BearerTokenCredentials credentials = new BearerTokenCredentials("thetoken");
service.setCredentials(credentials);
service.setUrl(new
URI(host));//https://outloook.office365.com/EWS/Exchange.asmx
try{
Folder.bind(service, WellKnownFolderName.Inbox);
}catch(Exception e)
{
//The remote server returned an error: (500)Internal Server Error
}
您用於連接到 Office365 郵箱的代碼仍然需要使用 EWS Impersonation eg
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, mailboxName);
其中 MailboxName 是您要連接的郵箱。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.