我正面临身份验证失败的问题,同时试图使用用于OAuth2.0的客户端凭据授予流连接两个IMAP协议。在这里,我一直在遵循微软在其逐步指南中建议的步骤,即"使用OAuth验证IMAP、POP或SMTP连接“。
我一直在使用这个github项目获取访问令牌,使用客户端凭据授予流:使用Java的MSAL客户端凭据授予
IMAP的Java代码
public static void connectIMAP(String userEmail, String accessToken){
String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
Properties props= new Properties();
props.put("mail.imap.ssl.enable", "true");
props.put("mail.imap.sasl.enable", "true");
props.put("mail.imap.port", "993");
props.put("mail.imap.auth.mechanisms", "XOAUTH2");
props.put("mail.imap.sasl.mechanisms", "XOAUTH2");
props.put("mail.imap.auth.login.disable", "true");
props.put("mail.imap.auth.plain.disable", "true");
props.setProperty("mail.imap.socketFactory.class", SSL_FACTORY);
props.setProperty("mail.imap.socketFactory.fallback", "false");
props.setProperty("mail.imap.socketFactory.port", "993");
props.setProperty("mail.imap.starttls.enable", "true");
props.put("mail.debug", "true");
props.put("mail.debug.auth", "true");
Session session = Session.getInstance(props);
session.setDebug(true);
try {
final Store store = session.getStore("imap");
store.connect("outlook.office365.com",userEmail, accessToken);
} catch (NoSuchProviderException e) { // session.getStore()
e.printStackTrace();
} catch (MessagingException e) { // store.connect()
e.printStackTrace();
}
}
下面是我在使用MSAL库执行客户端凭据授予流时使用的凭据
注意:我一直在使用默认的,以及我的Azure帐户的默认用户(Admin)。这样行吗?还是需要一个新的自定义Azure AD和单独的租户来执行客户凭证流?
下面的图像包含我在应用程序中应用的权限列表:图像,用于应用权限列表。
错误日志:
*** IMAP ***
DEBUG: JavaMail version 1.5.6
DEBUG: successfully loaded resource: /META-INF/javamail.default.providers
DEBUG: Tables of loaded providers
DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle]}
DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]}
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: setDebug: JavaMail version 1.5.6
DEBUG: getProvider() returning javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle]
DEBUG IMAP: mail.imap.fetchsize: 16384
DEBUG IMAP: mail.imap.ignorebodystructuresize: false
DEBUG IMAP: mail.imap.statuscachetimeout: 1000
DEBUG IMAP: mail.imap.appendbuffersize: -1
DEBUG IMAP: mail.imap.minidletime: 10
DEBUG IMAP: enable STARTTLS
DEBUG IMAP: enable SASL
DEBUG IMAP: SASL mechanisms allowed: XOAUTH2
DEBUG IMAP: closeFoldersOnStoreFailure
DEBUG IMAP: trying to connect to host "outlook.office365.com", port 993, isSSL true
* OK The Microsoft Exchange IMAP4 service is ready. [UABO......]
A0 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+
A0 OK CAPABILITY completed.
DEBUG IMAP: AUTH: PLAIN
DEBUG IMAP: AUTH: XOAUTH2
DEBUG IMAP: protocolConnect login, host=outlook.office365.com, user=ManishPrajapati@SampleOrg2022.onmicrosoft.com, password=<non-null>
DEBUG IMAP: SASL Mechanisms:
DEBUG IMAP: XOAUTH2
DEBUG IMAP:
DEBUG IMAP: SASL client XOAUTH2
DEBUG IMAP: SASL callback length: 2
DEBUG IMAP: SASL callback 0: javax.security.auth.callback.NameCallback@73f9ac
DEBUG IMAP: SASL callback 1: javax.security.auth.callback.PasswordCallback@1064425
A1 AUTHENTICATE XOAUTH2 dXNlcj.....
A1 NO AUTHENTICATE failed.
javax.mail.AuthenticationFailedException: AUTHENTICATE failed.
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:725)
at javax.mail.Service.connect(Service.java:366)
at javax.mail.Service.connect(Service.java:246)
at test.ClientCredentialGrantAndConnect.connectIMAP(ClientCredentialGrantAndConnect.java:166)
at test.ClientCredentialGrantAndConnect.main(ClientCredentialGrantAndConnect.java:45)
任何帮助解决这个问题都将是非常感谢的。
谢谢。
发布于 2022-08-13 10:30:48
我现在能够在exchange-online服务器上执行IMAP协议的OAuth2.0身份验证.我发现我的方法的问题是,由于缺乏使用Azure的经验,我使用了来自错误位置的一些参数。
按照一步一步的指导和设置新创建的应用程序的权限是可以的。但真正的问题在于本文末尾给出的查询,我们需要运行3条命令才能执行OAuth2.0
根据我的理解,以下是执行服务主体相关查询时使用的参数列表:
参数使用(以及查找它们的位置):
命令
我面对的困惑
发布于 2022-08-19 07:09:14
我能够使用客户端凭据授予生成的IMAP OAuth2访问令牌连接到邮箱。以下是详细信息:
Java代码(将下面代码中的客户端、机密、权威和电子邮件id替换为您的蓝色应用程序注册中的值)
//this method returns the token
public String getAccessTokenByClientCredentialGrant() {
String accessToken = null;
String clientId = "<client id from azure app registration>";
String secret = "<client secret from azure app registration>";
String authority = "https://login.microsoftonline.com/<tenant-id from azure>/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();
// 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);
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;
}
//This method connects to store using the access token
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;
}
//the main method which calls the above 2 methods.
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();
}
//write code to read email using javax.mail code
}
确保您的应用程序是在Azure应用程序注册下注册的,并在应用程序的"API权限“中授予了以下API权限(应用程序权限)。
Office 365在线交换
还要确保邮箱通过以下链接中的命令链接到Azure:https://learn.microsoft.com/en-us/graph/auth-limit-mailbox-access
Test-ApplicationAccessPolicy -Identity <email> -AppId <app id>
您还可以使用https://jwt.io/解码java代码生成的访问令牌,并验证权限是否正确。
验证office365电子邮件配置并确保启用IMAP :帮助可以在下面的链接中找到。https://www.limilabs.com/blog/office365-enable-imap-pop3-smtp
https://stackoverflow.com/questions/73039215
复制相似问题