c# - 使用 Oauth2 进行身份验证以在 C# MVC Web 应用程序中读取 IMAP
问题描述
我想使用 IMAP 阅读来自已登录用户的电子邮件。
我创建了一个控制台应用程序用于测试目的并确保 azure 中的应用注册设置正确。
控制台应用程序按预期工作。
- 将显示一个 Microsoft 登录窗口,用户可以在其中输入其凭据。
- 接收到访问令牌并将其传递给 MailKit 以获取用户的电子邮件。
问题
当我尝试在 MVC .net 标准 Web 应用程序中使用 MailKit 进行身份验证时,我收到一条错误消息,提示“身份验证失败”。
但是,当我复制使用控制台应用程序获得的访问令牌并在我的 Web 应用程序中使用它时,我没有收到授权错误,并且可以成功验证和阅读电子邮件。(我使用访问令牌作为第二个参数
var oauth2 = new SaslMechanismOAuth2("[Email here]", oathToken.access_token);
)。
我使用DotNetOpenAuth来显示 Microsoft 登录窗口。(我找不到 Web 应用程序的 MSAL 示例,我不必将 OWIN 添加为中间件。我只想进行身份验证以获取电子邮件,而不是应用程序范围的身份验证和授权。)
控制台应用程序代码(有效):
// Using Microsoft.Identity.Client 4.22.0
// Configure the MSAL client to get tokens
var pcaOptions = new PublicClientApplicationOptions
{
ClientId = "[client-id here]",
AadAuthorityAudience = AadAuthorityAudience.AzureAdMultipleOrgs,
};
var pca = PublicClientApplicationBuilder
.CreateWithApplicationOptions(pcaOptions).Build();
var scopes = new string[] {
"email",
"offline_access",
"https://outlook.office365.com/IMAP.AccessAsUser.All" };
// Make the interactive token request
var authResult = await pca.AcquireTokenInteractive(scopes).ExecuteAsync();
var oauth2 = new SaslMechanismOAuth2(authResult.Account.Username, authResult.AccessToken);
using (var client = new ImapClient())
{
await client.ConnectAsync("outlook.office365.com", 993, SecureSocketOptions.Auto);
await client.AuthenticateAsync(oauth2);
var inbox = client.Inbox;
inbox.Open(FolderAccess.ReadOnly);
for (int i = 0; i < inbox.Count; i++)
{
var message = inbox.GetMessage(i);
Console.WriteLine("Subject: {0}", message.Subject);
}
await client.DisconnectAsync(true);
}
网络应用程序(这不起作用):
public ActionResult Index()
{
string clientID = "[client-id here]";
string clientSecret = "[client-secret here]";
string redirectUri = "[redirectUri here]";
AuthorizationServerDescription server = new AuthorizationServerDescription
{
AuthorizationEndpoint = new Uri("https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize"),
TokenEndpoint = new Uri("https://login.microsoftonline.com/organizations/oauth2/v2.0/token"),
ProtocolVersion = ProtocolVersion.V20,
};
List<string> scopes = new List<string>
{
"email",
"offline_access",
"https://outlook.office365.com/IMAP.AccessAsUser.All"
};
WebServerClient consumer = new WebServerClient(server, clientID, clientSecret);
OutgoingWebResponse response = consumer.PrepareRequestUserAuthorization(
scopes, new Uri(redirectUri));
return response.AsActionResultMvc5();
}
public async Task<ActionResult> Authorized(string code, string state, string session_state)
{
List<string> scopes = new List<string>
{
"IMAP.AccessAsUser.All",
"User.Read",
"offline_access"
};
HttpClient httpClient = new HttpClient();
var values = new Dictionary<string, string>
{
{ "Host", "https://login.microsoftonline.com" },
{ "Content-Type", "application/x-www-form-urlencoded" },
{ "client_id", "[client-id here]" },
{ "scope", string.Join(" ",scopes) },
{ "code", code },
{ "redirect_uri", [redirectUri here] },
{ "grant_type", "authorization_code" },
{ "client_secret", "[client-secret here]" },
{ "state", state },
};
var content = new FormUrlEncodedContent(values);
var response = await httpClient.PostAsync("https://login.microsoftonline.com/organizations/oauth2/v2.0/token", content);
var jsonString = await response.Content.ReadAsStringAsync();
var oathToken = JsonConvert.DeserializeObject<OathToken>(jsonString);
var oauth2 = new SaslMechanismOAuth2("[Email here]", oathToken.access_token);
var stringBuilder = new StringBuilder();
using (var client = new ImapClient())
{
try
{
await client.ConnectAsync("outlook.office365.com", 993, SecureSocketOptions.Auto);
await client.AuthenticateAsync(oauth2);
var inbox = client.Inbox;
inbox.Open(FolderAccess.ReadOnly);
for (int i = 0; i < inbox.Count; i++)
{
var message = inbox.GetMessage(i);
stringBuilder.AppendLine($"Subject: {message.Subject}");
}
await client.DisconnectAsync(true);
return Content(stringBuilder.ToString());
}
catch (Exception e)
{
return Content(e.Message);
}
}
}
问题发生在这一行:await client.AuthenticateAsync(oauth2);
我收到一条错误消息,提示“身份验证失败”但是,当在 Web 应用程序中使用控制台应用程序的访问令牌时,我没有收到此错误,并且可以成功地在 Web 中进行身份验证和阅读电子邮件-应用。
谁能指出我正确的方向?
谢谢。
解决方案
推荐阅读
- jquery - 单击侦听器事件不会在 SVG 元素上触发(字体真棒图标)
- python - 如何在 Python 3.7.2 中使用命令“t.print”?
- java - Spring 5 和响应式编程
- powershell - CCM 日志读取最后几行日志文本
- vue.js - 防止对象在分配给组件属性时被转换为反应性对象
- android - 未授予 Android WRITE_EXTERNAL_STORAGE
- mysql - 如何在mysql中选择按日期DESC排序并按字段分组的最后两条记录?
- java - 为什么 Google Appengine 的图像 API 提供的图像方向不正确?
- python-3.x - 如何找到唯一对的最大值?
- c++ - 从函数返回指针