簡體   English   中英

Web應用程序和API AzureAD身份驗證流程ASP.NET Core

[英]Web Application and API AzureAD authentication flow ASP.NET Core

我目前對如何實現身份驗證/授權流程感到困惑。

我正在開發兩個應用程序,一個是前端/ Web應用程序,另一個是后端/ API,都使用ASP.NET Core。 目標是使用AzureAD並使用域中的用戶/組。 我已經在兩個應用程序上都實現了身份驗證,並且能夠基於登錄狀態登錄和限制內容。

作為參考,我從微軟開發人員那里舉了這個例子。 我應該做的正是這件事。 有一個WebApp和API。 使用的認證流程是授權碼流程 首先,用戶需要登錄,然后,當需要從API請求一些數據時,將請求訪問令牌。

問題1:這是正確的身份驗證流程嗎? 對我來說,這似乎是雙重身份驗證,因為首先我在前端對自己進行身份驗證,當Webapp需要一些數據時,我需要在后端再次進行身份驗證。 使用相同的Azure AD租戶,那么您對此有何看法?

接下來的一點看起來非常“丑陋”是獲取一些數據的過程。 在該示例中,當首先請求某些數據時,將請求令牌,然后請求數據。 但是我認為有很多樣板。 對於所有待辦事項中的一個請求,僅需以下示例代碼。

// GET: /<controller>/
public async Task<IActionResult> Index()
{
    AuthenticationResult result = null;
    List<TodoItem> itemList = new List<TodoItem>();

    try
    {
        // Because we signed-in already in the WebApp, the userObjectId is know
        string userObjectID = (User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier"))?.Value;

        // Using ADAL.Net, get a bearer token to access the TodoListService
        AuthenticationContext authContext = new AuthenticationContext(AzureAdOptions.Settings.Authority, new NaiveSessionCache(userObjectID, HttpContext.Session));
        ClientCredential credential = new ClientCredential(AzureAdOptions.Settings.ClientId, AzureAdOptions.Settings.ClientSecret);
        result = await authContext.AcquireTokenSilentAsync(AzureAdOptions.Settings.TodoListResourceId, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));

        // Retrieve the user's To Do List.
        HttpClient client = new HttpClient();
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, AzureAdOptions.Settings.TodoListBaseAddress + "/api/todolist");
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
        HttpResponseMessage response = await client.SendAsync(request);

        // Return the To Do List in the view.
        if (response.IsSuccessStatusCode)
        {
            List<Dictionary<String, String>> responseElements = new List<Dictionary<String, String>>();
            JsonSerializerSettings settings = new JsonSerializerSettings();
            String responseString = await response.Content.ReadAsStringAsync();
            responseElements = JsonConvert.DeserializeObject<List<Dictionary<String, String>>>(responseString, settings);
            foreach (Dictionary<String, String> responseElement in responseElements)
            {
                TodoItem newItem = new TodoItem();
                newItem.Title = responseElement["title"];
                newItem.Owner = responseElement["owner"];
                itemList.Add(newItem);
            }

            return View(itemList);
        }

        //
        // If the call failed with access denied, then drop the current access token from the cache, 
        //     and show the user an error indicating they might need to sign-in again.
        //
        if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
        {
            return ProcessUnauthorized(itemList, authContext);
        }
    }
    catch (Exception)
    {
        if (HttpContext.Request.Query["reauth"] == "True")
        {
            //
            // Send an OpenID Connect sign-in request to get a new set of tokens.
            // If the user still has a valid session with Azure AD, they will not be prompted for their credentials.
            // The OpenID Connect middleware will return to this controller after the sign-in response has been handled.
            //
            return new ChallengeResult(OpenIdConnectDefaults.AuthenticationScheme);
        }
        //
        // The user needs to re-authorize.  Show them a message to that effect.
        //
        TodoItem newItem = new TodoItem();
        newItem.Title = "(Sign-in required to view to do list.)";
        itemList.Add(newItem);
        ViewBag.ErrorMessage = "AuthorizationRequired";
        return View(itemList);
    }
    //
    // If the call failed for any other reason, show the user an error.
    //
    return View("Error");
}

問題2:如果Q1中的流程正確,是否存在“不太丑陋”的方法來訪問數據?

我找到了解決此問題的合適方法。

我只是在此示例中使用了多租戶saas指導的方法 ,它的工作原理就像魅力。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM