public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation("C# HTTP trigger function processed a request."); #region Authentication // We're using Microsoft.Identity.Web var(authenticationStatus, authenticationResponse) = await req.HttpContext.AuthenticateAzureFunctionAsync(); if (!authenticationStatus) { return(authenticationResponse); } // Sample call to show how to get an access token, only for demo purposes //var token = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes: Constants.BasePermissionScopes, tokenAcquisitionOptions: new TokenAcquisitionOptions()); //log.LogInformation($"Graph access token: {token}"); #endregion #region Configure a subscription to handle change notifications // Get the current user information string tid = req.HttpContext.User.FindFirstValue("http://schemas.microsoft.com/identity/claims/tenantid"); string oid = req.HttpContext.User.FindFirstValue("http://schemas.microsoft.com/identity/claims/objectidentifier"); string upn = req.HttpContext.User.FindFirstValue("preferred_username"); await SubscriptionManagement.ManageSubscription(null, oid, tid, upn, _config, _msalAccountActivityStore, _graphServiceClient, _msalTokenCacheProvider); #endregion string responseMessage = "This HTTP triggered function executed successfully"; return(new OkObjectResult(responseMessage)); }
public async Task Run([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer, ILogger log) { log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}"); if (myTimer.IsPastDue) { log.LogInformation("Skipping past due invocation, waiting for next scheduled run"); return; } var subscriptions = await _msalAccountActivityStore.GetSubscriptionActivities(); foreach (var subscription in subscriptions) { // Get the most recently updated msal account information for this subscription var account = await _msalAccountActivityStore.GetMsalAccountActivityForSubscription(subscription.SubscriptionId); if (account != null) { // Configure the confidential client to get an access token for the needed resource var app = ConfidentialClientApplicationBuilder.Create(_config.GetValue <string>("AzureAd:ClientId")) .WithClientSecret(_config.GetValue <string>("AzureAd:ClientSecret")) .WithAuthority($"{_config.GetValue<string>("AzureAd:Instance")}{_config.GetValue<string>("AzureAd:TenantId")}") .Build(); // Initialize the MSAL cache for the specific account var msalCache = new BackgroundWorkerTokenCacheAdapter(account.AccountCacheKey, _serviceProvider.GetService <IDistributedCache>(), _serviceProvider.GetService <ILogger <MsalDistributedTokenCacheAdapter> >(), _serviceProvider.GetService <IOptions <MsalDistributedTokenCacheAdapterOptions> >()); await msalCache.InitializeAsync(app.UserTokenCache); // Prepare an MsalAccount instance representing the user we want to get a token for var hydratedAccount = new MsalAccount { HomeAccountId = new AccountId( account.AccountIdentifier, account.AccountObjectId, account.AccountTenantId) }; try { // Use the confidential MSAL client to get a token for the user we need to impersonate var result = await app.AcquireTokenSilent(Constants.BasePermissionScopes, hydratedAccount) .ExecuteAsync() .ConfigureAwait(false); // Configure the Graph SDK to use an auth provider that takes the token we've just requested var authenticationProvider = new DelegateAuthenticationProvider( (requestMessage) => { requestMessage.Headers.Authorization = new AuthenticationHeaderValue(CoreConstants.Headers.Bearer, result.AccessToken); return(Task.FromResult(0)); }); var graphClient = new GraphServiceClient(authenticationProvider); // Add/renew the subscriptions await SubscriptionManagement.ManageSubscription(subscription, account.AccountObjectId, account.AccountTenantId, account.UserPrincipalName, _config, _msalAccountActivityStore, graphClient, _msalTokenCacheProvider); } catch (MsalUiRequiredException ex) { /* * If MsalUiRequiredException is thrown for an account, it means that a user interaction is required * thus the background worker wont be able to acquire a token silently for it. * The user of that account will have to access the web app to perform this interaction. * Examples that could cause this: MFA requirement, token expired or revoked, token cache deleted, etc */ await _msalAccountActivityStore.HandleIntegratedTokenAcquisitionFailure(account); log.LogError($"Could not acquire token for account {account.UserPrincipalName}."); log.LogError($"Error: {ex.Message}"); } catch (Exception ex) { throw ex; } } } }