Aplikasi saya ialah pendekatan hibrid menggunakan ASP.NET Core MVC sebagai hujung belakang. Saya mempunyai pelbagai pengawal yang digunakan bahagian hadapan saya untuk menarik data daripada pangkalan data dan membuat panggilan API pada MS Graph. Saya menggunakan fail program.cs berikut untuk memulakan pengesahan apabila pengguna log masuk ke tapak web buat kali pertama:
//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();
Dalam portal Azure AD, permohonan saya didaftarkan sebagai aplikasi web. Oleh itu, apabila pengguna mula-mula mengakses tapak web, mereka dialihkan ke https://login.microsoftonline.com/blahblah untuk memulakan proses log masuk. Ini dilakukan secara automatik oleh platform identiti Azure AD. Kemudian, setelah log masuk berlaku, mereka dialihkan ke localhost (localhost:43862) di mana VueJS spa dimuatkan. Spa saya menggunakan pelbagai permintaan aksios kepada pengawal, yang menarik data, dan penghala vue untuk memuatkan komponen. Walau bagaimanapun, masalah saya ialah pengguna perlu log masuk semula kerana kuki telah tamat tempoh atau mereka log keluar dalam tab lain. Permintaan axios seterusnya daripada sesi tamat tempoh tidak mengubah hala pengguna ke skrin log masuk Azure tetapi mengakibatkan ralat CORS. Oleh itu, saya perlu meminta axios saya memaksa halaman untuk mengubah hala ke skrin log masuk Azure AD (yang mungkin merupakan idea yang paling teruk kerana dasar CORS akan menyebabkan ralat), atau minta ia ubah hala semula ke localhost/log masuk, itulah yang saya Anda skrin log masuk tersuai sendiri menggunakan butang log masuk Azure AD seharusnya tidak menjejaskan CORS. Jadi bagaimana saya memintas ubah hala Azure AD ini ke log masuk Azure AD dan menggantikannya dengan saya sendiri?
Saya juga cuba mengembalikan kod ralat 401 supaya saya boleh menyemaknya dalam permintaan axios, tetapi tidak berjaya, ia tidak melakukan apa-apa. Jika saya meletakkan titik putus di sana, ia memukul kod ini, tetapi ia tidak mengubah kod status respons, saya masih mendapat 302. Kod saya cuba ditambahkan pada acara:
OnRedirectToIdentityProvider = context => { context.Response.StatusCode = 401; return Task.CompletedTask; }
Pemikiran saya yang lain mungkin saya perlu menyediakan dasar CORS untuk membenarkan ubah hala daripada login.microsoft.com? Atau adakah ini amalan buruk?
Saya boleh menjawab sebahagian daripada soalan anda... Pertama, untuk aplikasi API dilindungi Azure AD kami, perkara yang perlu dilakukan oleh API ialah mengesahkan bahawa permintaan itu mengandungi token akses yang betul dalam pengepala permintaan, dan jika ya, berikan respons , jika tidak, ralat seperti 401 atau 403 diberikan. Aplikasi API biasa tidak sepatutnya mempunyai UI untuk log masuk pengguna. Bagaimanapun, jika anda ingin mendedahkan API dalam projek MVC, itu OK, tetapi untuk API itu sendiri, ia tidak sepatutnya mempunyai UI.
Mari lihat contoh di bawah, saya mempunyai projek api Web .net 6 dan ini adalah
program.cs
saya:Dan perlu dikonfigurasikan dalam appsetting.json.
Ini adalah pengawal:
Saya mempunyai aplikasi Azure AD dan mendedahkan API berikut:
Saya juga menambahkan API ini untuk apl Azure AD yang sama.
Kemudian mari buat ujian. Apabila saya memanggil API ini secara langsung, saya mendapat ralat 401:
Saya juga mendapat ralat 401 jika saya menggunakan token tamat tempoh dalam permintaan:
Tetapi jika saya menggunakan token yang betul (pergi ke https://jwt.io untuk menyahkod token yang sepatutnya kita lihat ia mengandungi skop yang betul, bagi saya itu
"scp": "Tiny.Read",
) dan saya mendapat respons :Pada ketika ini, bahagian API telah siap. Jom tengok client SPA. Untuk SPA anda harus menyepadukan
MSAL
,以便您可以让您的用户通过 Azure AD 登录,并生成用于调用 MS graph API 或您自己的 API 的访问令牌。生成访问令牌的代码应该相同,但您应该为不同的API设置不同的范围
。在我的场景中,我的 API 需要一个范围Tiny.Read
maka saya harus menetapkannya dalam aplikasi pelanggan saya.Ini ialah tangkapan skrin menjana token akses dalam tindak balas. Anda perlu menetapkan skop dalam kod anda.
Sekarang anda mempunyai cara untuk menjana token akses, anda sudah mengetahui url API. Kemudian anda boleh menghantar permintaan untuk memanggil api, gunakan AJAX, gunakan fetch, atau apa sahaja, hantar sahaja permintaan http. Dan dalam bahagian memanggil api, respons juga perlu diproses. Jika kod respons ialah 401, maka anda perlu melakukan beberapa logik, mungkin mengubah hala ke halaman log masuk. Anda berkata anda menghadapi masalah di sini, bahawa anda menghadapi masalah CORS. Saya tidak dapat menjawab bahagian ini. Saya fikir ia bergantung pada cara anda mengubah hala ke halaman log masuk Azure AD. Saya takut anda boleh melihat contoh ini untuk memahami cara log masuk pengguna dan memanggil api graf.