예제 #1
0
파일: Connect.cs 프로젝트: pnp/contoso
        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));
        }
예제 #2
0
        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;
                    }
                }
            }
        }