Проверка подлинности Microsoft Outlook oAuth2.0
У нас есть демон-приложение, которое устанавливает IMAP-соединение для доступа к почтовому ящику пользователя. Ранее мы использовали простой метод аутентификации с использованием идентификатора электронной почты и пароля для установления соединения IMAP. Теперь, когда Microsoft заблокировала процесс аутентификации этого типа и представила oAuth2.0.
Мой вопрос здесь. Мне удалось установить IMAP-соединение с пользователем, который находится внутри моего арендатора. Но я не могу понять, как это можно сделать, если мне нужно получить доступ к почтовому ящику пользователя, который не входит в мой клиент, или мне нужно получить доступ к почтовому ящику любой личной учетной записи Outlook.
1 ответ
Я попытался воспроизвести то же самое в своей среде и получил следующие результаты:
Обратите внимание , что если вы хотите получить доступ к почтовому ящику пользователя, который не относится к вашему арендатору, или вам необходимо получить доступ к почтовому ящику любой личной учетной записи Outlook, вам необходимо зарегистрировать
Multi-Tenant Azure AD Application
как показано ниже:
Я создал мультитенантное приложение Azure AD и предоставил разрешения API :
Теперь я зарегистрировал субъектов-служб в Exchange с помощью следующих команд:**
Connect-ExchangeOnline -Organization TenantID
New-ServicePrincipal -AppId AppID -ServiceId ObjectID [-Organization OrganizationID]
Get-ServicePrincipal | fl
Я предоставил субъекту-службе доступ к одному почтовому ящику :
Add-MailboxPermission -Identity "USER@XXX.com" -User
ServicePrincipal_ID> -AccessRights FullAccess
Test-ApplicationAccessPolicy -Identity "USER@XXX.com" -AppId AppID
Я сгенерировал токен доступа через Postman для многопользовательского приложения , используя следующие параметры:
https://login.microsoftonline.com/common/oauth2/v2.0/token
client_id:5f3068f5-a920-4d6d-9742-XXXXXX
client_secret:ESJ8Q~ShJVdlY2MhKicyTEApGdtZh*******
scope:https://outlook.office365.com/.default
grant_type:client_credentials
Чтобы сделать то же самое в
JAVA
, вы можете сослаться на приведенный ниже пример кода пользователем3206771 в этой теме SO :
public String getAccessTokenByClientCredentialGrant() {
String accessToken = null;
String clientId = "CLIENTID";
String secret = "CLIENTSECRET";
String authority = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
String scope = "https://outlook.office365.com/.default";
log.info("Client ID : "+clientId);
log.info("Client Secret : "+secret);
log.info("Auth Server: "+authority);
log.info("Scope: "+scope);
try {
ConfidentialClientApplication app = ConfidentialClientApplication.builder(
clientId,
ClientCredentialFactory.createFromSecret(secret))
.authority(authority)
.build();
ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(
Collections.singleton(scope))
.build();
CompletableFuture<IAuthenticationResult> future = app.acquireToken(clientCredentialParam);
IAuthenticationResult result = future.get();
accessToken = result.accessToken();
} catch(Exception e) {
log.error("Exception in acquiring token: "+e.getMessage());
e.printStackTrace();
}
log.info("Access Token : "+accessToken);
return accessToken;
}
public Store connect(String userEmailId, String oauth2AccessToken) throws Exception {
String host = "outlook.office365.com";
String port = "993";
Store store = null;
String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
Properties props= new Properties();
props.put("mail.imaps.ssl.enable", "true");
props.put("mail.imaps.sasl.enable", "true");
props.put("mail.imaps.port", port);
props.put("mail.imaps.auth.mechanisms", "XOAUTH2");
props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put("mail.imaps.auth.login.disable", "true");
props.put("mail.imaps.auth.plain.disable", "true");
props.setProperty("mail.imaps.socketFactory.class", SSL_FACTORY);
props.setProperty("mail.imaps.socketFactory.fallback", "false");
props.setProperty("mail.imaps.socketFactory.port", port);
props.setProperty("mail.imaps.starttls.enable", "true");
props.put("mail.debug", "true");
props.put("mail.debug.auth", "true");
Session session = Session.getInstance(props);
session.setDebug(true);
store = session.getStore("imaps");
log.info("OAUTH2 IMAP trying to connect with system properties to Host:" + host + ", Port: "+ port
+ ", userEmailId: " + userEmailId+ ", AccessToken: " + oauth2AccessToken);
try {
store.connect(host, userEmailId, oauth2AccessToken);
log.info("IMAP connected with system properties to Host:" + host + ", Port: "+ port
+ ", userEmailId: " + userEmailId+ ", AccessToken: " + oauth2AccessToken);
if(store.isConnected()){
log.info("Connection Established using imap protocol successfully !");
}
} catch (Exception e) {
log.error("Store.Connect failed with the errror: "+e.getMessage());
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
log.error(exceptionAsString);
}
return store;
}
public void getEmailContents() throws Exception {
Store store = null;
String accessToken = getAccessTokenByClientCredentialGrant();
String emailId = "<email which needs to be read>";
try {
store = connect(emailId, accessToken );
} catch (Exception ex) {
log.error("Exception in connecting to email " + ex.getMessage());
ex.printStackTrace();
}
}