我正在使用 OpenId 从我的 Web 应用程序中的 Azure AD 进行身份验证,并尝试在我的 Web API 中进行授权。
我可以从 Web App (.NET 4.8) 访问我的 WebAPI (.NET Framework 6.0),没有任何问题。然而,当尝试在我的 WebAPI 控制器中使用授权标签时,我热衷于收到内部错误。
Web 应用程序 - Startup.cs
private static string _clientId = Properties.Resource.ClientId;
private static string _aadInstance = EnsureTrailingSlash(Properties.Resource.AADInstance);
private static string _tenantId = Properties.Resource.TenantId;
private static string _RedirectUri = Properties.Resource.RedirectUri;
private static string _clientSecret = Properties.Resource.ClientSecret;
private string _authority = _aadInstance + _tenantId;
private string _scope = Properties.Resource.Scope;
public void ConfigureAuth(IAppBuilder app)
{
//Set the authentication to cookies
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
//Create a new cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions());
//Set the openId connect authentication settings and call the WebPortal app in Azure
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = _clientId,
Authority = _authority,
RedirectUri = _RedirectUri,
PostLogoutRedirectUri = _RedirectUri,
ClientSecret = _clientSecret,
UseTokenLifetime = false,
SaveTokens = true,
RedeemCode = true,
Scope = _scope,
ResponseType = OpenIdConnectResponseType.Code,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
AuthenticationFailed = (context) =>
{
return Task.FromResult(0);
}
}
});
app.UseStageMarker(PipelineStage.Authenticate);
}
Web Api 代码 - Program.cs
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(options =>{options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;options.DefaultChallengeScheme = "oidc";}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme).AddOpenIdConnect(openIdOptions =>{openIdOptions.ClientId = "7221484D-1550-4087-840D-7170BC566B93";openIdOptions.Authority = "https://login.microsoftonline.com/4c2ecc82-c268-467a-bb63-0e92247d5fab";openIdOptions.ResponseType = OpenIdConnectResponseType.Code;openIdOptions.GetClaimsFromUserInfoEndpoint = false;openIdOptions.CallbackPath = "/signin-oidc";openIdOptions.SaveTokens = true;openIdOptions.ClientSecret = "****";});
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbucklebuilder.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.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Web Api 控制器 - 授权不起作用的地方
[Authorize]
[HttpGet("GetRoleInfo")]
public async Task<IActionResult> GetRoleInfo()
{
try
{
string userId = GetAzureUserId();
List<Role> roles = await GetRoles();
List<AdminRole> adminRoles = await GetAdminRoles();
List<BusinessUser> businessUsers = await GetBusinessUsers();
List<ApplicationUser> applicationUsers = await GetApplicationUsers();
List<Application> applications = await GetApplications();
var roleAdminModel = PopulateRoleInfo(userId, roles, adminRoles,
businessUsers,applicationUsers, applications);
return Ok(roleAdminModel);
}
catch (Exception ex)
{
return StatusCode((int)HttpStatusCode.InternalServerError, ex.Message);
}
}
我遇到错误
网络应用程序.NET 4.8。
我无法获取 OpenId 来获取 Azure AD 中的自定义范围,因此无法获取 Web API 进行授权。因此我现在使用 Microsoft.Identity.Client。您可以从 Nuget 包管理器获取此信息。
我的 Login.cs 页面中有以下代码。
代码流程login.cs页面 -> AuthenticateProcess -> PopulateRoleInfo -> GetHttpResponseType -> Web API
using Microsoft.Identity.Client;
public partial class Login : Page
{
private void AuthenticateProcess()
{
//Get the access token from Azure
Task<string> accessToken = Task.Run(async () => await GetAccessToken());
if (accessToken != null && accessToken.Result != null && accessToken.Result.Count() > 0)
{
Task<List<RoleAdminRoleModel>> roleAdminRoleModel = Task.Run(() => PopulateRoleInfo(accessToken.Result));
}
}
private async Task<string> GetAccessToken()
{
string accessToken = string.Empty;
try
{
string[] Graphscopes = new string[] { Resource.Scope };
var clientApp = PublicClientApplicationBuilder.Create(Resource.ClientId)
.WithAuthority($"{Resource.AADInstance}{Resource.TenantId}")
.WithDefaultRedirectUri()
.Build();
var azureAccounts = await clientApp.GetAccountsAsync();
var azureAccount = azureAccounts.FirstOrDefault();
var authResult = await clientApp
.AcquireTokenInteractive(Graphscopes)?
.WithAccount(azureAccount)?
.ExecuteAsync();
if (authResult != null
{
accessToken = authResult.AccessToken;
}
}
catch (Exception ex)
{
Response.Redirect(Resource.ErrorPage + " " + ex.Message);
}
return accessToken;
}
private async Task<List<RoleAdminRoleModel>> PopulateRoleInfo(string accessToken)
{
var webPortalAPIAccess = new WebPortalAPIAccess(accessToken);
List<RoleAdminRoleModel> roleAdminRoleModel = await webPortalAPIAccess.GetRoleInfo();
return roleAdminRoleModel;
}
public async Task<List<RoleAdminRoleModel>> GetRoleInfo()
{
var roleAdminRoleModel = await GetHttpResponseType<List<RoleAdminRoleModel>>($"{_webPortalPublicAPIPath}/api/WebPortal/GetRoleInfo");
return roleAdminRoleModel;
}
private async Task<T> GetHttpResponseType<T>(string url)
{
var options = new System.Text.Json.JsonSerializerOptions { PropertyNameCaseInsensitive = true };
var stream = await _httpClient.GetStreamAsync(url);
var instance = await DeserializeAsync<T>(stream, options);
return instance;
}
}
然后像这样设置 Web API -> Program.cs。
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph"))
.AddInMemoryTokenCaches();
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();
现在设置 Web API 控制器。请注意授权和范围标签。控制器顶部是按键。范围标记是指 Azure AD 中的自定义范围设置。您可以出于测试目的手动输入此值,而不是从 appsettings.json 文件引用范围(“MicrosoftGraph:Scopes”)。
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System.Net;
using Models;
using System.Data;
using Application = Models.Application;
using RolePermission = Models.RolePermission;
using Permission = Models.Permission;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Identity.Web;
[Authorize]
[AuthorizeForScopes(ScopeKeySection = "MicrosoftGraph:Scopes")]
[ApiController]
[Route("api/[controller]")]
public class WebPortalController : Controller
{
[HttpGet("GetRoleInfo")]
public async Task<IActionResult> GetRoleInfo()
{
try
{
string userId = GetAzureUserId();
List<Role> roles = await GetRoles();
List<AdminRole> adminRoles = await GetAdminRoles();
List<BusinessUser> businessUsers = await GetBusinessUsers();
List<ApplicationUser> applicationUsers = await GetApplicationUsers();
List<Application> applications = await GetApplications();
var roleAdminModel = PopulateRoleInfo(userId, roles, adminRoles, businessUsers, applicationUsers, applications);
return Ok(roleAdminModel);
}
catch (Exception ex)
{
return StatusCode((int)HttpStatusCode.InternalServerError, ex.Message);
}
}
}