You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
6.2 KiB
173 lines
6.2 KiB
using EasyBL;
|
|
using Microsoft.Identity.Client;
|
|
using Microsoft.Office365.OutlookServices;
|
|
using System;
|
|
using System.Linq;
|
|
using System.Security.Claims;
|
|
using System.Threading.Tasks;
|
|
using System.Web;
|
|
using WebApp.Outlook.TokenStorage;
|
|
|
|
namespace WebApp.Outlook.AuthProvider
|
|
{
|
|
public sealed class AuthProvider : IAuthProvider
|
|
{
|
|
// Properties used to get and manage an access token.
|
|
private readonly string redirectUri = ServiceHelper.RedirectUri;
|
|
|
|
private readonly string appId = ServiceHelper.AppId;
|
|
private readonly string appPassword = ServiceHelper.AppSecret;
|
|
private readonly string graphScopes = ServiceHelper.Scopes;
|
|
private readonly string graphScopes_Outlook = ServiceHelper.Scopes_Outlook;
|
|
|
|
private static readonly AuthProvider instance = new AuthProvider();
|
|
|
|
private AuthProvider()
|
|
{
|
|
}
|
|
|
|
public static AuthProvider Instance
|
|
{
|
|
get
|
|
{
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
public string AppPassword => appPassword;
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<string> GetAccessTokenAsync()
|
|
{
|
|
try
|
|
{
|
|
string accessToken = null;
|
|
// Load the app config from web.config
|
|
|
|
// Get the current user's ID
|
|
var signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
|
|
|
|
if (!string.IsNullOrEmpty(signedInUserID))
|
|
{
|
|
// Get the user's token cache
|
|
var httpContextWrapper = new HttpContextWrapper(HttpContext.Current);
|
|
var tokenCache = new SessionTokenCache(signedInUserID, httpContextWrapper).GetMsalCacheInstance();
|
|
|
|
var cca = new ConfidentialClientApplication(appId, redirectUri, new ClientCredential(AppPassword), tokenCache, null);
|
|
|
|
// Call AcquireTokenSilentAsync, which will return the cached access token if it
|
|
// has not expired. If it has expired, it will handle using the refresh token to
|
|
// get a new one.
|
|
var scopes = graphScopes.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
|
var result = await cca.AcquireTokenSilentAsync(scopes, cca.Users.First());
|
|
|
|
accessToken = result.AccessToken;
|
|
}
|
|
|
|
return accessToken;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<string> GetOutlookAccessTokenAsync()
|
|
{
|
|
try
|
|
{
|
|
string accessToken = null;
|
|
// Get the current user's ID
|
|
var signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
|
|
|
|
if (!string.IsNullOrEmpty(signedInUserID))
|
|
{
|
|
var httpContextWrapper = new HttpContextWrapper(HttpContext.Current);
|
|
var tokenCache = new SessionTokenCache(signedInUserID, httpContextWrapper).GetMsalCacheInstance();
|
|
var cca = new ConfidentialClientApplication(appId, redirectUri, new ClientCredential(AppPassword), tokenCache, null);
|
|
var scopes = graphScopes_Outlook.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
|
var result = await cca.AcquireTokenSilentAsync(scopes, cca.Users.First());
|
|
accessToken = result.AccessToken;
|
|
}
|
|
return accessToken;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<string> GetCacheOutlookAccessTokenAsync()
|
|
{
|
|
try
|
|
{
|
|
var accessToken = (string)HttpRuntimeCache.Get("outlookaccesstoken");
|
|
|
|
return accessToken;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<string> GetUserEmailAsync()
|
|
{
|
|
var client = new OutlookServicesClient(new Uri("https://outlook.office.com/api/v2.0"), AuthProvider.Instance.GetOutlookAccessTokenAsync);
|
|
try
|
|
{
|
|
var userDetail = (User)await client.Me.ExecuteAsync();
|
|
return userDetail.EmailAddress;
|
|
}
|
|
catch (MsalException ex)
|
|
{
|
|
return $"#ERROR#: Could not get user's email address. {ex.Message}";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 請求初始化
|
|
/// </summary>
|
|
/// <param name="email">todo: describe email parameter on GetRequestAsync</param>
|
|
/// <returns></returns>
|
|
public async Task<OutlookServicesClient> GetRequestAsync(string email = null)
|
|
{
|
|
var userEmail = email;
|
|
if (email == null)
|
|
{
|
|
userEmail = await GetUserEmailAsync();
|
|
}
|
|
Func<Task<string>> Getter = AuthProvider.Instance.GetOutlookAccessTokenAsync;
|
|
if (email != null)
|
|
{
|
|
Getter = AuthProvider.Instance.GetCacheOutlookAccessTokenAsync;
|
|
}
|
|
var client = new OutlookServicesClient(new Uri("https://outlook.office.com/api/v2.0"), Getter);
|
|
client.Context.SendingRequest2 += new EventHandler<Microsoft.OData.Client.SendingRequest2EventArgs>(
|
|
(sender, e) => InsertXAnchorMailboxHeader(e, userEmail));
|
|
return client;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 添加Header郵件地址
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <param name="email"></param>
|
|
public void InsertXAnchorMailboxHeader(Microsoft.OData.Client.SendingRequest2EventArgs e, string email)
|
|
{
|
|
e.RequestMessage.SetHeader("X-AnchorMailbox", email);
|
|
}
|
|
}
|
|
}
|