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;
///
///
///
public async Task 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;
}
}
///
///
///
public async Task 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;
}
}
///
///
///
public async Task GetCacheOutlookAccessTokenAsync()
{
try
{
var accessToken = (string)HttpRuntimeCache.Get("outlookaccesstoken");
return accessToken;
}
catch (Exception ex)
{
return null;
}
}
///
///
///
public async Task 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}";
}
}
///
/// 請求初始化
///
/// todo: describe email parameter on GetRequestAsync
///
public async Task GetRequestAsync(string email = null)
{
var userEmail = email;
if (email == null)
{
userEmail = await GetUserEmailAsync();
}
Func> 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(
(sender, e) => InsertXAnchorMailboxHeader(e, userEmail));
return client;
}
///
/// 添加Header郵件地址
///
///
///
///
public void InsertXAnchorMailboxHeader(Microsoft.OData.Client.SendingRequest2EventArgs e, string email)
{
e.RequestMessage.SetHeader("X-AnchorMailbox", email);
}
}
}