我一直在尝试使用以下Java代码获取用于oauth2身份验证的令牌,以便连接到邮件服务器:
public static String getAuthToken(String tenantId, String clientId, String client_secret) throws ClientProtocolException , IOException {
CloseableHttpClient client = HttpClients.createDefault();
HttpPost loginPost = new HttpPost("https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/token");
//String scopes = "https://outlook.office365.com/IMAP.AccessAsUser.All";
String scopes = "https://outlook.office365.com/.default"; // we need this scope when we have the grand_type as client credidentials
//String encodedBody = "client_id=" + clientId + "&scope=" + scopes + "&client_secret=" + client_secret+ "&username="+mailAddress+"&password=" + EMAIL_PASSWORD + "&grant_type=password";
String encodedBody = "client_id=" + clientId + "&scope=" + scopes + "&client_secret=" + client_secret+ "&username="+mailAddress+ "&grant_type=client_credentials";
loginPost.setEntity(new StringEntity(encodedBody, ContentType.APPLICATION_FORM_URLENCODED));
loginPost.addHeader(new BasicHeader("cache-control", "no-cache"));
CloseableHttpResponse loginResponse = client.execute(loginPost);
InputStream inputStream = loginResponse.getEntity().getContent();
byte[] response = readAllBytes(inputStream);
ObjectMapper objectMapper = new ObjectMapper();
JavaType type = objectMapper.constructType(
objectMapper.getTypeFactory().constructParametricType(Map.class, String.class, String.class));
Map<String, String> parsed = new ObjectMapper().readValue(response, type);
return parsed.get("access_token");
}
但是,如果我试图在请求正文中没有密码的情况下获取令牌(如果我像在注解行中那样添加密码,一切正常),我无法连接该令牌,并得到以下身份验证失败错误:Exception in thread "main" javax.mail.AuthenticationFailedException: AUTHENTICATE failed. at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:732) at javax.mail.Service.connect(Service.java:366) at yk.Auth.main(Auth.java:79)
我尝试过修改请求主体(更改/删除作用域等),但没有任何变化。
要获得有效令牌而不将密码作为请求的一部分发送,需要执行什么操作?
谢谢大家!
1条答案
按热度按时间pobjuy321#
这是一个通用的答案,可以由更了解MS Azure服务的人改进。
您可能需要用户授权的令牌才能访问IMAP服务器。因为您的OAuth2客户端(由clientId标识)不是IMAP服务器用户-使用client_credentials授权获得的令牌不能用于IMAP服务器。您注解掉的行使用密码授权(deprecated),并需要用户的密码。
我认为从OAuth2的Angular 来看,正确的方法是使用auth code flow,这样,用户(资源所有者角色)将其权限(由请求的作用域表示)委托给应用程序(OAuth2客户端角色),应用程序可以在IMAP服务器(资源服务器角色)上使用这些权限。
身份验证代码流需要用户交互-用户的浏览器被重定向到OAuth2身份验证终结点,用户获得身份验证并同意将请求的权限委派给应用程序。然后,浏览器被重定向到由应用程序处理的
redirect_uri
。该请求具有一个身份验证代码值,可以在OAuth2服务器的令牌终结点交换令牌。如果您的应用程序不与可以委托其IMAP服务器访问权限的用户交互,您可能需要使用密码授权,或者弄清楚如何使您的应用程序(由其
client_id
标识)成为IMAP用户并使用client_credentials授权(就像您现在所做的那样)。