首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用OAuth2.0的客户端凭证流实现IMAP的身份验证失败

使用OAuth2.0的客户端凭证流实现IMAP的身份验证失败
EN

Stack Overflow用户
提问于 2022-07-19 14:55:45
回答 2查看 4.7K关注 0票数 4

我正面临身份验证失败的问题,同时试图使用用于OAuth2.0的客户端凭据授予流连接两个IMAP协议。在这里,我一直在遵循微软在其逐步指南中建议的步骤,即"使用OAuth验证IMAP、POP或SMTP连接“。

我一直在使用这个github项目获取访问令牌,使用客户端凭据授予流:使用Java的MSAL客户端凭据授予

IMAP的Java代码

代码语言:javascript
运行
复制
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和单独的租户来执行客户凭证流?

下面的图像包含我在应用程序中应用的权限列表:图像,用于应用权限列表。

错误日志:

代码语言:javascript
运行
复制
    *** 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)

任何帮助解决这个问题都将是非常感谢的。

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-08-13 10:30:48

我现在能够在exchange-online服务器上执行IMAP协议的OAuth2.0身份验证.我发现我的方法的问题是,由于缺乏使用Azure的经验,我使用了来自错误位置的一些参数。

按照一步一步的指导和设置新创建的应用程序的权限是可以的。但真正的问题在于本文末尾给出的查询,我们需要运行3条命令才能执行OAuth2.0

根据我的理解,以下是执行服务主体相关查询时使用的参数列表:

参数使用(以及查找它们的位置):

  • appId:来自企业和App的应用程序概述屏幕中的应用程序(客户端) ID
  • entObjId:仅在企业应用程序概述屏幕中找到的对象ID(企业应用程序)
  • orgId:Azure概述屏幕中的目录(租户) ID

命令

  1. 新服务主体-AppId appId -ServiceId entObjId -Organization orgId
  2. Get-服务主体-Organization entObjId \ fl
  3. -Identity "“-User entObjId -AccessRights FullAccess

我面对的困惑

  • 在中,会造成混乱,因为为了应用诸如" IMAP.AccessAsApp“这样的权限,互联网告诉您,”服务主体ID“可以在Azure AD ->企业应用程序-> (选择的应用程序) -> permissions -> IMAP.AccessAsApp ->中找到,因为使用从飞出菜单中的服务主体ID。
  • 在所有3个cmdlet中使用Enterprise是可以的
票数 2
EN

Stack Overflow用户

发布于 2022-08-19 07:09:14

我能够使用客户端凭据授予生成的IMAP OAuth2访问令牌连接到邮箱。以下是详细信息:

Java代码(将下面代码中的客户端、机密、权威和电子邮件id替换为您的蓝色应用程序注册中的值)

代码语言:javascript
运行
复制
//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在线交换

  • full_access_as_app
  • IMAP.AccessAsApp
  • Mail.Read
  • Mail.ReadWrite
  • Mail.Send

还要确保邮箱通过以下链接中的命令链接到Azure:https://learn.microsoft.com/en-us/graph/auth-limit-mailbox-access

代码语言:javascript
运行
复制
Test-ApplicationAccessPolicy -Identity <email> -AppId <app id>

您还可以使用https://jwt.io/解码java代码生成的访问令牌,并验证权限是否正确。

验证office365电子邮件配置并确保启用IMAP :帮助可以在下面的链接中找到。https://www.limilabs.com/blog/office365-enable-imap-pop3-smtp

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73039215

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档