如何在混合 ASP.NET Core MVC(後端)和 Vuejs SPA(前端)中設定 Azure AD 驗證?
P粉242741921
P粉242741921 2024-01-08 10:44:05
0
1
584

我的應用程式是一種混合方法,使用 ASP.NET Core MVC 作為後端。我有各種控制器,我的前端使用它們從資料庫中提取數據,並在 MS Graph 上進行 API 呼叫。我使用以下 program.cs 檔案來在使用者首次登入網站時啟動身份驗證:

//authentication pipline
builder.Services.AddHttpContextAccessor();
var initialScopes = builder.Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApp(options =>
                {
                    builder.Configuration.Bind("AzureAd", options);
                    options.Events = new OpenIdConnectEvents
                    {
                        //Tap into this event to add a UserID Claim to a new HttpContext identity
                        OnTokenValidated = context =>
                        {
                            //This query returns the UserID from the DB by sending the email address in the claim from Azure AD
                            string query = "select dbo.A2F_0013_ReturnUserIDForEmail(@Email) as UserID";
                            string connectionString = builder.Configuration.GetValue<string>("ConnectionStrings:DBContext");
                            string signInEmailAddress = context.Principal.FindFirst   Value("preferred_username");

                            using (var connection = new SqlConnection(connectionString))
                            {
                                var queryResult = connection.QueryFirst(query, new { Email = signInEmailAddress });

                                var claims = new List<Claim>
                                {
                                    new Claim("UserID", queryResult.UserID.ToString())
                                };

                                var appIdentity = new ClaimsIdentity(claims);

                                context.Principal.AddIdentity(appIdentity);
                            }

                            return Task.CompletedTask;
                        },
                    };
                }).EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
                        .AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
                        .AddInMemoryTokenCaches();

//Add Transient Services
builder.Services.AddTransient<IOneDrive, OneDrive>();

builder.Services.AddControllers(options =>
{
    var policy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
    options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();

builder.Services.AddRazorPages().AddRazorPagesOptions(options =>
{
    options.Conventions.AllowAnonymousToFolder("/Login");
    options.Conventions.AuthorizeFolder("/");
    options.Conventions.AuthorizeFolder("/files");
}).AddMicrosoftIdentityUI();

// Add the UI support to handle claims challenges
builder.Services.AddServerSideBlazor()
   .AddMicrosoftIdentityConsentHandler();
builder.Services.AddRequiredScopeAuthorization();

在 Azure AD 入口網站中,我的應用程式註冊為 Web 應用程式。因此,當使用者最初造訪網站時,他們會被重新導向至 https://login.microsoftonline.com/blahblah 以開始登入程序。這是由 Azure AD 身分識別平台自動執行的。然後,一旦登入發生,它們就會被重定向到載入 VueJS spa 的本機 (localhost:43862)。我的 spa 使用各種 axios 請求到控制器,它們提取數據,vue 路由器加載組件。然而,我的問題是用戶需要重新登錄,因為 cookie 已過期或他們在另一個選項卡中登出。過期會話發出的下一個 axios 請求不會將使用者重新導向到 Azure 登入畫面,而是導致 CORS 錯誤。因此,我需要讓我的axios 請求強制頁面重定向到Azure AD 登入畫面(這可能是最糟糕的想法,因為CORS 策略會導致錯誤),或者讓它返回到localhost/login 的重定向,這是我自己的自訂登入畫面使用Azure AD 登入按鈕,不應影響CORS。那麼如何攔截此 Azure AD 重定向到 Azure AD 登入並替換為我自己的?

我還嘗試返回 401 錯誤代碼,以便我可以在 axios 請求中檢查該錯誤代碼,但無濟於事,它什麼都不做。如果我在那裡放置一個斷點,它確實會命中此代碼,但不會更改響應的狀態代碼,我仍然得到 302。我的程式碼是嘗試新增到事件中:

OnRedirectToIdentityProvider = context =>
                    {
                        context.Response.StatusCode = 401;
                        return Task.CompletedTask;
                    }

我的其他想法是也許我應該設定 CORS 策略以允許從 login.microsoft.com 進行重定向?還是這是不好的做法?

P粉242741921
P粉242741921

全部回覆(1)
P粉501007768

我可以回答你的部分問題...首先,對於我們受Azure AD 保護的API 應用程序,API 應該做的是驗證請求是否在請求標頭中包含正確的訪問令牌,如果是,給出回應,如果沒有,則給出401 或403 之類的錯誤。普通的 API 應用程式不應該有 UI 來讓使用者登入。無論如何,如果你想在 MVC 專案中公開 API,這是可以的,但是對於API 本身,它不應該有 UI。

讓我們看看下面的範例,我有一個 .net 6 Web api 項目,這是我的 program.cs

using Microsoft.Identity.Web;

var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration);
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();

並且需要在appsetting.json中進行設定。

"AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "ClientId": "azure_ad_client_id",
    "ClientSecret": "client_secret",
    "Domain": "tenant_id",
    "TenantId": "tenant_id",
    //"Audience": "api://azure_ad_client_id_which exposed_api" // here I used the same azure ad app to expose API, so I can comment this property
  },

這是控制器:

[ApiController]
    [Route("[controller]")]
    [Authorize]
    public class WeatherForecastController : ControllerBase
    {
        [RequiredScope("Tiny.Read")]
        [HttpGet]
        public string Get()
        {
            return "world";
        }
    }

我有一個 Azure AD 應用程序,並且公開瞭如下 API:

我還為同一個 Azure AD 應用程式新增了此 API。

那我們來做個測試吧。當我直接呼叫這個API時,我會得到401錯誤:

如果我在請求中使用了過期的令牌,我也會收到 401 錯誤:

但是如果我使用了正確的令牌(轉到https://jwt.io 來解碼令牌,我們應該看到它包含正確的範圍,對我來說它的"scp": "Tiny.Read",),我會得到回應:

至此,API部分已經完成。讓我們看看客戶端 SPA。對於 SPA,您應該整合 MSAL,以便您可以讓您的使用者透過 Azure AD 登錄,並產生用於呼叫 MS graph API 或您自己的 API 的存取權杖。產生存取令牌的程式碼應該相同,但您應該為不同的API設定不同的範圍。在我的場景中,我的 API 需要一個範圍 Tiny.Read,那麼我應該在我的客戶端應用程式中設定。

這是在react中產生存取令牌的螢幕截圖。您需要在程式碼中設定範圍。

現在您已經有了產生存取權杖的方法,您已經知道了 API url。然後你可以發送請求呼叫api,使用AJAX,使用fetch,或其他什麼,發送http請求就可以了。並且在呼叫api部分,還需要處理回應。如果回應代碼是 401,那麼您需要執行一些邏輯,可能會重新導向到登入頁面。你說你在這裡遇到了麻煩,你遇到了 CORS 問題。這部分我無法回答。我認為這取決於您如何重定向到 Azure AD 登入頁面。恐怕你可以看看 此範例,了解如何登入使用者和呼叫圖形 api。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板