4

我有一个配置了 Azure Active Directory 的 Azure Function App,但是当我从我的客户端调用时,我不断收到未经授权的响应。

我尝试了几种不同的场景,但没有任何效果。下面是我尝试的最后一段代码的片段。

                ///
                var @params2 = new NameValueCollection
                {
                    {"grant_type", "client_credentials"},
                    {"client_id", $"{ClientId}"},
                    {"client_secret", $"{ClientSecret}"},
                    {"username", userId},
                    {"resource", "https://management.azure.com/"}
                };
                var queryString2 = HttpUtility.ParseQueryString(string.Empty);
                queryString2.Add(@params2);
                var content = new FormUrlEncodedContent(new Dictionary<string, string>
                    {
                        {"grant_type", "client_credentials"},
                        {"client_id", ClientId},
                        {"client_secret", ClientSecret},
                        {"username", userId}
                    });
                var authorityUri2 = $"{string.Format(CultureInfo.InvariantCulture, AadInstance, Tenant).TrimEnd('/')}/oauth2/token";
                //var authorityUri2 = $"https://login.microsoftonline.com/{Tenant}/v2.0/.well-known/openid-configuration";
                var authUri2 = String.Format("{0}?{1}", authorityUri2, queryString2);
                var client2 = new HttpClient();
                var message = client2.PostAsync(authorityUri2, content).Result;
                //var message = client2.GetAsync(authorityUri2).Result;
                var response = message.Content.ReadAsStringAsync().Result;
                dynamic values=null;
                try
                {
                    values = JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
                }
                catch
                {
                    values = response;
                }

                var AuthToken2 = values["access_token"];
                client2.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AuthToken2);
                HttpResponseMessage response2 = await client2.GetAsync(AppBaseAddress.TrimEnd('/') + "/api/AADIntegration");

if (response.IsSuccessStatusCode)
                {
                    // Read the response and data-bind to the GridView to display To Do items.
                    string s = await response.Content.ReadAsStringAsync();
                    log.LogInformation($"Success while getting / api / AADIntegration : {s}");

                    return (ActionResult)new OkObjectResult(s);
                }
                else
                {
                    string failureDescription = await response.Content.ReadAsStringAsync();
                    log.LogInformation($"An error occurred while getting / api / AADIntegration : {response.ReasonPhrase}\n {failureDescription}");
                    return (ActionResult)new OkObjectResult(failureDescription);
                }

数据应从函数应用程序返回。

4

3 回答 3

3

对于client_credentials授权流程,您的代码似乎没什么不同。在这里,我为您提供了 azure 函数的确切示例。即插即用 :))

示例包含:

  1. 您将如何使用client_credentials流获得令牌
  2. 使用上述令牌从 Azure Active Directory 租户获取用户列表

访问令牌类:

public   class AccessTokenClass
    {
        public string token_type { get; set; }
        public string expires_in { get; set; }
        public string resource { get; set; }
        public string scope { get; set; }
        public string access_token { get; set; }

    }

参考添加:

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Net.Http;
using System.Collections.Generic;
using System.Net.Http.Headers;

Azure 函数体:

  public static class FunctionGetUserList
    {
        [FunctionName("FunctionGetUserList")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {

            try
            {
                log.LogInformation("C# HTTP trigger function processed a request.");


                //Token Request endpoint Just replace yourTennantId/Name
                string tokenUrl = $"https://login.microsoftonline.com/yourTennantId/Name.onmicrosoft.com/oauth2/token";
                var tokenRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);

                tokenRequest.Content = new FormUrlEncodedContent(new Dictionary<string, string>
                {
                    ["grant_type"] = "client_credentials",
                    ["client_id"] = "b603c7bead87-Your_client_id-e6921e61f925",
                    ["client_secret"] = "Vxf1SluKbgu4P-Your_client_Secret-F0Nf3wE5oGl/2XDSeZ=",
                    ["resource"] = "https://graph.microsoft.com"
                });

                dynamic json;
                AccessTokenClass results = new AccessTokenClass();
                HttpClient client = new HttpClient();

                var tokenResponse = await client.SendAsync(tokenRequest);

                json = await tokenResponse.Content.ReadAsStringAsync();
                results = JsonConvert.DeserializeObject<AccessTokenClass>(json);
                var accessToken = results.access_token;

                //Create Request To Server
                using (HttpClient clientNew = new HttpClient())
                {

                    //Pass Token on header
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    //Get Data from API
                    var requestToAzureEndpoint = await client.GetAsync("https://graph.microsoft.com/v1.0/users");

                    if (requestToAzureEndpoint.IsSuccessStatusCode)
                    {
                        var result_string = await requestToAzureEndpoint.Content.ReadAsStringAsync();
                        dynamic responseResults = JsonConvert.DeserializeObject<dynamic>(result_string);

                        return new OkObjectResult(responseResults);

                    }
                    else
                    {
                        var result_string = await requestToAzureEndpoint.Content.ReadAsStringAsync();
                        return new OkObjectResult(result_string);
                    }
                }
            }
            catch (Exception ex)
            {

                return new OkObjectResult(ex.Message);
            }

        }


    }

要记住的要点

对于 Azure Active DirectoryList users访问,请确保您具有以下权限:

  1. 用户阅读全部
  2. 权限类型:Application

你可以在这里查看。请参阅屏幕截图以更好地理解;添加权限后,请确保您已单击“为您的租户授予管理员同意”。

在此处输入图像描述

注意:这是使用 Azure 函数访问 Azure Active Directory 令牌的方法,然后是如何使用该令牌有效地访问特定 API 端点的资源。

于 2019-06-13T15:12:25.420 回答
1

资源的值不正确。

替换{"resource", "https://management.azure.com/"}{"resource", $"{ClientId}"}

于 2019-06-13T06:08:09.653 回答
1

您确定您已正确实施了吗?看起来您的一些参数对于客户端凭据流是错误的。请仔细检查您是否正确遵循客户端凭据流程。

此处记录了客户端凭据授予流程:https ://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow

但有关如何在您的函数应用中正常工作的更多信息,请参阅下面的博客以获取有关实现此功能的更多信息/帮助。 https://blogs.msdn.microsoft.com/ben/2018/11/07/client-app-calling-azure-function-with-aad/

于 2019-06-13T01:00:44.773 回答