ews-java-api
ews-java-api copied to clipboard
How to Authenticate an EWS application by using OAuth?
https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth How to Authenticate an EWS application by using OAuth in Java? Thanks
`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);
request.setHeaders(headersMap);
}
}`
` String email = "emailaddressxx"; ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2); service.setTraceEnabled(true); BearerTokenCredentials credentials = new BearerTokenCredentials(MsEwsTokenProvider.getAccesToken()); service.setCredentials(credentials); service.setUrl(new URI("https://" + "outlook.office365.com" + "/EWS/Exchange.asmx")); service.setImpersonatedUserId(new ImpersonatedUserId(ConnectingIdType.SmtpAddress, email));
// Bind to the Inbox.
Folder inbox = Folder.bind(service, WellKnownFolderName.Inbox);
int count = inbox.getTotalCount();
System.out.println(inbox.getDisplayName());
ItemView itemView = new ItemView(count);
//
FindItemsResults<Item> findResults = service.findItems(inbox.getId(), itemView);
ArrayList<Item> items = findResults.getItems();
for (int i = 0; i < items.size(); i++) {
EmailMessage message = EmailMessage.bind(service, items.get(i).getId());
message.load();
System.out.println(message.getSender());
}
But return 401
Exception in thread "main" microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRequestException: The request failed. The request failed. The remote server returned an error: (401)Unauthorized
at microsoft.exchange.webservices.data.core.request.SimpleServiceRequestBase.internalExecute(SimpleServiceRequestBase.java:74)
at microsoft.exchange.webservices.data.core.request.MultiResponseServiceRequest.execute(MultiResponseServiceRequest.java:158)
at microsoft.exchange.webservices.data.core.ExchangeService.bindToFolder(ExchangeService.java:504)
at microsoft.exchange.webservices.data.core.ExchangeService.bindToFolder(ExchangeService.java:523)
at microsoft.exchange.webservices.data.core.service.folder.Folder.bind(Folder.java:98)
at microsoft.exchange.webservices.data.core.service.folder.Folder.bind(Folder.java:147)
at ReadExchangeMail.main(ReadExchangeMail.java:64)
Caused by: microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRequestException: The request failed. The remote server returned an error: (401)Unauthorized
at microsoft.exchange.webservices.data.core.request.ServiceRequestBase.validateAndEmitRequest(ServiceRequestBase.java:644)
at microsoft.exchange.webservices.data.core.request.SimpleServiceRequestBase.internalExecute(SimpleServiceRequestBase.java:62)
... 6 more
Caused by: microsoft.exchange.webservices.data.core.exception.http.HttpErrorException: The remote server returned an error: (401)Unauthorized
at microsoft.exchange.webservices.data.core.request.ServiceRequestBase.getEwsHttpWebResponse(ServiceRequestBase.java:723)
at microsoft.exchange.webservices.data.core.request.ServiceRequestBase.validateAndEmitRequest(ServiceRequestBase.java:639)
... 7 more`
Can you show us MsEwsTokenProvider.java? By the way use triple back ticks for blocks of code (not single back ticks).
`public final class MsEwsTokenProvider {
private static final String EWS_URL = "https://outlook.office365.com/EWS/Exchange.asmx";
private static String scope = "https://outlook.office.com/.default";
private static String clientId = "xxxxx";
private static String secret = "xxxxx";
private static String authority = "https://login.microsoftonline.com/xxxxx/";
public static String getAccesToken() throws Exception {
ConfidentialClientApplication app = ConfidentialClientApplication.builder(
clientId,
ClientCredentialFactory.createFromSecret(secret))
.authority(authority)
.build();
// With client credentials flows the scope is ALWAYS of the shape "resource/.default", as the
// application permissions need to be set statically (in the portal), and then granted by a tenant administrator
ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(
Collections.singleton(scope))
.build();
CompletableFuture<IAuthenticationResult> future = app.acquireToken(clientCredentialParam);
System.out.println(future.get().accessToken());
return future.get().accessToken();
}`
I can got the token,but can not get the mail inbox. Thanks
Yeah but if you are getting a 401 it means that the token doesn't authenticate you. I guess it could be a permission problem and the service is giving you a 401 instead of the appropriate 403.
Triple ticks please, formatting gets stuffed up.
https://docs.github.com/en/github/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#quoting-code
@davidmoten @Chandler54321
Any idea how to resolve it tho?
On the EWS docs, theres two types of Authentication, Delegated and App only Where delegated uses specific permissions but I keep getting a 401 unauthorised, but Authentication via Application Auth works 100%
@Chandler54321 I notice that our code (that works fine) does this step:
service.setImpersonatedUserId(new ImpersonatedUserId(ConnectingIdType.PrincipalName, email));
You might want to try that instead of your line:
service.setImpersonatedUserId(new ImpersonatedUserId(ConnectingIdType.SmtpAddress, email));
BearerTokenCredentials credentials = new BearerTokenCredentials(MsEwsTokenProvider.getAccesToken()); service.setCredentials(credentials); I am getting setCredentials is not applicable for BearerTokenCredentials .kindly help me out. Thanks in Advance!
You answer is quite helpful to me, Thanks a lot.
BearerTokenCredentials credentials = new BearerTokenCredentials(MsEwsTokenProvider.getAccesToken()); service.setCredentials(credentials); I am getting setCredentials is not applicable for BearerTokenCredentials .kindly help me out. Thanks in Advance!
Did your BearerTokenCredentials class extend ExchangeCredentials? "public class BearerTokenCredentials extends ExchangeCredentials" works well here.